• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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