Ruby で SMTPError#message を使う場合の注意点

やっと「シン・ウルトラマン」を映画館で観てきた id:kizashi1122 です。

弊社サービス Re:lation ではメールを扱うことが多いです。送受信のエラーもハンドルしています。
今回ご紹介するのはメール送信時のエラーについてです。

メールアドレスの @ より前に .. を含んでいたり、@ の直前に . を含むと RFC 5321 的には不適合となります。

実際に日本では DoCoMo ユーザなど一部のユーザがこの手のメールアドレスをまだ使い続けていたりしますが RFC 的にはダメなわけです。

昔は Gmail でもこの手のメールアドレス宛に送信はできていました。しかし確か2015年くらいだったかと思いますが、送信時にRFC違反だよというエラーを返すようになりました。

このような RFC 違反のメールアドレス宛に Gmail の送信サーバーに Ruby のプログラムから送るようにします。
このエラーの場合は Net::SMTPFatalError が返ります。ハンドリングしてみましょう。

 begin
   mailer.deliver
rescue Net::SMTPFatalError => e
  puts e.message
end

このようにハンドリングして e.message を受けとり表示するようにしてみます。

表示された中身はこうなります。

553-5.1.3 The recipient address <example...example@example.jp> is not a

なんか文の途中で切れてしまってますね。

実はこれ、Ruby の Net::SMTP の仕様になります。実際のメッセージは改行を挟んで続きます。

github.com

ソースを見るとSMTPサーバから受け取ったエラーメッセージの1行目しか返してないのです。

ここを私はモンキーパッチを当てて、e.message で改行以降も取れるようにしました(コードは省略)

するとちゃんと

553-5.1.3 The recipient address <example...example@example.jp> is not a
553 5.1.3 valid RFC-5321 address. w1sm9957374pgs.15 - gsmtp

と全文とることができます。MS Exchange では、SMTPのエラーメッセージに大量の謎の文字列がくっついてくるので途中で切り取るなどの処理が必要になるかと思います。

俺はモンキーパッチをあてなくないぞ、という方は、

e.response.string

で文字列全体を取得することができます。

インゲージではエンジニアを募集しています。 ご応募よろしくおねがいします。