Fetchmailで、あるPOP3サーバから受信したメールをPostfixで再配送すると、下記のようにmail forwarding loop が発生した。
Aug 4 00:00:00 MyMailServer postfix/pipe[27838]: xxxxxxxx: to=<[email protected]>, relay=procmail, delay=1.1, delays=0.83/0.07/0/0.15, dsn=5.4.6, status=bounced (mail forwarding loop for [email protected])
このエラーのためメールのローカル配信プロセスはここで中断されてしまった。
エラーを発生させたメールサーバはPostfixで、バーチャルドメインを設定し、ローカル配信などを担当しているものである。
さらにprocmailなどで指定した転送処理などもされない。
■問題が発生しないPOP3サーバもあった。
しかし、同じ仕組みでFetchmailで受信しPostfixに処理を任せていたこれ以外のPOP3サーバについては、問題なく配送プロセスを完了できた。
メールヘッダーを比較してみると、Fetchmailが受信しているPOP3メールサーバによって、
「Delivered-To:」ヘッダーの内容のパターンが異なっていることに気がついた。
■Fetchmail周りのメールヘッダーを確認した。
○問題が発生したメールのヘッダー(pop3.test [x.y.z.a]からfetchmailで受信)
Received: from MyMailServer.local (localhost [127.0.0.1])
by postfix1.local (Postfix) with ESMTP id xxxxxxxxxx
for <[email protected]>; Thu, 3 Aug 2017 00:00:00 +0900 (JST)
X-Original-To: [email protected]
Delivered-To: [email protected]
Received: from pop3.test [x.y.z.a]
by MyMailServer.local with POP3 (fetchmail-6.3.17)
for <[email protected]> (single-drop); Thu, 03 Aug 2017 00:00:00 +0900 (JST)
○問題が発生しなかったメールのヘッダー(pop3.example.co.jp [b.c.d.e]からfetchmailで受信)
Received: from MyMailServer.local (localhost [127.0.0.1])
by postfix1.local (Postfix) with ESMTP id xxxxxxxxxx
for <[email protected]>; Sat, 5 Aug 2017 00:00:00 +0900 (JST)
Delivered-To: m19200000-[email protected]
Received: from pop3.example.co.jp [b.c.d.e]
by MyMailServer.local with POP3 (fetchmail-6.3.17)
for <[email protected]> (single-drop); Sat, 05 Aug 2017 00:00:00 +0900 (JST)
Delivered-Toヘッダーに注目すると、問題が発生しなかったメールの場合、
Delivered-Toヘッダーに記載されているユーザー名に、ハイフンで「m19200000」が繋げられている。
Delivered-Toヘッダーのアドレスと、for <[email protected]> に記載されているアドレスは異なるものになっていた。
問題の発生しなかったさらに他のPOP3サーバーについても、同じパターンではなかったものの、
Delivered-Toヘッダーのアドレスが、for内のアドレスと一致しないようになっていた。
Fetchmailの設定は共通であるため、この差は、受信元POP3サーバに拠るものだと考えた。
あるいは、受信元POP3サーバが付加したものだと考えられる。
■原因らしいDelivered-Toヘッダーを記載しないようにした。
問題の発生するPOP3サーバからの受信に際して、
メールヘッダーにDelivered-Toヘッダーを記載しないようにした。
Fetchmailには、Delivered-Toヘッダーを記載しないオプションがある。
設定ファイルの次の箇所に
「dropdelivered」というオプションを挿入した。
(省略)
username "[email protected]" password "thisispwd" dropdelivered is "[email protected]" here
(省略)
○オプションなし
Received: from MyMailServer.local (localhost [127.0.0.1])
by postfix1.local (Postfix) with ESMTP id xxxxxxxxxx
for <[email protected]>; Thu, 3 Aug 2017 00:00:00 +0900 (JST)
X-Original-To: [email protected]
Delivered-To: [email protected]
Received: from pop3.test [x.y.z.a]
by MyMailServer.local with POP3 (fetchmail-6.3.17)
for <[email protected]> (single-drop); Thu, 03 Aug 2017 00:00:00 +0900 (JST)
Received: from mail.test (localhost [127.0.0.1])
by mail.test (Postfix) with ESMTP id yyyyyyyyyyyy
for <[email protected]>; Thu, 3 Aug 2017 00:00:00 +0900 (JST)
○オプションあり
Received: from MyMailServer.local (localhost [127.0.0.1])
by postfix1.local (Postfix) with ESMTP id xxxxxxxxxx
for <[email protected]>; Sat, 5 Aug 2017 00:00:00 +0900 (JST)
X-Original-To: [email protected]
Received: from pop3.test [x.y.z.a]
by MyMailServer.local with POP3 (fetchmail-6.3.17)
for <[email protected]> (single-drop); Sat, 05 Aug 2017 00:00:00 +0900 (JST)
Received: from mail.test (localhost [127.0.0.1])
by mail.test (Postfix) with ESMTP id yyyyyyyyyyyy
for <[email protected]>; Sat, 5 Aug 2017 00:00:00 +0900 (JST)
以上のように、
「dropdelivered」というオプションが有効に機能して、
Delivered-Toヘッダーが記載されないようになった。
また、これによって、
冒頭の「mail forwarding loop」の問題も解消した。
■なぜ「mail forwarding loop」が発生したのか。
下記、参考ページ(†1)によれば、
ISPなどのPOP3サーバが、Delivered-Toラインをメールに付加する。
そして、Fetchmailがこのメールを受信しPostfixに転送すると、Postfixはこのラインを見つけて、
mail forwarding loop error をスローして、ローカル配送を中断する。
しかし、以上の検証では、Delivered-Toラインが付加されていたとしても、そのアドレスが、
for<アドレス> に一致していない場合には、問題が生じないことがわかった。
○次のようにイメージすることができると思う。
ローカル配信を担当するPostfixにしてみれば、
転送されてきたメールは、確かに自分が管理するローカルのユーザー(Aさん)宛のものだとしても、
既にそれには「配送済みマーク(Delivered-To Aさん)」が記載されているので、
いったん届け終わったものがまた外部からやってきたのだと思い首をかしげるわけだろう。
届けたはずなのにまた回ってきたということは「メールループしている!」と考えて、
そこで、配送担当のPostfixは、それ以上はAさんに配信しないように中断するわけだ。
再配達防止機能(メールループ阻止機能)である。
つまり、
ローカル配送を担当するPostfixは、Delivered-Toラインがある場合には、
そこに記載されているアドレスと、ローカル配送先アドレス(エンベロープアドレス?)とを比較し、転送ループしているかどうかを判定する。
一致するならば、転送がループしているとしてエラーが発生し、
一致しなければ、問題なく、新たな配信先として配送プロセスが完了する。
<エラーが発生する場合の図>
・【Aさん済印】・・・ヘッダーに配送済み印 「Delivered-To : Aさん」 が記載されたメール
POP3サーバ【Aさん済印】⇒Fetchmail【Aさん済印】(Aさん宛)⇒中継Postfix【Aさん済印】(Aさん宛)⇒ローカル配送Postfix【Aさん済印】(Aさん宛)←←←ここで転送ループエラー発生!!「お届け済みのメールがまた回ってきたよ!」
<Delivered-ToラインをFetchmailのオプションで削除した場合>
・【Aさん済印】・・・ヘッダーに配送済み印 「Delivered-To : Aさん」 が記載されたメール
・【-】・・・ヘッダーからDelivered-To : Aさん が削除されたメール
POP3サーバ【Aさん済印】⇒Fetchmail《済印クリア》【-】(Aさん宛)⇒中継Postfix【-】(Aさん宛)⇒ローカル配送Postfix【-】(Aさん宛)←←←配送プロセス完了、あるいはprocmailなどでさらに処理を継続する。
■まとめ
FetchmailでPOP3サーバから受信したメール(いったん配送済みになったもの)を、さらにメールの配送プロセスに載せる前には、
「配送済みマーク(Delivered-To Aさん)」には注意する必要がある。
新たな配送プロセスの先にあるローカル配信先アドレスと、「配送済みマーク(Delivered-To アドレス)」が一致する場合、
今回の問題のように、再配達防止機能が検知して、中断されてしまう。
一致する場合には、上記の方法でFetchmailにオプションを付けて、
「配送済みマーク(Delivered-To アドレス)」を剥がす必要がある。
一致しないのであれば、問題は発生しない。
そんなDelivered-Toラインがあってもかまわない。
<参考>
(1)Fetchmail and postfix 'mail forwarding loop' - SOLVED
< https://lists.kolab.org/pipermail/users/2005-November/003755.html > 2017年8月5日
(2)Delivered-To【メールヘッダ】
< http://wa3.i-3-i.info/word11114.html > 2017年8月5日