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  }