github.com/blend/go-sdk@v1.20240719.1/email/message.go (about) 1 /* 2 3 Copyright (c) 2024 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package email 9 10 import ( 11 "strings" 12 13 "github.com/blend/go-sdk/ex" 14 ) 15 16 // Errors 17 const ( 18 ErrMessageFieldUnset ex.Class = "email; message required field unset" 19 ErrMessageFieldNewlines ex.Class = "email; message field contains newlines" 20 ) 21 22 // MergeMessages merges a given set of messages, such that 23 // messages that appear last override the options in the output 24 // message provided those fields are set. 25 // 26 // If message A has just the `To` field set, and message B 27 // has just the `Subject`field set, and message C also has the 28 // `To` field set, the result of: 29 // 30 // MergeMessages(a,b,c) 31 // 32 // Will be `To` of C, and `Subject` of B, with C overwriting 33 // the `To` of A. 34 func MergeMessages(messages ...Message) (output Message) { 35 for _, message := range messages { 36 if message.From != "" { 37 output.From = message.From 38 } 39 if len(message.To) > 0 { 40 output.To = message.To 41 } 42 if len(message.CC) > 0 { 43 output.To = message.CC 44 } 45 if len(message.BCC) > 0 { 46 output.To = message.BCC 47 } 48 if message.Subject != "" { 49 output.Subject = message.Subject 50 } 51 if message.TextBody != "" { 52 output.TextBody = message.TextBody 53 } 54 if message.HTMLBody != "" { 55 output.HTMLBody = message.HTMLBody 56 } 57 } 58 return 59 } 60 61 // Message is a message to send via. ses. 62 type Message struct { 63 From string `json:"from" yaml:"from"` 64 To []string `json:"to" yaml:"to"` 65 CC []string `json:"cc" yaml:"cc"` 66 BCC []string `json:"bcc" yaml:"bcc"` 67 Subject string `json:"subject" yaml:"subject"` 68 TextBody string `json:"textBody" yaml:"textBody"` 69 HTMLBody string `json:"htmlBody" yaml:"htmlBody"` 70 } 71 72 // IsZero returns if the object is set or not. 73 func (m Message) IsZero() bool { 74 return len(m.To) == 0 75 } 76 77 // Validate checks that a message can be sent. 78 func (m Message) Validate() error { 79 if m.From == "" { 80 return ex.New(ErrMessageFieldUnset, ex.OptMessage("field: from")) 81 } 82 if strings.ContainsAny(m.From, "\r\n") { 83 return ex.New(ErrMessageFieldNewlines, ex.OptMessage("field: from")) 84 } 85 if len(m.To) == 0 { 86 return ex.New(ErrMessageFieldUnset, ex.OptMessage("field: to")) 87 } 88 for index, to := range m.To { 89 if strings.ContainsAny(to, "\r\n") { 90 return ex.New(ErrMessageFieldNewlines, ex.OptMessagef("field: to[%d]", index)) 91 } 92 } 93 for index, cc := range m.CC { 94 if strings.ContainsAny(cc, "\r\n") { 95 return ex.New(ErrMessageFieldNewlines, ex.OptMessagef("field: cc[%d]", index)) 96 } 97 } 98 for index, bcc := range m.BCC { 99 if strings.ContainsAny(bcc, "\r\n") { 100 return ex.New(ErrMessageFieldNewlines, ex.OptMessagef("field: bcc[%d]", index)) 101 } 102 } 103 if strings.ContainsAny(m.Subject, "\r\n") { 104 return ex.New(ErrMessageFieldNewlines, ex.OptMessage("field: subject")) 105 } 106 if len(m.TextBody) == 0 && len(m.HTMLBody) == 0 { 107 return ex.New(ErrMessageFieldUnset, ex.OptMessage("fields: textBody and htmlBody")) 108 } 109 return nil 110 }