code.gitea.io/gitea@v1.19.3/modules/log/smtp.go (about) 1 // Copyright 2014 The Gogs Authors. All rights reserved. 2 // Copyright 2019 The Gitea Authors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 5 package log 6 7 import ( 8 "fmt" 9 "net/smtp" 10 "strings" 11 12 "code.gitea.io/gitea/modules/json" 13 ) 14 15 type smtpWriter struct { 16 owner *SMTPLogger 17 } 18 19 // Write sends the message as an email 20 func (s *smtpWriter) Write(p []byte) (int, error) { 21 return s.owner.sendMail(p) 22 } 23 24 // Close does nothing 25 func (s *smtpWriter) Close() error { 26 return nil 27 } 28 29 // SMTPLogger implements LoggerProvider and is used to send emails via given SMTP-server. 30 type SMTPLogger struct { 31 WriterLogger 32 Username string `json:"Username"` 33 Password string `json:"password"` 34 Host string `json:"host"` 35 Subject string `json:"subject"` 36 RecipientAddresses []string `json:"sendTos"` 37 sendMailFn func(string, smtp.Auth, string, []string, []byte) error 38 } 39 40 // NewSMTPLogger creates smtp writer. 41 func NewSMTPLogger() LoggerProvider { 42 s := &SMTPLogger{} 43 s.Level = TRACE 44 s.sendMailFn = smtp.SendMail 45 return s 46 } 47 48 // Init smtp writer with json config. 49 // config like: 50 // 51 // { 52 // "Username":"example@gmail.com", 53 // "password:"password", 54 // "host":"smtp.gmail.com:465", 55 // "subject":"email title", 56 // "sendTos":["email1","email2"], 57 // "level":LevelError 58 // } 59 func (log *SMTPLogger) Init(jsonconfig string) error { 60 err := json.Unmarshal([]byte(jsonconfig), log) 61 if err != nil { 62 return fmt.Errorf("Unable to parse JSON: %w", err) 63 } 64 log.NewWriterLogger(&smtpWriter{ 65 owner: log, 66 }) 67 log.sendMailFn = smtp.SendMail 68 return nil 69 } 70 71 // WriteMsg writes message in smtp writer. 72 // it will send an email with subject and only this message. 73 func (log *SMTPLogger) sendMail(p []byte) (int, error) { 74 hp := strings.Split(log.Host, ":") 75 76 // Set up authentication information. 77 auth := smtp.PlainAuth( 78 "", 79 log.Username, 80 log.Password, 81 hp[0], 82 ) 83 // Connect to the server, authenticate, set the sender and recipient, 84 // and send the email all in one step. 85 contentType := "Content-Type: text/plain" + "; charset=UTF-8" 86 mailmsg := []byte("To: " + strings.Join(log.RecipientAddresses, ";") + "\r\nFrom: " + log.Username + "<" + log.Username + 87 ">\r\nSubject: " + log.Subject + "\r\n" + contentType + "\r\n\r\n") 88 mailmsg = append(mailmsg, p...) 89 return len(p), log.sendMailFn( 90 log.Host, 91 auth, 92 log.Username, 93 log.RecipientAddresses, 94 mailmsg, 95 ) 96 } 97 98 // Content returns the content accumulated in the content provider 99 func (log *SMTPLogger) Content() (string, error) { 100 return "", fmt.Errorf("not supported") 101 } 102 103 // Flush when log should be flushed 104 func (log *SMTPLogger) Flush() { 105 } 106 107 // ReleaseReopen does nothing 108 func (log *SMTPLogger) ReleaseReopen() error { 109 return nil 110 } 111 112 // GetName returns the default name for this implementation 113 func (log *SMTPLogger) GetName() string { 114 return "smtp" 115 } 116 117 func init() { 118 Register("smtp", NewSMTPLogger) 119 }