現象
Spring Boot 2.3.4 (+ spring-boot-starter-mail)で開発したアプリから送信したメールの添付ファイルの名前が文字化けする場合があることに気づきました。
これはOutlookで受信したメールの添付ファイルの表示です。
以下はその簡略化したメール送信コードです。
import org.springframework.mail.javamail.JavaMailSender
import org.springframework.mail.javamail.MimeMessageHelper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class SampleMailApplication : CommandLineRunner {
@Autowired
lateinit var mailSender: JavaMailSender
override fun run(vararg args: String?)
val message = mailSender.createMimeMessage()
val helper = MimeMessageHelper(message, true)
helper.setTo(username)
helper.setFrom(username)
helper.setSubject("送信")
helper.setText("テスト")
helper.addAttachment("あいうえおかきくけこ", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("あいうえおかきくけこさ", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("あいうえおかきくけこさし", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("あいうえおかきくけこさしす", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("あいうえおかきくけこさしすせ", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("1234567890", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("12345678901234567890", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
helper.addAttachment("123456789012345678901234567890", ByteArrayResource("あいうえお".toByteArray()), "plain/text")
mailSender.send(message)
}
}
fun main(args: Array<String>) {
runApplication<SampleMailApplication>(*args)
}
ファイル名が全角13文字以上だと、文字化けというかエンコードされたままの表示になります。
メールの確認
メールのソースでContent-dispositionを確認すると
// あいうえおかきくけこさし
Content-disposition: attachment;
filename*=UTF-8''%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93
// あいうえおかきくけこさしす
Content-disposition: attachment;
filename="=UTF-8B44GC44GE44GG44GI44GK44GL44GN44GP44GR44GT44GV44GX44GZ44Gb="
全角12文字と13文字を境に、属性名がfilenameとfilenameだとか、エンコードされた文字列のフォーマットが変わっていました。
またOutlookで同じ添付ファイルを送ると、当然ファイル名が化けることなく、ソースを確認すると全角13字以上のファイル名でもfilenameのパターンが使われていました。
ソースコードの調査
そこで調べていくとMimeMessageHelperに次のコードがありました。
public void addAttachment(String attachmentFilename, DataSource dataSource) throws MessagingException {
Assert.notNull(attachmentFilename, "Attachment filename must not be null");
Assert.notNull(dataSource, "DataSource must not be null");
try {
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
mimeBodyPart.setFileName(isEncodeFilenames() ?
MimeUtility.encodeText(attachmentFilename) : attachmentFilename);
文字数で処理が分岐する訳ではないですが、フラグでMimeUtility.encodeTextするか制御しているので何かあるのかも?
そこでhelper.addAttachmentを呼び出す前に以下のコードを追加すると、全角13文字以上でもファイル名が化けなくなりました。
helper.isEncodeFilenames = false
- なお、このフラグは丁度Spring Boot 2.3で使われているSpring Framework 5.2から追加されていました。
根本的な原因まで深堀りできませんでしたが、とりあえず解決できたので良しとします。