Content-type: message/rfc822 の謎

f:id:ingage:20210419194939p:plain

id:kizashi1122 です。 メールの話です。

メールってとてもややこしいんですよね。 マルチパートと言って、パート部分を複数持つこともできますし、マルチパートを入れ子にすることもできます。

  • メール本体
    • 本文(テキスト)
    • 本文(HTML)
    • 添付ファイル1

みたいなのが典型的なマルチパートメールです。

添付ファイルであれば、Content-Type が image/png だったり application/pdf だったりするわけです。
たまに Content-Type が message/rfc822 の場合もあります。

よくあるのがメールの不達で返ってきたメール(バウンスメール)です。 @ より前のユーザが存在しない場合は、Unknown User で返ってくる例のあのメールです。

メールサーバーによりますがバウンスメールにはそもそも届けたかったメールが添付されていることがあります。 つまりメールにメールが添付されてるということになります。

そのときに使う Content-Typeが message/rfc822 なのです。 こんなイメージです。

Date: Mon, 19 Apr 2021 08:38:03 +0900 (JST)
From: MAILER-DAEMON@example.com (Mail Delivery System)
Subject: Undelivered Mail Returned to Sender
To: system@example.com
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
        boundary="aaaaaa"
Message-Id: <20210418233803@example.com>

This is a MIME-encapsulated message.

--aaaaaa
Content-Description: Notification
Content-Type: text/plain; charset=us-ascii

Unknown User ですよ的なメッセージ



--aaaaaa
Content-Description: Undelivered Message
Content-Type: message/rfc822

Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=iso-2022-jp
Mime-Version: 1.0
To: example@example.jp
From: example@example.co.jp
Subject: foo


元メールの本分


--aaaaaa--

みたいな感じです。

タイトルで「謎」と書きましたが、何が謎なのか。

最近こういうバウンスメールをみるのです。

Content-Type: message/rfc822; charset=utf-8
Content-Transfer-Encoding: base64


WyRyO3Ikajh8JC84Zk5pPz0kNz5lJDIkXiQ5ISMbKEINCg0KGyRCQWFCLiRHJE8kNCQ2JCQkXiQ5
JCwhIhsoQg0KGyRCQGhITCEiJSshPCVJMnEwd01NJCskaSROJDRNeE1RSF1HJyROPz1AQSRLSDwk
:
:

ふーん、 元のメッセージが base64 エンコードされてるのね、というメールなのですが、うちのサービスではこのバウンスメールの扱いに失敗します。

なんでだろう?

と思って、RFCのドキュメントを読むことにしました。

RFC 2046: Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types

の Page 29 に

No encoding other than "7bit", "8bit", or "binary" is permitted for the body of a "message/rfc822" entity

とあります。つまり RFC 違反のメールであり、うちが使っているライブラリでは RFC に則って作られていたため、 Content-Transfer-Encoding: base64 が指定してあってもそれを無視して本文をそのまま扱っていたということになります。

フォーマットの違うCSVをインポートしようとしたらエラーで弾けばいいでしょう。 ただメールの世界ではルール違反(RFC違反)はもはや当たり前です。どこまでをサポートすればよいのかは悩み外どころです。

うちでは今回は Content-Transfer-Encoding: base64 が指定してあれば、明示的に base64 でデコードしてあげることにしました。

以上です。

インゲージではエンジニアを募集しています!

ではまた。