Skip to content

Instantly share code, notes, and snippets.

@carelvwyk
Created February 22, 2018 12:40
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save carelvwyk/60100f2421c6284391d08374bc887dca to your computer and use it in GitHub Desktop.
Save carelvwyk/60100f2421c6284391d08374bc887dca to your computer and use it in GitHub Desktop.
Building an email in Golang to be delivered using Amazon SES
func buildEmailInput(source, destination, subject, message string,
csvFile []byte) (*ses.SendRawEmailInput, error) {
buf := new(bytes.Buffer)
writer := multipart.NewWriter(buf)
// email main header:
h := make(textproto.MIMEHeader)
h.Set("From", source)
h.Set("To", destination)
h.Set("Return-Path", source)
h.Set("Subject", subject)
h.Set("Content-Language", "en-US")
h.Set("Content-Type", "multipart/mixed; boundary=\""+writer.Boundary()+"\"")
h.Set("MIME-Version", "1.0")
_, err := writer.CreatePart(h)
if err != nil {
return nil, err
}
// body:
h = make(textproto.MIMEHeader)
h.Set("Content-Transfer-Encoding", "7bit")
h.Set("Content-Type", "text/plain; charset=us-ascii")
part, err := writer.CreatePart(h)
if err != nil {
return nil, err
}
_, err = part.Write([]byte(message))
if err != nil {
return nil, err
}
// file attachment:
fn := attachmentFilename
h = make(textproto.MIMEHeader)
h.Set("Content-Disposition", "attachment; filename="+fn)
h.Set("Content-Type", "text/csv; x-unix-mode=0644; name=\""+fn+"\"")
h.Set("Content-Transfer-Encoding", "7bit")
part, err = writer.CreatePart(h)
if err != nil {
return nil, err
}
_, err = part.Write(csvFile)
if err != nil {
return nil, err
}
err = writer.Close()
if err != nil {
return nil, err
}
// Strip boundary line before header (doesn't work with it present)
s := buf.String()
if strings.Count(s, "\n") < 2 {
return nil, fmt.Errorf("invalid e-mail content")
}
s = strings.SplitN(s, "\n", 2)[1]
raw := ses.RawMessage{
Data: []byte(s),
}
input := &ses.SendRawEmailInput{
Destinations: []*string{aws.String(destination)},
Source: aws.String(source),
RawMessage: &raw,
}
return input, nil
}
@quentinlesceller
Copy link

Wow, was desperate about sending an email with SES and GO. This literally saved me hours. Thank you so much.

@anujdeshpande
Copy link

You, my good sir, have saved me a lot of head banging today. The AWS docs sent me on a wild goose chase that lasted ages. Cheers!

@gnsx
Copy link

gnsx commented Aug 21, 2019

⭐⭐⭐⭐⭐

@ajain352
Copy link

ajain352 commented Dec 6, 2019

line 38 should be h.Set("Content-Disposition", "attachment; filename=""+fn+""").
Else this fails if file name has chars like @
Though, thanks for the ready made code.

@shackra
Copy link

shackra commented Jul 27, 2020

you may be better using the help of https://pkg.go.dev/github.com/jhillyerd/enmime

You build the email with enmime.EmailBuilder, then get the thing with the .Build attach method and use a buffer from bytes to enmime.Part.Encode the entire thing into the buffer, then you can use that to get the bytes back.

easy peasy!

@shackra
Copy link

shackra commented Dec 18, 2020

I am unable to send attachment with file type other than text/csv. Can anyone please help!!!

be explicit about any error messages or panics, maybe?

@shackra
Copy link

shackra commented Dec 22, 2020

I am unable to send attachment with file type other than text/csv. Can anyone please help!!!

be explicit about any error messages or panics, maybe?

When I try to send a jpeg image with Content-Type value image/jpeg I am getting a Serialization Error with status code 500.
Screenshot 2020-12-19 at 11 42 48 AM

@rishab-zomato better use the library I'm linking on here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment