go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/mailer/api.go (about) 1 // Copyright 2021 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package mailer can be used to send mails through a mailer service. 16 // 17 // Install it as a server module and then use Send(...) API. 18 // 19 // Using "gae" backend requires running on GAE and having 20 // "app_engine_apis: true" in the module YAML. 21 // See https://cloud.google.com/appengine/docs/standard/go/services/access. 22 package mailer 23 24 import ( 25 "context" 26 ) 27 28 var mailerCtxKey = "go.chromium.org/luci/server/mailer.Mailer" 29 30 // Mail represents an email message. 31 // 32 // Addresses may be of any form permitted by RFC 822. At least one of To, Cc, 33 // or Bcc must be non-empty. At least one of TextBody or HTMLBody must be 34 // non-empty. 35 type Mail struct { 36 // Sender is put into "From" email header field. 37 // 38 // If empty, some default value will be used. See ModuleOptions. 39 Sender string 40 41 // ReplyTo is put into "Reply-To" email header field. 42 // 43 // Optional. 44 ReplyTo string 45 46 // To is put into "To" email header field. 47 To []string 48 49 // Cc is put into "Cc" email header field. 50 Cc []string 51 52 // Bcc is put into "Bcc" email header field. 53 Bcc []string 54 55 // Subject is put into "Subject" email header field. 56 Subject string 57 58 // TextBody is a plaintext body of the email message. 59 // 60 // Can be used together with HTMLBody to send a multipart email. 61 TextBody string 62 63 // HTMLBody is an HTML body of the email message. 64 // 65 // Can be used together with TextBody to send a multipart email. 66 HTMLBody string 67 } 68 69 // Mailer lives in the context and knows how to send Messages. 70 // 71 // Must tag transient errors with transient.Tag. All other errors are assumed 72 // to be fatal. 73 type Mailer func(ctx context.Context, msg *Mail) error 74 75 // Use replaces the mailer in the context. 76 // 77 // Useful in tests to mock the real mailer. 78 func Use(ctx context.Context, m Mailer) context.Context { 79 return context.WithValue(ctx, &mailerCtxKey, m) 80 } 81 82 // Send sends the given message through a mailer client in the context. 83 // 84 // Panics if the context doesn't have a mailer. Transient errors are tagged with 85 // transient.Tag. All other errors are fatal and should not be retried. 86 func Send(ctx context.Context, msg *Mail) error { 87 m, _ := ctx.Value(&mailerCtxKey).(Mailer) 88 if m == nil { 89 panic("no mailer in the context") 90 } 91 return m(ctx, msg) 92 }