github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/framework/logs/log_email.go (about) 1 // the package is exported from github.com/beego/beego/v2/core/logs 2 3 // Copyright 2023. All Rights Reserved. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package logs 18 19 import ( 20 "crypto/tls" 21 "encoding/json" 22 "fmt" 23 "net" 24 "net/smtp" 25 "strings" 26 27 "github.com/pkg/errors" 28 ) 29 30 // SMTPWriter implements LoggerInterface and is used to send emails via given SMTP-server. 31 type SMTPWriter struct { 32 Username string `json:"username"` 33 Password string `json:"password"` 34 Host string `json:"host"` 35 Subject string `json:"subject"` 36 FromAddress string `json:"fromAddress"` 37 RecipientAddresses []string `json:"sendTos"` 38 Level int `json:"level"` 39 formatter LogFormatter 40 Formatter string `json:"formatter"` 41 } 42 43 // NewSMTPWriter creates the smtp writer. 44 func newSMTPWriter() Logger { 45 res := &SMTPWriter{Level: LevelTrace} 46 res.formatter = res 47 return res 48 } 49 50 // Init smtp writer with json config. 51 // config like: 52 // 53 // { 54 // "username":"example@gmail.com", 55 // "password:"password", 56 // "host":"smtp.gmail.com:465", 57 // "subject":"email title", 58 // "fromAddress":"from@example.com", 59 // "sendTos":["email1","email2"], 60 // "level":LevelError 61 // } 62 func (s *SMTPWriter) Init(config string) error { 63 res := json.Unmarshal([]byte(config), s) 64 if res == nil && len(s.Formatter) > 0 { 65 fmtr, ok := GetFormatter(s.Formatter) 66 if !ok { 67 return errors.New(fmt.Sprintf("the formatter with name: %s not found", s.Formatter)) 68 } 69 s.formatter = fmtr 70 } 71 return res 72 } 73 74 func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth { 75 if len(strings.Trim(s.Username, " ")) == 0 && len(strings.Trim(s.Password, " ")) == 0 { 76 return nil 77 } 78 return smtp.PlainAuth( 79 "", 80 s.Username, 81 s.Password, 82 host, 83 ) 84 } 85 86 func (s *SMTPWriter) SetFormatter(f LogFormatter) { 87 s.formatter = f 88 } 89 90 func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAddress string, recipients []string, msgContent []byte) error { 91 client, err := smtp.Dial(hostAddressWithPort) 92 if err != nil { 93 return err 94 } 95 96 host, _, _ := net.SplitHostPort(hostAddressWithPort) 97 tlsConn := &tls.Config{ 98 InsecureSkipVerify: true, 99 ServerName: host, 100 } 101 if err = client.StartTLS(tlsConn); err != nil { 102 return err 103 } 104 105 if auth != nil { 106 if err = client.Auth(auth); err != nil { 107 return err 108 } 109 } 110 111 if err = client.Mail(fromAddress); err != nil { 112 return err 113 } 114 115 for _, rec := range recipients { 116 if err = client.Rcpt(rec); err != nil { 117 return err 118 } 119 } 120 121 w, err := client.Data() 122 if err != nil { 123 return err 124 } 125 _, err = w.Write(msgContent) 126 if err != nil { 127 return err 128 } 129 130 err = w.Close() 131 if err != nil { 132 return err 133 } 134 135 return client.Quit() 136 } 137 138 func (s *SMTPWriter) Format(lm *LogMsg) string { 139 return lm.OldStyleFormat() 140 } 141 142 // WriteMsg writes message in smtp writer. 143 // Sends an email with subject and only this message. 144 func (s *SMTPWriter) WriteMsg(lm *LogMsg) error { 145 if lm.Level > s.Level && lm.Level != LeverPerformance { 146 return nil 147 } 148 149 hp := strings.Split(s.Host, ":") 150 151 // Set up authentication information. 152 auth := s.getSMTPAuth(hp[0]) 153 154 msg := s.Format(lm) 155 156 // Connect to the server, authenticate, set the sender and recipient, 157 // and send the email all in one step. 158 contentType := "Content-Type: text/plain" + "; charset=UTF-8" 159 mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress + 160 ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", lm.When.Format("2006-01-02 15:04:05")) + msg) 161 162 return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg) 163 } 164 165 // Flush implementing method. empty. 166 func (s *SMTPWriter) Flush() { 167 } 168 169 // Destroy implementing method. empty. 170 func (s *SMTPWriter) Destroy() { 171 } 172 173 func init() { 174 Register(AdapterMail, newSMTPWriter) 175 }