eintopf.info@v0.13.16/service/email/email.go (about) 1 // Copyright (C) 2023 The Eintopf authors 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16 package email 17 18 import ( 19 "crypto/tls" 20 "fmt" 21 "net" 22 "net/mail" 23 "net/smtp" 24 25 "golang.org/x/exp/slices" 26 ) 27 28 // Config is used to configure the email service. 29 type Config struct { 30 SMTPHost string 31 SMTPPassword string 32 Mail string 33 DisableTLS bool 34 AllowList []string 35 } 36 37 type Service struct { 38 config Config 39 } 40 41 func NewService(config Config) *Service { 42 return &Service{config: config} 43 } 44 45 var ErrDisallowedEmail = fmt.Errorf("email is not in allow list") 46 47 func (s *Service) Send(email, subject, body string) error { 48 if len(s.config.AllowList) > 0 && !slices.Contains(s.config.AllowList, email) { 49 return ErrDisallowedEmail 50 } 51 from := mail.Address{Address: s.config.Mail} 52 to := mail.Address{Address: email} 53 54 // Setup headers 55 headers := map[string]string{ 56 "From": from.String(), 57 "To": to.String(), 58 "MIME-Version": "1.0", 59 "Content-Type": "text/text; charset=utf-8", 60 "Subject": subject, 61 } 62 63 // Setup message 64 message := "" 65 for k, v := range headers { 66 message += fmt.Sprintf("%s: %s\r\n", k, v) 67 } 68 message += "\r\n" + body 69 70 c, err := smtp.Dial(s.config.SMTPHost) 71 if err != nil { 72 return err 73 } 74 75 // TLS 76 host, _, _ := net.SplitHostPort(s.config.SMTPHost) 77 if !s.config.DisableTLS { 78 tlsconfig := &tls.Config{InsecureSkipVerify: true, ServerName: host} 79 if err := c.StartTLS(tlsconfig); err != nil { 80 return err 81 } 82 } 83 84 // Auth 85 if s.config.SMTPPassword != "" { 86 auth := smtp.PlainAuth("", s.config.Mail, s.config.SMTPPassword, host) 87 if err := c.Auth(auth); err != nil { 88 return err 89 } 90 } 91 92 // To && From 93 if err := c.Mail(from.Address); err != nil { 94 return err 95 } 96 if err := c.Rcpt(to.Address); err != nil { 97 return err 98 } 99 100 // Data 101 w, err := c.Data() 102 if err != nil { 103 return err 104 } 105 if _, err := w.Write([]byte(message)); err != nil { 106 return err 107 } 108 if err := w.Close(); err != nil { 109 return err 110 } 111 112 return c.Quit() 113 }