github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/state/impl_send_mail_storage.go (about) 1 /* 2 * Copyright (c) 2022-present unTill Pro, Ltd. 3 */ 4 5 package state 6 7 import ( 8 "fmt" 9 10 "github.com/voedger/voedger/pkg/appdef" 11 "github.com/voedger/voedger/pkg/goutils/logger" 12 "github.com/voedger/voedger/pkg/istructs" 13 "github.com/voedger/voedger/pkg/state/smtptest" 14 coreutils "github.com/voedger/voedger/pkg/utils" 15 "github.com/wneessen/go-mail" 16 ) 17 18 type sendMailStorage struct { 19 messages chan smtptest.Message // not nil in tests only 20 } 21 22 type sendMailValueBuilder struct { 23 istructs.IStateValueBuilder 24 } 25 26 func (s *sendMailStorage) NewKeyBuilder(appdef.QName, istructs.IStateKeyBuilder) istructs.IStateKeyBuilder { 27 return &sendMailKeyBuilder{ 28 keyBuilder: newKeyBuilder(SendMail, appdef.NullQName), 29 to: make([]string, 0), 30 cc: make([]string, 0), 31 bcc: make([]string, 0), 32 } 33 } 34 func (s *sendMailStorage) Validate(items []ApplyBatchItem) (err error) { 35 for _, item := range items { 36 k := item.key.(*sendMailKeyBuilder) 37 38 mustExist := func(field string) (err error) { 39 _, ok := k.data[field] 40 if !ok { 41 return fmt.Errorf("'%s': %w", field, ErrNotFound) 42 } 43 return 44 } 45 46 err = mustExist(Field_Host) 47 if err != nil { 48 return 49 } 50 err = mustExist(Field_Port) 51 if err != nil { 52 return 53 } 54 err = mustExist(Field_Username) 55 if err != nil { 56 return 57 } 58 err = mustExist(Field_Password) 59 if err != nil { 60 return 61 } 62 err = mustExist(Field_From) 63 if err != nil { 64 return 65 } 66 if len(item.key.(*sendMailKeyBuilder).to) == 0 { 67 return fmt.Errorf("'%s': %w", Field_To, ErrNotFound) 68 } 69 } 70 return nil 71 } 72 func (s *sendMailStorage) ApplyBatch(items []ApplyBatchItem) (err error) { 73 stringOrEmpty := func(k *sendMailKeyBuilder, name string) string { 74 if intf, ok := k.data[name]; ok { 75 return intf.(string) 76 } 77 return "" 78 } 79 for _, item := range items { 80 k := item.key.(*sendMailKeyBuilder) 81 82 msg := mail.NewMsg() 83 msg.Subject(stringOrEmpty(k, Field_Subject)) 84 err = msg.From(k.data[Field_From].(string)) 85 if err != nil { 86 return 87 } 88 err = msg.To(k.to...) 89 if err != nil { 90 return 91 } 92 err = msg.Cc(k.cc...) 93 if err != nil { 94 return 95 } 96 err = msg.Bcc(k.bcc...) 97 if err != nil { 98 return 99 } 100 msg.SetBodyString(mail.TypeTextHTML, stringOrEmpty(k, Field_Body)) 101 msg.SetCharset(mail.CharsetUTF8) 102 103 opts := []mail.Option{ 104 mail.WithPort(int(k.data[Field_Port].(int32))), 105 mail.WithUsername(k.data[Field_Username].(string)), 106 mail.WithPassword(k.data[Field_Password].(string)), 107 mail.WithSMTPAuth(mail.SMTPAuthPlain), 108 } 109 110 if coreutils.IsTest() { 111 opts = append(opts, mail.WithTLSPolicy(mail.NoTLS)) 112 } 113 114 logger.Info(fmt.Sprintf("send mail '%s' from '%s' to %s, cc %s, bcc %s", stringOrEmpty(k, Field_Subject), k.data[Field_From], k.to, k.cc, k.bcc)) 115 116 if s.messages != nil { 117 // happens in tests only 118 m := smtptest.Message{ 119 Subject: stringOrEmpty(k, Field_Subject), 120 From: k.data[Field_From].(string), 121 To: k.to, 122 CC: k.cc, 123 BCC: k.bcc, 124 Body: stringOrEmpty(k, Field_Body), 125 } 126 s.messages <- m 127 } else { 128 c, e := mail.NewClient(k.data[Field_Host].(string), opts...) 129 if e != nil { 130 return e 131 } 132 err = c.DialAndSend(msg) 133 if err != nil { 134 return err 135 } 136 } 137 138 logger.Info(fmt.Sprintf("mail '%s' from '%s' to %s, cc %s, bcc %s successfully sent", stringOrEmpty(k, Field_Subject), k.data[Field_From], k.to, k.cc, k.bcc)) 139 } 140 return nil 141 } 142 func (s *sendMailStorage) ProvideValueBuilder(istructs.IStateKeyBuilder, istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 143 return &sendMailValueBuilder{}, nil 144 }