ターミナルからSMTPサーバーを経由してメールを送信する
はじめに
モバイルアプリを作成しているとき、SMTPサーバーを経由してメールを送信することがありました。その際、ライブラリを使ってお手軽に送信していました。SMTPのプロトコルを理解するため、ターミナルからSMTPサーバーを経由してメールを送信を試してみることにしました。
環境
- Mac OS 14.4.1
- smtp4dev
- ダミーのSMTPサーバー
smtp4devのセットアップ
手元の環境でダミーのSMTPサーバーを用意します。
その際、smtp4devを使うと便利です。
docker-compose.ymlをダンロードして、docker-compose upを実行することで簡単に起動できます。
そしてデフォルト設定ではhttp://localhost:5000でコンソール画面にアクセスできます。

このページの左端にある歯車ボタンから、必要な設定を行います。
今回の例では、TLSモードはSTARTTLSに設定し、ユーザー名とパスワードを指定しておきます。


STARTTLSの確認
さきほど設定したダミーSMTPサーバーに対して、ターミナルから接続してみます。smtp4devではデフォルト25番ポートが空いているので、下記のようにコマンドを打ちます。telnet://localhost:25として、telnetを利用し、直接サーバーとTCP接続を試みます。
curl -v telnet://localhost:25
接続を開始した後、ehloコマンドを使ってehlo localhostと入力すると、サーバーが対応している仕様を返してくれます。その中に、STARTTLSがありますね。なので、次にSTARTTLSを入力すると、220 Ready to start TLSとなり、通信が暗号化されたTLS接続が確立されることが確認できました。

メール送信
opensslコマンドをつかって、メール送信をしてみた。
openssl s_client -starttls smtp -connect localhost:25 -quiet
そして、下記のように入力を進めます。

画像で示したテキストデータ
AUTH LOGIN
334 VXNlcm5hbWU6
dGVzdC11c2Vy
334 UGFzc3dvcmQ6
dGVzdDEyMzQ1
235 Authenticated OK
MAIL FROM:<test@test.com>
250 New message started
RCPT TO:<sample@test.com>
250 Recipient accepted
DATA
354 End message with period
From: test <test@test.com>
To: test <sample@test.com>
Subject: test
Content-Type: text/plain; charset=UTF-8
This is a test mail.
.
250 Mail accepted
QUIT
221 Goodbye
注意点としては
- ユーザ名・パスワードはBase64形式に変換しておくこと
- 例えば、下記のコマンドで変換
echo -n {$DATA} | base64
- サーバー側でヘッダーと本文を区別するため、ヘッダーと本文の間は1行空けておくこと
です。
以上でメールが送信され、smtp4devのダッシュボードに表示されます。

smtp4devをつかったときの疑問点
さきほどのopensslコマンドを使ってehloコマンドを実行すると、STARTTLSを有効にしているにかかわらず、リストにSTARTTLSが表示されません。STARTTLSを実行すると、Ready状態になるものの、AUTH LOGINを実行すると、エラーが出て終了します。smtp4devを使う際に自己証明書の設定が正しくできていないのかと推察しています。現状は未解決です。

おわりに
検証用にsmtp4devは便利ですね。
SMTPのプロトコルについて少し理解することができました。
参考
smtp4devで自己証明書の設定に関する記事
Discussion