go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gae/service/mail/message.go (about)

     1  // Copyright 2015 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 mail
    16  
    17  import (
    18  	"fmt"
    19  	net_mail "net/mail"
    20  	"reflect"
    21  
    22  	"google.golang.org/appengine/mail"
    23  )
    24  
    25  // Attachment is a mimic of https://godoc.org/google.golang.org/appengine/mail#Attachment
    26  //
    27  // It's provided here for convenience, and is compile-time checked to be
    28  // identical.
    29  type Attachment struct {
    30  	// Name must be set to a valid file name.
    31  	Name      string
    32  	Data      []byte
    33  	ContentID string
    34  }
    35  
    36  var _ Attachment = (Attachment)(mail.Attachment{})
    37  
    38  // Message is a mimic of https://godoc.org/google.golang.org/appengine/mail#Message
    39  //
    40  // It's provided here for convenience, and is init-time checked to be identical
    41  // (not statically because []Attachement prevents static casting).
    42  type Message struct {
    43  	Sender      string
    44  	ReplyTo     string
    45  	To, Cc, Bcc []string
    46  	Subject     string
    47  	Body        string
    48  	HTMLBody    string
    49  	Attachments []Attachment
    50  	Headers     net_mail.Header
    51  }
    52  
    53  func init() {
    54  	mt := reflect.TypeOf(mail.Message{})
    55  	ot := reflect.TypeOf(Message{})
    56  	if mt.NumField() != ot.NumField() {
    57  		panic(fmt.Errorf("mismatched number of fields %s v %s", mt, ot))
    58  	}
    59  
    60  	for i := 0; i < mt.NumField(); i++ {
    61  		mf := mt.Field(i)
    62  		of := mt.Field(i)
    63  		if mf.Name != of.Name {
    64  			panic(fmt.Errorf("mismatched names %s v %s", mf.Name, of.Name))
    65  		}
    66  		if mf.Name == "Attachments" {
    67  			if !mf.Type.Elem().ConvertibleTo(of.Type.Elem()) {
    68  				panic(fmt.Errorf("mismatched element type for Attachments %s v %s",
    69  					mf.Type, of.Type))
    70  			}
    71  		} else {
    72  			if mf.Type != of.Type {
    73  				panic(fmt.Errorf("mismatched type for field %s: %s v %s", mf.Name, mf.Type, of.Type))
    74  			}
    75  		}
    76  	}
    77  }
    78  
    79  func dupStrs(strs []string) []string {
    80  	if len(strs) > 0 {
    81  		ret := make([]string, len(strs))
    82  		copy(ret, strs)
    83  		return ret
    84  	}
    85  	return nil
    86  }
    87  
    88  // ToSDKMessage returns a copy of this Message that's compatible with the native
    89  // SDK's Message type. It only needs to be used by implementations (like
    90  // "impl/prod") which need an SDK compatible object
    91  func (m *Message) ToSDKMessage() *mail.Message {
    92  	if m == nil {
    93  		return nil
    94  	}
    95  
    96  	m = m.Copy()
    97  
    98  	ret := &mail.Message{
    99  		Sender:   m.Sender,
   100  		ReplyTo:  m.ReplyTo,
   101  		Subject:  m.Subject,
   102  		Body:     m.Body,
   103  		HTMLBody: m.HTMLBody,
   104  		To:       m.To,
   105  		Cc:       m.Cc,
   106  		Bcc:      m.Bcc,
   107  		Headers:  m.Headers,
   108  	}
   109  
   110  	ret.Attachments = make([]mail.Attachment, len(m.Attachments))
   111  	for i := range m.Attachments {
   112  		ret.Attachments[i] = (mail.Attachment)(m.Attachments[i])
   113  	}
   114  	return ret
   115  }
   116  
   117  // Copy returns a duplicate Message
   118  func (m *Message) Copy() *Message {
   119  	if m == nil {
   120  		return nil
   121  	}
   122  
   123  	ret := *m
   124  
   125  	ret.To = dupStrs(m.To)
   126  	ret.Cc = dupStrs(m.Cc)
   127  	ret.Bcc = dupStrs(m.Bcc)
   128  
   129  	if len(m.Headers) > 0 {
   130  		ret.Headers = make(net_mail.Header, len(m.Headers))
   131  		for k, vals := range m.Headers {
   132  			ret.Headers[k] = dupStrs(vals)
   133  		}
   134  	}
   135  
   136  	if len(m.Attachments) > 0 {
   137  		ret.Attachments = make([]Attachment, len(m.Attachments))
   138  		copy(ret.Attachments, m.Attachments)
   139  	}
   140  
   141  	return &ret
   142  }