はじめに
現在のお仕事で使っているサーバで Mail::Sendmail を使ったメールの送信でつまづいたので,ひとまずの解決までをメモしておきます.
メール送信コード: before
Mail::Sendmail は,サーバ上の任意のSMTPを経由してメールを送信するモジュールで,簡単なコードを書くだけでメールの送信が行えます.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ... use Mail::Sendmail; use Encode; ... my $subject = '...'; $subject = encode( 'MIME-Header-ISO_2022_JP', decode( 'utf-8', $subject ) ); my $body = encode( 'jis', decode( 'utf-8', '...' ) ); my %mail = ( smtp => 'localhost', 'Content-Type' => 'text/plain; charset=iso-2022-jp', To => '...', From => '...', Subject => $subject, Message => $body, ); sendmail( %mail ); if( $Mail::Sendmail::error ) { warn 'Mail::Sendmail error: ', $Mail::Sendmail::error; } |
コードについては,次を参考にしています.
問題発生
上記のコードは既に以前に書いており,今まで何度か利用してきましたが,特に問題が起こることはありませんでした.
...で,今回.
Mail::Sendmail error: message transmission error (451 See http://pobox.com/~djb/docs/smtplf.html.)
といったメッセージが出てメールが送信されない,といったことが起こるようになりました.
qmail と bare LF 問題
メッセージにあるURLを覗いてみます.
It was generated by qmail, an Internet message transfer agent. Your mailer tried to send an e-mail message to a server running qmail. Unfortunately, qmail spotted a problem: your mailer sent a bare LF.
Bare LFs in SMTP – http://cr.yp.to/docs/smtplf.html
「bare LF(生のLF?)」 の状態で送ることに問題が, qmail で?,あるようです.確かに,現在のお仕事で使っているサーバでは,MTA として qmail が使われています.
この 「bare LF」 なるものについてググってみたところ,次の文にあたりました.
一般に、SMTPセッションはRFCの規定により使用される改行コードはCR+LFと規定されています。
しかし、残念な事にこの規定は各種MTAやメーラーは必ずしもこのRFCに準拠しているものばかりではありません。
特に、LFのみで送ってしまうものは多く、これをbare LF (生のLF)と呼びます。
携帯端末とbare LFとqmail : アシアルブログ
RFC(822) で「改行コードは CR+LF」と規定されているんですね.だけど,残念なものあるよ,と.
本文の改行コードを変えてみる
改行コードですぐに頭に浮かんだのが,メール本文.
UTF-8 / LF なテンプレートを使っているので,それが問題か?と考え,改行コードを置き換えてみました.
my $body = encode( 'jis', decode( 'utf-8', '...' ) ); $body =~ s{(?:\x0d\x0a?|\x0a)}{\x0a}g; $body =~ s{\x0a}{\x0d\x0a}g; # $body の改行を CR+LF に統一する
...が,変化はありませんでした.
Subjectヘッダに改行が...
先のキーワードでさらに調べてみると,とあるメーリングリストの次の投稿記事にあたりました.
Linuxで同一マシン内のqmailを使って無事送信できましたが 届いたメールのヘッダーを見ると
Subject: =?ISO-2022-JP?B?GyRCIzEjMiMzIzQjNSM2IzcbKEI=?=
=?ISO-2022-JP?B?GyRCIzgbKEI=?=
と27バイト目?で改行されてました。
[PHP-users 21450]Re: メール送信エラー
あ~,確か長い文字列をエンコードした場合には,一定の長さごとに改行されるんでしたっけ...
my $subject = 'ほげほげほげほげほげほげほげほげほげほげ'; $subject = encode( 'MIME-Header-ISO_2022_JP', decode( 'utf-8', $subject ) );
=?ISO-2022-JP?B?GyRCJFskMiRbJDIkWyQyJFskMiRbJDIkWyQyJFskMiRbJDIkWyQyGyhC?= =?ISO-2022-JP?B?GyRCJFskMhsoQg==?=
確かに改行されてますね.同様のエラーでメールも送信できませんでした.
では,改行されないような短い件名ではどうよ?
$subject = 'ほげほげほげほげ'; $subject = encode( 'MIME-Header-ISO_2022_JP', decode( 'utf-8', $subject ) );
=?ISO-2022-JP?B?GyRCJFskMiRbJDIkWyQyJFskMhsoQg==?=
...送信できました orz
my $subject = 'ほげほげほげほげほげほげほげほげほげほげ'; $subject = encode( 'MIME-Header-ISO_2022_JP', decode( 'utf-8', $subject ) ); $subject =~ s{(?:\x0d\x0a?|\x0a)}{\x0a}g; $subject =~ s{\x0a}{\x0d\x0a}g; # $subject のエンコード後の改行を CR+LF に統一する
ということで,エンコード後の件名の改行コードも CR+LF に置き換えたところ,どちらの場合にもメールを送信することができるようになりました.
メール送信コード: after
以上より,Mail::Sendmail を使ってメールを送信するコードは,次のように修正されました.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ... use Mail::Sendmail; use Encode; ... my $subject = '...'; $subject = encode( 'MIME-Header-ISO_2022_JP', decode( 'utf-8', $subject ) ); $subject =~ s{(?:\x0d\x0a?|\x0a)}{\x0a}g; $subject =~ s{\x0a}{\x0d\x0a}g; # $subject のエンコード後の改行を CR+LF に統一する my $body = encode( 'jis', decode( 'utf-8', '...' ) ); $body =~ s{(?:\x0d\x0a?|\x0a)}{\x0a}g; $body =~ s{\x0a}{\x0d\x0a}g; # $body の改行を CR+LF に統一する my %mail = ( smtp => 'localhost', 'Content-Type' => 'text/plain; charset=iso-2022-jp', To => '...', From => '...', Subject => $subject, Message => $body, ); sendmail( %mail ); if( $Mail::Sendmail::error ) { warn 'Mail::Sendmail error: ', $Mail::Sendmail::error; } |
これでしばらくは問題起きないかな.
おわりに
以上,メールのSubjectヘッダ(エンコード後)に改行が入り得ることを忘れ,一晩中格闘した記録でした.
エンコードする際に改行コードを指定できればちょっと幸せなのかもしれませんが,今回その辺までは調査していません.

まだ解消できたかどうか判らないのですが、こちらのソースを参考に自社システム対応させて頂きました。
オーダー受注部分のメール発送が問題だったので、本当に悩んでいたのですが、助かりました!ありがとうございます。