- SMTPプロトコルはRFC5321で規定されている。
- SMTPプロトコルでは認証機能があるが、それについてはRFC2554で規定されている。
- SMTPプロトコルでのデータ(ヘッダ含む)はインターネットメッセージフォーマットというプロトコルが使われている。
- IMFプロトコルはRFC5322で規定されている。
ThuderBird等でメールの送信をしながらWireSharkでsmtpでフィルターをかけて表示すると流れがよくわかる。
メール送信の流れ
ユーザ:telnet等でSMTPサーバへ接続
↓
サーバ:220 foobar.ne.jp SMTP-Gateway Version 1.09 at Tue, 24 May 2016 01:00:05 +0900 (JST)
↓
ユーザ:EHLO [192.168.11.2]
↓
SMTPサーバ:
250-foobar.ne.jp Hello [192.168.11.2] [203.136.30.210], pleased to meet you
250-AUTH CRAM-MD5 LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-8BITMIME
250-SIZE 104857600
250-DSN
250-DELIVERBY
250 HELP
↓
ユーザ:AUTH CRAM-MD5
↓
サーバ:334 Base64でエンコードされた文字列
Base64でエンコードされた文字列をデコードした内容は「<2529.28.95.1464019205@foobar.ne.jp>」
↓ユーザ:Base64でエンコードされた文字列
Base64でエンコードされた文字列をデコードした内容は「user@foobar.ne.jp 870214746a7d75c7ccbc2514eed93b28」
↓
サーバ:235 2.7.0 Authentication successful
↓
ユーザ:MAIL FROM:<user@foobar.ne.jp> BODY=8BITMIME SIZE=456
↓
サーバ:250 2.1.0 <user@foobar.ne.jp>… Sender ok
↓
ユーザ:RCPT TO:<user@foobar.ne.jp>
↓
サーバ:250 2.1.5 <user@foobar.ne.jp>… Recipient ok
↓
ユーザ:DATA
↓
ユーザ:354 Enter mail, end with “.” on a line by itself
↓
ユーザ:ヘッダとデータを送信(詳細は下の画像の通り)
↓
サーバ:250 2.0.0 u4NG05xa012846 Message accepted for delivery
↓
ユーザ:QUIT
↓
サーバ:221 2.0.0 foobar.ne.jp closing connection
認証について
チャレンジレスポンス方式で認証される。
チャレンジレスポンス方式の流れ
ユーザ:IDを送信
サーバ:チャレンジと呼ばれる文字列等を送信
ユーザ:IDとパスワードをチャレンジを元にレスポンスを作成して、サーバへ送信
サーバ:IDとパスワードをチャレンジを元にレスポンスを作成して、ユーザから送られてきたレスポンスが正しいかを確認
サーバ:正しければ認証。正しくなければ認証しない。
認証について参考になるサイト
http://www.tohoho-web.com/ex/draft/smtp-auth.htm
Perlでのテストスクリプト
Net::SMTPとAuthen::SASLをインストールしてから動いた。
何かうまく動かなかったら、$@を参照するとエラー内容が書かれている。
#!/usr/bin/perl use strict; use warnings; sub sendmail_smtp { use Net::SMTP; # SMTPサーバ my $mail_server = "foobar"; # 自分のIPアドレス、もしくはドメイン my $hello = '192.168.11.20'; # SMTPサーバに接続する時のポート my $port = 587; # SMTPサーバに接続する時のユーザ名 my $auth_user = 'foo'; # SMTPサーバに接続する時のパスワード my $auth_pswd = 'bar'; # 送信元メールアドレス my $from = 'foobar'; # 送信先メールアドレス my $to = 'foobar'; # ヘッダーが格納される変数 my $header = ''; # メールの件名 my $subject = 'PerlMailテストTest'; # メールの本文 my $mail_body = <<END_OF_MAIL_BODY; This is あいうえお PerlTest. かきくけこ END_OF_MAIL_BODY my $flag = 1; my $smtp = Net::SMTP -> new($mail_server, Hello => $hello, Timeout => 60, Port => $port ); if (!defined($smtp)) { $flag = 0; die "PerlMailTest.pl\n" . $! . "\n"; } if ($flag == 1) { if (!($smtp -> auth($auth_user, $auth_pswd))) { $flag = 0; die "PerlMailTest.pl\n" . $! . "\n"; } } if ($flag == 1) { if (!($smtp -> mail($from))) { $flag = 0; die "PerlMailTest.pl\n" . $! . "\n"; } } # ヘッダーの設定。 $header = "From:$from\n"; $header .= "To:$to\n"; $header .= "Subject:$subject\n"; $header .= "MIME-Version:1.0\n"; #$header .= "Content-Type:text/plain; charset=iso-2022-jp\n"; $header .= "Content-Type:text/plain; charset=utf-8\n"; $header .= "Content-Transfer-Encoding: 7bit\n"; # メール送信。 if ($flag == 1 && $smtp -> to($to)) { $smtp -> data(); $smtp -> datasend($header); $smtp -> datasend("\n"); $smtp -> datasend($mail_body); } else { die "PerlMailTest.pl\n" . $! . "\n" . $smtp -> message() . "\n"; } $smtp -> quit; } &sendmail_smtp;