I'm trying to send an email via AWS pinpoint containing attachments. To send attachments with an email, you must use the 'RAW' email content. The only documentation I can find about this is here: https://docs.aws.amazon.com/pinpoint-email/latest/APIReference/API_RawMessage.html, but it is missing quite a few things (like, what are the required headers?)
When I send an email using the 'simple' content, it works fine:
emailInput := &pinpointemail.SendEmailInput{
Destination: &pinpointemail.Destination{
ToAddresses: []*string{&address},
},
FromEmailAddress: &sender,
Content: &pinpointemail.EmailContent{
Simple: &pinpointemail.Message{
Body: &pinpointemail.Body{
Html: &pinpointemail.Content{
Charset: &charset,
Data: &emailHTML,
},
Text: &pinpointemail.Content{
Charset: &charset,
Data: &emailText,
},
},
Subject: &pinpointemail.Content{
Charset: &charset,
Data: &emailSubject,
},
},
}
Since I want to add attachments, I have to use the 'RAW' content type. I have written a function which generates the email content, based on: https://gist.github.com/douglasmakey/90753ecf37ac10c25873825097f46300:
func generateRawEmailContent(subject, to, from, HTMLBody string, attachments *[]EmailAttachment) []byte {
buf := bytes.NewBuffer(nil)
buf.WriteString(fmt.Sprintf("Subject: %s\n", subject))
buf.WriteString(fmt.Sprintf("To: %s\n", to))
buf.WriteString(fmt.Sprintf("From: %s\n\n", from))
buf.WriteString("MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n")
buf.WriteString(HTMLBody)
writer := multipart.NewWriter(buf)
boundary := writer.Boundary()
buf.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s\n", boundary))
buf.WriteString(fmt.Sprintf("--%s\n", boundary))
for _, attachment := range *attachments {
buf.WriteString(fmt.Sprintf("\n\n--%s\n", boundary))
buf.WriteString(fmt.Sprintf("Content-Type: %s\n", http.DetectContentType(attachment.Data)))
buf.WriteString("Content-Transfer-Encoding: base64\n")
buf.WriteString(fmt.Sprintf("Content-Disposition: attachment; filename=%s\n", attachment.FileName))
b := make([]byte, base64.StdEncoding.EncodedLen(len(attachment.Data)))
base64.StdEncoding.Encode(b, attachment.Data)
buf.Write(b)
buf.WriteString(fmt.Sprintf("\n--%s", boundary))
}
buf.WriteString("--")
log.Println(string(buf.Bytes()))
return buf.Bytes()
}
This generates the following (emails changed):
Subject: Welcome \nTo: xxxxx@gmail.com\nFrom: xxxxx@gmail.com\n\nMIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n\u003ch1\u003eHello ,\u003c/h1\u003e\u003cp\u003eYou now have an account.\u003c/p\u003e\nContent-Type: multipart/mixed; boundary=8f6b2cc498b79f5a99550b930ba1ecab1fc1ee2d3425a0a69ab67b83b647\n--8f6b2cc498b79f5a99550b930ba1ecab1fc1ee2d3425a0a69ab67b83b647\n\n\n--8f6b2cc498b79f5a99550b930ba1ecab1fc1ee2d3425a0a69ab67b83b647\nContent-Type: text/plain; charset=utf-8\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment; filename=test.json\newogICJ0ZXN0IjogdHJ1ZQp9\n--8f6b2cc498b79f5a99550b930ba1ecab1fc1ee2d3425a0a69ab67b83b647--
I then construct the email as follows:
&pinpointemail.SendEmailInput{
Destination: &pinpointemail.Destination{
ToAddresses: []*string{&address},
},
FromEmailAddress: &sender,
Content: &pinpointemail.EmailContent{
Raw: &pinpointemail.RawMessage{
Data: generateRawEmailContent(emailSubject, address, sender, emailHTML, emailAttachments),
},
}
When sending this email via the github.com/aws/aws-sdk-go/service/pinpoint
package, I get a 403 returned, and I have no idea why. A 403 means that the resource I'm trying to access is forbidden, but I don't see how that is relevant here? Also, there is no documentation about a 403 even being a possible response. Any help would be greatly appreciated!
I have also tried using libraries, like for instance the gomail-v2 library as follows:
m := gomail.NewMessage()
m.SetHeader("From", from)
m.SetHeader("To", to)
m.SetHeader("Subject", subject)
m.SetBody("text/plain", textBody)
m.AddAlternative("text/html", HTMLBody)
m.Attach("foo.txt", gomail.SetCopyFunc(func(w io.Writer) error {
_, err := w.Write((*attachments)[0].Data)
return err
}))
buf := bytes.NewBuffer(make([]byte, 0, 2048))
_, werr := m.WriteTo(buf)
if werr != nil {
return nil, common.NewStackError(werr)
}
But that still gives me a 403 error.