あなたの作ったメール配信システムはエラーメール処理をしていますか?
今回はメルマガ等やメーリングリストのように大量のメールを配信するためのメール配信システムを自前で開発している方向けの情報(備忘録?)です。
大量のメールを配信する場合、配信できなかったエラーメールを適切に処理することが重要です。たとえば、
なんて感じです。適切なエラーメール処理なくば、知らず知らずのうちに SPAMer と同じようなメール配信をしていることになってしまうのです。かく言う僕の作ったメール配信システムも、それほどエラーメール処理を厳密に行っているわけではなく、何とかしないとなぁ〜と思っている今日この頃で、ちまちま資料を集め始めて仕様検討している次第です。
メール送信における socket データに関しての技術メモ
通常、メールを送信するには最低限下記の順序でコマンドを発行している。
| コマンド | 意味 |
| HELO ドメイン名 | SMTPサーバが接続してきたクライアントを認識する。 |
| MAIL FROM: 送信元メールアドレス | 送信元のメールアドレスを指定する(Envelope From)。 ※しばしばメールヘッダの「Return-Path:」として記録される。 |
| RCPT TO: 送信先メールアドレス | 送信先のメールアドレスを指定する(Envelope To)。 宛先がTO、CC、BCC に関係なく、複数の送信先がある場合はこのコマンドを繰り返す。 ※このコマンドで指定したアドレスにメールが送信される。 ※しばしばメールヘッダの「Received:」として記録される。 |
| DATA | サーバに本文の送信開始を宣言する。 ※DATA部のTO、CC、BCC は見た目だけ。RCPT TO: と混同しないように。 |
| QUIT | セッション終了を宣言する。 |
メールを送信に直接関係しないコマンドとしては下記のものがある。
| コマンド | 意味 |
| ETRN ホスト名・ドメイン名・キュー名 | 指定されたホスト名・ドメイン名・キュー名について、メールキューを作成する。 |
| RSET | MAIL、SEND、SOML、SAMLコマンドにより開始された処理を中止し、サーバ内部の状態をリセットする。 |
| NOOP | なにもしない。サーバの動作を確認するためのコマンド。 |
メールサーバによっては実装されていない可能性のあるコマンドとしては下記のものがある。
| コマンド | 意味 |
| EHLO ドメイン名 | HELOのESMTP版コマンド。ESMTPの機能を利用する場合はこのコマンドを利用する。 |
| VRFY ユーザー名・メールアドレス | 受信側SMTPサーバにユーザ名が存在するか確認を行う。 |
| EXPN メールアドレス | ユーザのaliasを展開し、表示する。 |
| VERB | 応答を詳細モードにする。 |
| TURN | クライアントとサーバの役割の交換を要求する。 |
| HELP [コマンド名] | 受信側SMTPサーバがサポートしているコマンドの一覧と説明を表示する。 |
メールヘッダーの内容に関しての技術メモ
| Header | 意味 |
| From: | 送信元のメールアドレス。 |
| To: | 送信先のメールアドレス。複数のメールアドレスが指定された場合、「,(カンマ)」で区切る。 |
| Cc: | 「Carbon Copy」の略で、「To:」で指定した宛先に送信されるメールと同じ内容のものを、「Cc:」で指定した宛先にも送信することが出来る。 |
| Date: | メールが送信された時刻を GMTを基準にして表す。 時差は「+」「-」で表す。 |
| Subject: | メールの件名(題名)を表す。 |
| Return-Path: | メール配信エラー時に送信されるエラーメールの送信先アドレスを表す。 |
| Received: | メールが配送されたルートを表す。配送経路は下から上の順で見ていく。 |
| Message-Id: | メール1通ごとにふられたユニークな番号。 |
| Reply-To: | 受信したメールに対して返信をする際に「From: 」と異なるメールアドレスに返信させたい場合に宛先を指定する。 |
| In-Reply-To: | 送信元のメッセージID。 |
| Errors-To: | 何らかのエラーが発生した場合に、指定したメールアドレスにエラーメッセージを送信する。 |
| MIME-Version: | MIMEのバージョンを表します。現在はVersion1.0のみ。 |
| Content-Length: | メッセージ本文のバイト数を10進数で指定する。 |
| Content-Type: | メッセージ本文の種類(Text、Image、Audio、Video、Application、Multipart、Message)を指定する。 |
| Content-Transfer-Encoding: | エンコードの種類を指定する。 |
| Organization: | 送信元が何の組織に属しているかを指定する。 |
| X-UIDL: | POPサーバーが届いたメールを区別するために、メールごとに自動でつける場合がある。 |
| Encrypted: | 暗号化情報を指定する。 |
メールの応答コードに関しての技術メモ
| エラー種別 | コード | 意味 |
|---|---|---|
| 2xx : 正常系 | 200 | RFC標準以外の成功応答 |
| 214 | システム・ステータスまたはシステム・ヘルプ応答 | |
| 214 | ヘルプ・メッセージ、コマンドの使用方法 | |
| 220 | SMTPサービス準備完了 | |
| 221 | コネクションのクローズ(QUITコマンドに対する応答) | |
| 250 | リクエストされたコマンドが正常終了 | |
| 251 | 受信者がローカルユーザーでないが転送可能 | |
| 252 | VRFYコマンド利用不可 | |
| 3xx : 正常系:コマンド受け入れ後にさらに入力が必要 | 354 | メッセージを送信し"\n . \n"で終了して下さい |
| 4xx : 一時的なエラー.再度実行すれば成功する可能性がある | 421 | 指定ドメインのSMTPサービスが動作不能のためコネクションを切断 |
| 450 | メールボックス利用不可のため失敗 | |
| 451 | ローカルサーバエラーのため、コマンドの実行に失敗 | |
| 452 | 容量不足のため、リクエストされたメールの受信に失敗 | |
| 5xx : 恒久的なエラー.問題を修正しなければ成功しない | 500 | コマンドの文法エラーか不明なコマンド |
| 501 | コマンド引数エラー | |
| 502 | コマンドが未実装 | |
| 503 | コマンド順序が正しくない | |
| 504 | コマンドパラメーターが未実装 | |
| 550 | メールボックスが存在しないため失敗 | |
| 551 | ユーザーが指定のドメインに存在しない | |
| 552 | クライアント記憶域割り当て超過によるコマンド中止 | |
| 553 | メールボックス名が無効 | |
| 554 | メール転送処理に失敗 | |
| 上記表の各コードに共通 | x0x | 文法エラー |
| x1x | 付加メッセージ | |
| x2x | SMTP接続関連 | |
| x5x | クライアント側の問題 |
メール送信エラーの原因と対処方法についての技術メモ
| エラーメッセージ | 対処方法 |
| 554 delivery error: dd This user doesn't have a yahoo.co.jpaccount.(受信者のメールアドレス) | 指定した送信先が存在しないので、今後メールを送信してはならない。 |
| 554 delivery error: dd Sorry, your message to (受信者のメールアドレス) cannot be delivered. This account is over quota. | 相手の方のメールボックスの保存容量が規定容量を超え、新しいメールを受け取れない状態。一時的にメールの送信を停止する必要がある。 |
| (****@***.**.**): ***.***.***.*** does not like recipient. Remote host said: 550 Requested action not taken: mailbox unavailable Giving up on ***.***.***.***. | 宛先のメールアドレスのメールボックスが何かの理由により使用不可となってい留状態。一時的にメールの送信を停止する必要がある。 |
| ***.***.***.*** does not like recipient. Remote host said: 550 ... User unknown Giving up on ***.***.***.***. | 宛先のメールアドレスが間違っている、もしくは別のメールアドレスに変更されている可能性があるため、今後メールを送信してはならない。 |
| (****@***.**.**): ***.***.***.*** does not like recipient. Remote host said: 554 (****@***.**.**): Recipient address rejected: Access denied Giving up on ***.***.***.***. | 該当サーバーが宛先への中継が拒否されている状態。宛先のメールアドレス側で受信拒否設定を行なっている可能性があるため、、一時的に送信を停止する必要がある。 |
| (****@***.**.**): ***.***.***.*** does not like recipient. Remote host said: 554 5.7.1 Relay denied Giving up on ***.***.***.***. | 同上 |
| (****@***.**.**): Connected to ***.***.***.*** but sender was rejected. Remote host said: 550 Access denied | 送信者のアドレスが拒否されている状態。宛先のメールアドレス側で受信拒否設定を行なっている可能性があるため、一時的に送信を停止する必要がある。 |
| (****@***.**.**): ***.***.***.*** does not like recipient. Remote host said: 550 Invalid recipient: (****@***.**.**): Giving up on ***.***.***.***. | 宛先が間違っているため、無効なメールアドレスとして処理する。 |
| (****@***.**.**): ***.***.***.*** does not like recipient. Remote host said: 553 (****@***.**.**)... No such user here Giving up on ***.***.***.***. | 宛先のユーザーが送信先サーバーに存在しないため、無効なメールアドレスとして処理する。 |
| (****@***.**.**): CNAME lookup failed temporarily. (#4.4.3) I'm not going to try again; this message has been in the queue too long. | 宛先のドメインが正しくないため、しないため、無効なメールアドレスとして処理する。 |
| (****@***.**.**): Sorry, I wasn't able to establish an SMTP connection. (#4.4.1) I'm not going to try again; this message has been in the queue too long. | 宛先のサーバーは存在するが、メールの受け入れをしていない状態。一時的に送信を停止する必要がある。 |
| (****@***.**.**): Sorry, I couldn't find any host named *****.**.** (#5.1.2) | 宛先のドメインが正しくないため、しないため、無効なメールアドレスとして処理する。 |
エラーメールの送り先の落とし穴の技術メモ
Envelope-From と DATA部の From を混同しないよう注意。
いわゆるメーラーの From に表示されている値は、DATA部の From で単なる見た目です。何らかの理由で見た目の From を変更する場合でも、Envelope-From にはエラーメールを受け取りたいアドレスを指定する必要があります。間違えると、意図しないアドレスに大量のエラーメールが届く羽目になります。
エラーメールを自動処理する方法:qmail+Perl 編
僕が扱っているメールサーバに qmail なのですが、qmail は .qmailというファイルをホームディレクトリに用意することで、 Maildir にメールを保存する前にいろいろと処理をさせることができます。sendmail でいう .forward に相当するファイルになります。注意点は、パーミッションを 700 にする必要があるという点です。
メール転送の設定例 (エラーメールを他のアドレスに転送する)
chmod 700 ~/.qmail
エラー自動処理の設定例 (エラーメールをパイプを使って perl-script で処理する)
chmod 700 ~/.qmail
※ auto_errmail.pl ってのはエラーメールを適切に処理する perl-script を想定してまして、メーリングリストの fml8 っていうツールの Mail モジュールが流用できそうな感じです。
参考サイト一覧


コメントやシェアをお願いします!
前田忠志
とても参考になりました。
わかり易くまとまっていて整理できました。
ありがとうございました。
drk
Ageさん>ご報告有り難うございました。
Age
非常に参考になりました。
参考サイト一覧の
メールシステムの基礎と送受信処理
は次のところに移動されているみたいでした。
http://www7a.biglobe.ne.jp/~tsuneoka/cgitech/5.html
drk
りんもんさん>情報有難う御座います。mailman は最近日本でも流行りだしましたよね。内部動作、参考にしてみます。
りんもん
僕はmailmanというメーリングリストに乗り換えたのですが、エラー処理を自動でやってくれていそうなのですが、頼ってしまっているので、その真偽の程は、これからかなあ。