1// Copyright 2011 Google Inc. All rights reserved. 2// Use of this source code is governed by the Apache 2.0 3// license that can be found in the LICENSE file. 4 5/* 6Package mail provides the means of sending email from an 7App Engine application. 8 9Example: 10 msg := &mail.Message{ 11 Sender: "romeo@montague.com", 12 To: []string{"Juliet <juliet@capulet.org>"}, 13 Subject: "See you tonight", 14 Body: "Don't forget our plans. Hark, 'til later.", 15 } 16 if err := mail.Send(c, msg); err != nil { 17 log.Errorf(c, "Alas, my user, the email failed to sendeth: %v", err) 18 } 19*/ 20package mail 21 22import ( 23 "net/mail" 24 25 "github.com/golang/protobuf/proto" 26 "golang.org/x/net/context" 27 28 "google.golang.org/appengine/internal" 29 bpb "google.golang.org/appengine/internal/base" 30 pb "google.golang.org/appengine/internal/mail" 31) 32 33// A Message represents an email message. 34// Addresses may be of any form permitted by RFC 822. 35type Message struct { 36 // Sender must be set, and must be either an application admin 37 // or the currently signed-in user. 38 Sender string 39 ReplyTo string // may be empty 40 41 // At least one of these slices must have a non-zero length, 42 // except when calling SendToAdmins. 43 To, Cc, Bcc []string 44 45 Subject string 46 47 // At least one of Body or HTMLBody must be non-empty. 48 Body string 49 HTMLBody string 50 51 Attachments []Attachment 52 53 // Extra mail headers. 54 // See https://cloud.google.com/appengine/docs/standard/go/mail/ 55 // for permissible headers. 56 Headers mail.Header 57} 58 59// An Attachment represents an email attachment. 60type Attachment struct { 61 // Name must be set to a valid file name. 62 Name string 63 Data []byte 64 ContentID string 65} 66 67// Send sends an email message. 68func Send(c context.Context, msg *Message) error { 69 return send(c, "Send", msg) 70} 71 72// SendToAdmins sends an email message to the application's administrators. 73func SendToAdmins(c context.Context, msg *Message) error { 74 return send(c, "SendToAdmins", msg) 75} 76 77func send(c context.Context, method string, msg *Message) error { 78 req := &pb.MailMessage{ 79 Sender: &msg.Sender, 80 To: msg.To, 81 Cc: msg.Cc, 82 Bcc: msg.Bcc, 83 Subject: &msg.Subject, 84 } 85 if msg.ReplyTo != "" { 86 req.ReplyTo = &msg.ReplyTo 87 } 88 if msg.Body != "" { 89 req.TextBody = &msg.Body 90 } 91 if msg.HTMLBody != "" { 92 req.HtmlBody = &msg.HTMLBody 93 } 94 if len(msg.Attachments) > 0 { 95 req.Attachment = make([]*pb.MailAttachment, len(msg.Attachments)) 96 for i, att := range msg.Attachments { 97 req.Attachment[i] = &pb.MailAttachment{ 98 FileName: proto.String(att.Name), 99 Data: att.Data, 100 } 101 if att.ContentID != "" { 102 req.Attachment[i].ContentID = proto.String(att.ContentID) 103 } 104 } 105 } 106 for key, vs := range msg.Headers { 107 for _, v := range vs { 108 req.Header = append(req.Header, &pb.MailHeader{ 109 Name: proto.String(key), 110 Value: proto.String(v), 111 }) 112 } 113 } 114 res := &bpb.VoidProto{} 115 if err := internal.Call(c, "mail", method, req, res); err != nil { 116 return err 117 } 118 return nil 119} 120 121func init() { 122 internal.RegisterErrorCodeMap("mail", pb.MailServiceError_ErrorCode_name) 123} 124