明滅するプログラマの思索

WEBエンジニアとして勤務している一介の男が、日々気づいたことをまとめるブログです

qmail で特定のメール送信に失敗する問題

古いネタです。

メールサーバとして qmail を利用している環境において、特定のメール送信に失敗することがあります。
そのとき、クライアント側に帰ってくるエラーに451 See http://pobox.com/~djb/docs/smtplf.html.が含まれている場合、Bare LFs 問題と呼ばれる qmail のバグである可能性が高いです。

現象

Bare LFs 問題の特徴として以下が挙げられます。

  • 特定のメールの送信に失敗する
  • ほかのメールは送信に成功する
  • MTA が qmail
  • maillog にログが残らない
  • 送信エラーに以下の文言が含まれている
    • 451 See http://pobox.com/~djb/docs/smtplf.html.

原因

SMTP セッションの改行コードは RFC により CR+LF と規定されています。
qmail はその規定を順守し、裸の LF を含むデータを受け取ると、内部エラーとして処理してしまいます。
このときログに何も追記しないので、発見が難しいです。
ほかの MTA (Sendmail, Postfix など)は、裸の LF を受け取っても適切に対処するため問題ありません。
ちなみに、送信メールを見ても、裸の LF を含んでいる個所を見つけることはできなかったりします。

http://pobox.com/~djb/docs/smtplf.html には、問題の経緯などが記載されています。

対策

qmail と併せて利用される tcpデーモン ucspi-tcp には fixcrio というコマンドが同梱されており、このコマンドを使うと裸の LF を CR 付きに置換してくれます。
そのため、qmail-smtpd に引き渡す前に fixcrio を挟んであげればOKです。
qmail の起動用スクリプトは環境により多少異なるでしょうが、筆者の環境では以下のように書くことで解決できました。

...

tcpserver -qv -l0 -HR -u `id -u vpopmail` -g `id -g vpopmail` \
-x /etc/tcp.smtp.cdb 0 smtp \
fixcrio qmail-smtpd `hostname` vchkpw /bin/true 2>&1|\
splogger smtp &

...

現在は自前で MTA を立てなくても、クラウドベースの様々な配送システムが提供されています。
上記のような問題でハマることも少ないと思いますが、一応備忘録として。