Created
June 29, 2020 08:16
-
-
Save etowett/9699e8479889d3aecfb87bf24a52d8a8 to your computer and use it in GitHub Desktop.
Lambda function to get email from SES and extract attachment to s3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/json" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"path" | |
"time" | |
"github.com/aws/aws-lambda-go/events" | |
"github.com/aws/aws-lambda-go/lambda" | |
"github.com/aws/aws-sdk-go/aws" | |
"github.com/aws/aws-sdk-go/aws/session" | |
"github.com/aws/aws-sdk-go/service/s3" | |
"github.com/aws/aws-sdk-go/service/ses" | |
enmime "github.com/cention-sany/go.enmime" | |
"github.com/cention-sany/net/mail" | |
) | |
var ( | |
sesClient *ses.SES | |
s3Client *s3.S3 | |
) | |
func main() { | |
s3Region := os.Getenv("AWS_REGION") | |
sess, err := session.NewSession() | |
if err != nil { | |
log.Fatalf("AWS NewSession failed: %s", err) | |
} | |
sesClient = ses.New(sess) | |
s3Client = s3.New(sess, aws.NewConfig().WithRegion(s3Region)) | |
lambda.Start(handler) | |
} | |
func handler(event events.SimpleEmailEvent) error { | |
for _, sesMail := range event.Records { | |
jsonMail, err := json.Marshal(sesMail) | |
if err != nil { | |
log.Printf("failed to json marshal event: %v", err) | |
} | |
log.Printf("sesMail: %v", string(jsonMail)) | |
if err := processMail(&sesMail); err != nil { | |
return err | |
} | |
} | |
return nil | |
} | |
func processMail(original *events.SimpleEmailRecord) error { | |
s3Mail, err := getFromS3(original) | |
if err != nil { | |
return err | |
} | |
defer s3Mail.Close() | |
// parse the original message | |
parsedMail, err := mail.ReadMessage(s3Mail) | |
if err != nil { | |
return fmt.Errorf("ReadMessage failed: %s", err) | |
} | |
mime, err := enmime.ParseMIMEBody(parsedMail) | |
if err != nil { | |
return fmt.Errorf("ParseMIMEBody failed: %s", err) | |
} | |
log.Printf("From: %v", parsedMail.Header.Get("From")) | |
log.Printf("Subject: %v", parsedMail.Header.Get("Subject")) | |
log.Printf("To: %v", parsedMail.Header.Get("To")) | |
log.Printf("Text Body: %v\n", mime.Text) | |
log.Printf("HTML Body: %v\n", mime.HTML) | |
log.Printf("Inlines: %v\n", mime.Inlines) | |
for _, attach := range mime.Attachments { | |
attachmentFile := fmt.Sprintf("%v-%v", time.Now().UnixNano(), attach.FileName()) | |
log.Printf("Uploading : %v to s3\n", attachmentFile) | |
_, err := s3Client.PutObject(&s3.PutObjectInput{ | |
Bucket: aws.String(os.Getenv("S3_BUCKET")), | |
Key: aws.String(attachmentFile), | |
ACL: aws.String("private"), | |
Body: bytes.NewReader(attach.Content()), | |
ContentType: aws.String(attach.ContentType()), | |
ContentDisposition: aws.String(attach.Disposition()), | |
ServerSideEncryption: aws.String("AES256"), | |
StorageClass: aws.String("INTELLIGENT_TIERING"), | |
}) | |
if err != nil { | |
log.Printf("upload to s3 failed: %v\n", err) | |
} | |
} | |
return nil | |
} | |
func getFromS3(original *events.SimpleEmailRecord) (io.ReadCloser, error) { | |
key := path.Join(os.Getenv("S3_PREFIX"), original.SES.Mail.MessageID) | |
obj, err := s3Client.GetObject(&s3.GetObjectInput{ | |
Bucket: aws.String(os.Getenv("S3_BUCKET")), | |
Key: aws.String(key), | |
}) | |
if err != nil { | |
return nil, fmt.Errorf("S3 GetObject failed: %s", err) | |
} | |
return obj.Body, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment