procmail 在文件名中保存带有接收日期的附件

Fax*_*Max 2 email procmail

每天我们都会收到一封来自例如 foo@example.tld 的带有附件的电子邮件,文件名是例如 report.xlsx

如何使用收到的日期保存文件?例如20180131_report.xlsx,我如何过滤主题或发件人?

我的~/.procmailrc

:0
*^content-Type:
{
    :fw
    | ripmime --overwrite --no-nameless -i - -d /dir/to/save/attachment
}
Run Code Online (Sandbox Code Playgroud)

tri*_*eee 7

如果您的 Procmail 或接收 MTA 被配置为在正确的邮件之前放置From_一行,则此伪标头通常已包含日期。您需要解析它,这是一个拖累,所以除非这是一个您确实需要优化性能的系统(在这种情况下每秒有数百个匹配?),绝对最简单的解决方案是调用date +%Y%m%d.

要匹配两个不相关的标题中的任何一个,只需将它们放在一个正则表达式中|

:0
* ^Content-type:
* ^From:(.*\<)?foo@example\.tld|^Subject: Your daily report
| ripmime --overwrite --no-nameless -i - -d /dir/to/save/attachment/$(date +%Y%m%d)_report.xslx
Run Code Online (Sandbox Code Playgroud)

(此处有错误;请参阅下面的更新。)

这些fw标志在这种情况下没有意义,所以我把它们去掉了(实际上我也不确定这个Content-type:条件是否有意义;现在大多数消息都会有它)。

如果您想要组合更复杂的条件,您可以使用逻辑中称为 de Morgan 定律的基本原理。Procmail 中没有直接的语法来表示“这个条件或那个条件”,但是您可以将其重构为“不是((不是这个条件)和(不是那个条件))”。

:0
* ! this condition
* ! that condition
{ } # nothing happens here
:0E # else
{ LOG="at least one of them matched
" }
Run Code Online (Sandbox Code Playgroud)

或者干脆使用评分;

:0
* 1^0 this condition
* 1^0 that conditon
{ LOG="at least one of them matched
" }
Run Code Online (Sandbox Code Playgroud)

更新:

看起来ripmime实际上并不支持(提取或)命名单个附件。最简单的解决方案可能是cron在午夜之前重命名最新到达的工作(或者如果您知道它何时到达,则在您期望的最晚时间之后):

 55 23 * * * cd /dir/to/save/attachment && mv report.xslx "$(date +%%Y%%m%%d)"_report.xslx
Run Code Online (Sandbox Code Playgroud)

请注意如何(特别地)您需要将cron命令中的任何百分号加倍!您显然会恢复上面的 Procmail 配方,只需将ripmime保存到/dir/to/save/attachment

或者,我会在它到达后立即重命名附件,也许同时也会大大收紧条件。以下内容包括对传送附件的消息究竟是如何编码的大量猜测——它可以在许多不同的内容类型、MIME 结构、MIME 标头约定等之间进行选择,因此如果没有它,它可能无法工作一些调整。

:0
* ^From:(.*\<)?foo@example\.tld
* ^Subject: Your daily report
* HB ?? ^Content-type: application/(octet-stream|vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet|vnd\.ms-here-be-dragons-xslx); filename="?report.xslx
| ( cd dir/to/save/attachment; \
    ripmime --overwrite --no-nameless -i - -d . && \
    mv report.xslx $(date +%Y%m%d)"_report.xslx )
Run Code Online (Sandbox Code Playgroud)

Content-type:标题可能不包含文件名; 它可以(并且现在应该)在中指定,Content-Disposition:但许多发件人将它放在两个地方以实现向后兼容性。文件名应该正确地采用 RFC2231 编码,这意味着可以填充许多可选字段,我已经方便地假设它们将为空,就像 ASCII 文件名是镇上唯一的游戏一样。

还要注意我现在如何要求发件人主题匹配。该HB ??说(不准确),以查找匹配无论是在主邮件标题,或在身体的某个地方。正确地说,在后一种情况下,匹配应该在 MIME 正文部分的标头中,但 Procmail 没有简单的方法来指定这一点。