これはGo2 Advent Calendar 2018の6日目の記事です。
昨日はjoniyjoniyさんの「ちょっと使いやすくしたcutコマンド作成中」でした。

めんどくさすぎたので記事にする。
ポイントは2点。

Credentialsの設定

SESに限らず、AWS SDK for Go で何らかの処理を行う場合、最初にCredentialsを設定したセッションを作成する場合が多い。
以下は~/.aws/credentialsファイルに設定したaws_access_key_idaws_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などを設定できる。
さて、肝心の添付ファイルだが、SendEmailInputMessageのいずれかにファイルパスなり何なりを設定するだけでいけるかと思いきや、
探してもそのような項目は用意されていない様子…。

どうやらSendEmailとは別の、SendRawEmailInputSendRawEmailを使う必要があるようだった。
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()}を渡しているところがミソ。

ちなみに似たような経験をされている方もいたようで…。
aws-sdk-go だけで完結するように、gomailみたいなノリで手軽に添付ファイルを設定できませんかね…。

明日はrock619さんの「fmt.Printfなんかこわくない」です。

Copyright© 2011-2021 Shunsuke Otani All Right Reserved .