// Copyright 2011 Google Inc. All rights reserved. // Use of this source code is governed by the Apache 2.0 // license that can be found in the LICENSE file. /* Package mail provides the means of sending email from an App Engine application. Example: msg := &mail.Message{ Sender: "romeo@montague.com", To: []string{"Juliet "}, Subject: "See you tonight", Body: "Don't forget our plans. Hark, 'til later.", } if err := mail.Send(c, msg); err != nil { log.Errorf(c, "Alas, my user, the email failed to sendeth: %v", err) } */ package mail // import "google.golang.org/appengine/mail" import ( "net/mail" "github.com/golang/protobuf/proto" "golang.org/x/net/context" "google.golang.org/appengine/internal" bpb "google.golang.org/appengine/internal/base" pb "google.golang.org/appengine/internal/mail" ) // A Message represents an email message. // Addresses may be of any form permitted by RFC 822. type Message struct { // Sender must be set, and must be either an application admin // or the currently signed-in user. Sender string ReplyTo string // may be empty // At least one of these slices must have a non-zero length, // except when calling SendToAdmins. To, Cc, Bcc []string Subject string // At least one of Body or HTMLBody must be non-empty. Body string HTMLBody string Attachments []Attachment // Extra mail headers. // See https://cloud.google.com/appengine/docs/standard/go/mail/ // for permissible headers. Headers mail.Header } // An Attachment represents an email attachment. type Attachment struct { // Name must be set to a valid file name. Name string Data []byte ContentID string } // Send sends an email message. func Send(c context.Context, msg *Message) error { return send(c, "Send", msg) } // SendToAdmins sends an email message to the application's administrators. func SendToAdmins(c context.Context, msg *Message) error { return send(c, "SendToAdmins", msg) } func send(c context.Context, method string, msg *Message) error { req := &pb.MailMessage{ Sender: &msg.Sender, To: msg.To, Cc: msg.Cc, Bcc: msg.Bcc, Subject: &msg.Subject, } if msg.ReplyTo != "" { req.ReplyTo = &msg.ReplyTo } if msg.Body != "" { req.TextBody = &msg.Body } if msg.HTMLBody != "" { req.HtmlBody = &msg.HTMLBody } if len(msg.Attachments) > 0 { req.Attachment = make([]*pb.MailAttachment, len(msg.Attachments)) for i, att := range msg.Attachments { req.Attachment[i] = &pb.MailAttachment{ FileName: proto.String(att.Name), Data: att.Data, } if att.ContentID != "" { req.Attachment[i].ContentID = proto.String(att.ContentID) } } } for key, vs := range msg.Headers { for _, v := range vs { req.Header = append(req.Header, &pb.MailHeader{ Name: proto.String(key), Value: proto.String(v), }) } } res := &bpb.VoidProto{} if err := internal.Call(c, "mail", method, req, res); err != nil { return err } return nil } func init() { internal.RegisterErrorCodeMap("mail", pb.MailServiceError_ErrorCode_name) }