これはGo2 Advent Calendar 2018の6日目の記事です。
昨日はjoniyjoniyさんの「ちょっと使いやすくしたcutコマンド作成中」でした。
ポイントは2点。
昨日はjoniyjoniyさんの「ちょっと使いやすくしたcutコマンド作成中」でした。
aws-sdk-go/service/ses で添付ファイルを含めて送信する方法が分からん…。🤔
— ザネリ (@so_zaneli) 2018年8月16日
めんどくさすぎたので記事にする。エッ!?何これめんどくさすぎひん???
— ザネリ (@so_zaneli) 2018年8月16日
ポイントは2点。
Credentialsの設定
SESに限らず、AWS SDK for Go で何らかの処理を行う場合、最初にCredentialsを設定したセッションを作成する場合が多い。以下は
~/.aws/credentials
ファイルに設定したaws_access_key_id
とaws_secret_access_key
を使用する例。
s := session.New(&aws.Config{ Region: aws.String("us-east-1"), Credentials: credentials.NewSharedCredentials("", "zaneli"), })しかし、Lambdaで実行する場合、Lambda自体の実行IAMロールに権限を設定する必要があり、Goソースコード内の設定は見ないようだ。
LambdaのIAMロールさえ適切に設定していれば、
nil
でも実行が可能だった。
s := session.New(&aws.Config{ Region: aws.String("us-east-1"), Credentials: nil, })これはめんどくさいというよりは、分かってしまえばそういうものか、といったところだが。
添付メールの送信方法
めんどくさかったのはこちら。通常のメール送信ではSendEmailInputを作ってSendEmailを呼ぶ事になる。
SendEmailInput
には送信元アドレス、送信先アドレス、件名と本文を持つMessageなどを設定できる。さて、肝心の添付ファイルだが、
SendEmailInput
やMessage
のいずれかにファイルパスなり何なりを設定するだけでいけるかと思いきや、探してもそのような項目は用意されていない様子…。
どうやら
SendEmail
とは別の、SendRawEmailInputとSendRawEmailを使う必要があるようだった。SendRawEmailInput
に設定するRawMessageは、件名と本文を持つMessage
とは異なり[]byte
を持つのみ…。「Amazon SES API を使用して raw E メールを送信する」にあるように、
自前でMIMEエンコードしたデータを用意して、それをぶっ込む必要があるようだ…。
高度にカスタマイズしたいなら自分でいかようにでもメッセージを作成できるメリットもありそうだが、
いやいやファイルを添付したいだけっすよ勘弁してくださいよ…と途方にくれていたが、
他のメール送信ライブラリを使ってメッセージを組み立て、そこから
[]byte
を作成する事ができたので一安心。gomailを使い、このようにしてようやくSESでもメール添付する事ができた。
func sendSES(from, to, subject, body string, attachFilePaths ...string) error { tos := strings.Split(to, ",") m := gomail.NewMessage() m.SetHeader("From", from) m.SetHeader("To", tos...) m.SetHeader("Subject", subject) m.SetBody("text/plain", body) for _, attachFilePath := range attachFilePaths { m.Attach(attachFilePath) } var emailRaw bytes.Buffer m.WriteTo(&emailRaw) destinations := make([]*string, len(tos)) for i, to := range tos { destinations[i] = aws.String(fmt.Sprintf("%s <%s>", to, to)) } s := session.New(&aws.Config{ Region: aws.String("us-east-1"), Credentials: nil, }) _, err := ses.New(s).SendRawEmail(&ses.SendRawEmailInput{ RawMessage: &ses.RawMessage{Data: emailRaw.Bytes()}, Source: aws.String(from), Destinations: destinations, }) return err }
m.WriteTo(&emailRaw)
して&ses.RawMessage{Data: emailRaw.Bytes()}
を渡しているところがミソ。ちなみに似たような経験をされている方もいたようで…。
自分でMIMEエンコードするのがめちゃくちゃめんどくさいですよね。自分も昔、エンコードするライブラリを見つけて、それを改造して使いました。https://t.co/QPfrHQt2Jk
— しげっち (@yuunya) 2018年8月16日
これ確かRawなんちゃらかんちゃらで名前のEメールデータ作るってやるしかなかったはず。
— 誰か僕の右股関節と左足首と性根を何とかしてください (@kamekoopa) 2018年8月16日
aws-sdk-go だけで完結するように、gomailみたいなノリで手軽に添付ファイルを設定できませんかね…。これ(https://t.co/Zg3oymfmDh)で、添付ファイルくっつけて、これ(https://t.co/eUrrpaX9l7)で書き出す、みたいなことしたはず、確か。
— 誰か僕の右股関節と左足首と性根を何とかしてください (@kamekoopa) 2018年8月16日
明日はrock619さんの「fmt.Printfなんかこわくない」です。