📩

【Amazon SES/Go】メールの送信者名に日本語を含めたい

2022/09/10に公開

AWS SDK for Go を使って Amazon SES のメール送信を実行する際に、送信者名に含めた日本語が文字化けして困ったので解決方法をまとめます。
(日本語というかマルチバイト文字です)

先に結論

mimeパッケージを使ってエンコードする必要があります。
次項以降でサンプルコードも紹介しつつ説明します。
https://pkg.go.dev/mime

エンコードしないと何が起きるのか

送信者名を指定するフィールドのSource*stringだったので、何も考えずに文字列を渡して実装しました。

main.go
package main

import (
	"fmt"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ses"
)

func main() {
	sess := session.Must(session.NewSession(&aws.Config{Region: aws.String("ap-northeast-1")}))
	svc := ses.New(sess)

	input := new(ses.SendEmailInput)

	// サンプルのメールアドレス
	input.SetDestination(&ses.Destination{
		ToAddresses: []*string{
			aws.String("recipient@example.com"),
		},
	})

	input.SetMessage(&ses.Message{
		Body: &ses.Body{
			Text: &ses.Content{
				Data: aws.String("ぼでぃ"),
			},
		},
		Subject: &ses.Content{
			Data: aws.String("さぶじぇくと"),
		},
	})

	// サンプルのメールアドレス
	input.SetSource("そうしんしゃ<sender@example.com>")

	_, err := svc.SendEmail(input)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Println("Success")
}

しかし届いたメールは以下の画像の通りです。

ここで僕は生まれて初めて送信者名が文字化けしたメールを目にするのでした。

原因並びに解決法の調査

SDKはコメントがしっかり目に書いてあるので何か解決の糸口となるヒントはないかと、Sourceフィールドコメントの関連がありそうな部分に目を通してみます。

(一部略)
// Amazon SES does not support the SMTPUTF8 extension, as described in RFC6531
// (https://tools.ietf.org/html/rfc6531). For this reason, the local part of
// a source email address (the part of the email address that precedes the @
// sign) may only contain 7-bit ASCII characters (https://en.wikipedia.org/wiki/Email_address#Local-part).
// If the domain part of an address (the part after the @ sign) contains non-ASCII
// characters, they must be encoded using Punycode, as described in RFC3492
// (https://tools.ietf.org/html/rfc3492.html). The sender name (also known as
// the friendly name) may contain non-ASCII characters. These characters must
// be encoded using MIME encoded-word syntax, as described in RFC 2047 (https://tools.ietf.org/html/rfc2047).
// MIME encoded-word syntax uses the following form: =?charset?encoding?encoded-text?=.

https://pkg.go.dev/github.com/aws/aws-sdk-go/service/ses#SendEmailInput

抜粋部分をまとめると。

  • ローカルパート(@より前)は7-bit ASCIIのみ可。
  • ドメインパート(@より後ろ)に非ASCIIが含まれる場合は、Punycodeエンコードを使用する必要有。
  • 送信者名に非ASCIIが含まれる場合はMIMEエンコードを使用する必要有。

MIMEエンコードした上でSourceに渡してあげると良さそうです。

またコメントにURLが記載されていたRFC2047に目を通すと、MIMEエンコードの中でもQエンコードとBエンコードがあり、エンコード対象の文字列のほとんどがASCIIの場合にはQエンコード、そうでなければBエンコードを使うべきとのことです。

実装を修正する

GoでMIMEエンコードを使用するには、mimeパッケージを使用します。
今回はBエンコードを選択するので、WordEncoder型の定数BEncodingEncodeメソッドでエンコードして、エンコードされた文字列とローカルパート、ドメインパートを結合してSourceに渡してあげます。

 import (
 	"fmt"
+	"mime"
 	"os"
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/service/ses"
 )
 
 	// サンプルのメールアドレス
+	encoded := mime.BEncoding.Encode("utf-8", "そうしんしゃ")
+	source := encoded + "<sender@example.com>"
+	input.SetSource(source)
-	input.SetSource("そうしんしゃ<sender@example.com>")

修正したものを実行してみます。

無事送信者名が表示されました。

まとめ

実装する前にGodocに目を通そう。

参考

GitHubで編集を提案

Discussion