LoginSignup
8
10

More than 5 years have passed since last update.

JavaMailでヘッダをエンコードする際の注意点

Last updated at Posted at 2016-10-25

環境

バージョン
Java 8
JavaMail 1.5.5

ヘッダが長いメールをMimeUtility#encodeText(String)する際の注意点

 JavaMailのMimeUtility#encodeText(String)を利用する際、Base64エンコード後の文字列が76文字以上になる場合、自動的に複数の文字列に分割されます。ここまではよいのですが、文字列の接続子が、標準では「半角空白」になります。

1.サンプルコード

FoldTest.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Message.RecipientType;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

public class FoldTest {

    public static void main(String[] args) throws MessagingException, IOException {
        // smtp設定(設定値は適当)
        Properties props = new Properties();
        props.setProperty("mail.smtp.host", "smtp.example.com");
        props.setProperty("mail.smtp.port", "587");
        props.setProperty("mail.smtp.connectiontimeout", "5000");
        props.setProperty("mail.smtp.timeout", "5000");
        props.setProperty("mail.mime.address.strict", "false");

        // メールオブジェクトを作る
        final Session session = Session.getInstance(props);
        MimeMessage message = new MimeMessage(session);

        // Header-Fromに注目!!
        final String from = MimeUtility.encodeText("とてもすごーいフレンズ <from@example.com>", "iso-2022-jp", "B");
        message.setHeader("From", from);

        // Header-To
        final String to = MimeUtility.encodeText("<to@test.sample.co.jp>", "iso-2022-jp", "B");
        message.setRecipients(RecipientType.TO, to);
        // Subject
        message.setSubject("件名欄");
        // 本文
        message.setText("Hello World.");

        // メールオブジェクトから文字列へ
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            message.writeTo(baos);
            System.out.println(baos.toString("utf-8"));
        }
    }
}

1.の出力

From: =?iso-2022-jp?B?GyRCJEgkRiRiJDkkNCE8JCQlVSVsJXMlOhsoQiA8ZnI=?= =?iso-2022-jp?B?b21AZXhhbXBsZS5jb20+?=
To: to@test.sample.co.jp
Message-ID: <2052001577.0.1490015862605@..........>
Subject: =?UTF-8?B?5Lu25ZCN5qyE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello World.

この接続子を、「改行(CRLF) + 半角空白」にしたい場合、MimeUtility#encodeText(String)を使用する前に、以下の設定が必要になるようです。

System.setProperty("mail.mime.foldencodedwords", "true");

2.サンプルコード(foldencodewords設定版)

FoldTest.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Message.RecipientType;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

public class FoldTest {

    public static void main(String[] args) throws MessagingException, IOException {
        // trueの場合、長いヘッダー行は改行され、半角空白が付加される
        System.setProperty("mail.mime.foldencodedwords", "true");

        //---------- 以下は 1.と同様 ----------
        // smtp設定(設定値は適当)
        Properties props = new Properties();
        props.setProperty("mail.smtp.host", "smtp.example.com");
        props.setProperty("mail.smtp.port", "587");
        props.setProperty("mail.smtp.connectiontimeout", "5000");
        props.setProperty("mail.smtp.timeout", "5000");
        props.setProperty("mail.mime.address.strict", "false");

        // メールオブジェクトを作る
        final Session session = Session.getInstance(props);
        MimeMessage message = new MimeMessage(session);

        // Header-Fromに注目!!
        final String from = MimeUtility.encodeText("とてもすごーいフレンズ <from@example.com>", "iso-2022-jp", "B");
        message.setHeader("From", from);

        // Header-To
        final String to = MimeUtility.encodeText("<to@test.sample.co.jp>", "iso-2022-jp", "B");
        message.setRecipients(RecipientType.TO, to);
        // Subject
        message.setSubject("件名欄");
        // 本文
        message.setText("Hello World.");

        // メールオブジェクトから文字列へ
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            message.writeTo(baos);
            System.out.println(baos.toString("utf-8"));
        }
    }
}

2.の出力(foldencodewords設定版)

From: =?iso-2022-jp?B?GyRCJEgkRiRiJDkkNCE8JCQlVSVsJXMlOhsoQiA8ZnI=?=
 =?iso-2022-jp?B?b21AZXhhbXBsZS5jb20+?=
To: to@test.sample.co.jp
Message-ID: <2052001577.0.1490015590351@..........>
Subject: =?UTF-8?B?5Lu25ZCN5qyE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello World.

 出力結果のHeader-From欄を比較して見ていただければわかりますが、特に設定のないサンプルコードの出力は、Header-From欄が1行として表示されています。対して、foldencodewords設定がtrueの場合、Header-From欄が改行され、2行目の先頭に半角空白が付加されています。

 この理由は、「なんらかの目印がないと、この行がどのヘッダに属しているのがわからない」為と思われます。仕様としては、RFC2822の以下の記述にあるように

2.1.1. Line Length Limits

There are two limits that this standard places on the number of
characters in a line. Each line of characters MUST be no more than
998 characters, and SHOULD be no more than 78 characters, excluding
the CRLF.

「ヘッダ行は、できれば(SHOULD)78文字以下に収めるのが望ましい(改行抜きで)」としかないので、目印に半角空白ではなくタブ文字を利用する環境もあることを意識しておきましょう。単にメール送信するだけなら気にする問題ではありませんが、外部のメール処理プログラムと連携したり、自分でメール解析するような場合は注意が必要です。

MimeUtilityには、foldやunfoldといったそれらしいメソッドがあるので、他にスマートなやり方があるかもしれませんが、備忘も兼ねて。

参考

2行に渡るメールヘッダの正しい処理 http://adiary.blog.abk.nu/0213
RFC2822和訳(2.2 Header Fields) http://www.t-net.ne.jp/~cyfis/rfc/mail/rfc2822_ja-1.html

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10