- 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;