Email

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

  • February 3, 2018

每天我們都會收到一封來自例如 foo@example.tld 的帶有附件的電子郵件,文件名是例如report.xlsx

如何使用接收日期保存文件?例如20180131_report.xlsx,我如何過濾主題或發件人?

我的**~/.procmailrc**:

:0
*^content-Type:
{
   :fw
   | ripmime --overwrite --no-nameless -i - -d /dir/to/save/attachment
}

如果您的 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

(此處有錯誤;請參閱下面的更新。)

這些fw標誌在這種情況下沒有意義,所以我把它們拿出來(實際上我也不確定這個Content-type:條件是否有意義;這些天大多數消息都會有它)。

如果您想要組合更複雜的條件,您可以使用邏輯中的一個基本原理,稱為德摩根定律。Procmail中沒有直接的語法來表示“這個條件或那個條件”,但您可以將它重構為“不是((不是這個條件)和(不是那個條件))。

:0
* ! this condition
* ! that condition
{ } # nothing happens here
:0E # else
{ LOG="at least one of them matched
" }

或者乾脆使用打分;

:0
* 1^0 this condition
* 1^0 that conditon
{ LOG="at least one of them matched
" }

更新:

看起來ripmime實際上並不支持(提取或)命名單個附件。最簡單的解決方案可能是cron在午夜之前重命名最新到達的工作(或者如果您知道它何時到達,則在您期望的最晚時間之後):

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

請注意(特別)您需要將命令中的任何百分號加倍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 )

Content-type:頭可能不包含文件名;它可以(並且現在應該)在其中指定,Content-Disposition:但許多發件人將它放在兩個地方以實現向後兼容性。文件名應該正確地採用 RFC2231 編碼,這意味著可以填充許多可選欄位,我方便地假設它們將為空,就像 ASCII 文件名是城裡唯一的遊戲一樣。

還要注意我現在如何要求發件人主題匹配。說(不精確地)在HB ??主消息標題或正文中的某個位置查找匹配項。正確地說,在後一種情況下,匹配應該在 MIME 正文部分的標頭中,但 Procmail 沒有簡單的方法來指定這一點。

引用自:https://unix.stackexchange.com/questions/421433