github.com/cs3org/reva/v2@v2.27.7/pkg/smtpclient/smtpclient.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package smtpclient 20 21 import ( 22 "bytes" 23 "encoding/base64" 24 "fmt" 25 "net/smtp" 26 "os" 27 "strings" 28 "time" 29 30 "github.com/google/uuid" 31 "github.com/pkg/errors" 32 ) 33 34 // SMTPCredentials stores the credentials required to connect to an SMTP server. 35 type SMTPCredentials struct { 36 SenderLogin string `mapstructure:"sender_login" docs:";The login to be used by sender."` 37 SenderMail string `mapstructure:"sender_mail" docs:";The email to be used to send mails."` 38 SenderPassword string `mapstructure:"sender_password" docs:";The sender's password."` 39 SMTPServer string `mapstructure:"smtp_server" docs:";The hostname of the SMTP server."` 40 SMTPPort int `mapstructure:"smtp_port" docs:"587;The port on which the SMTP daemon is running."` 41 DisableAuth bool `mapstructure:"disable_auth" docs:"false;Whether to disable SMTP auth."` 42 LocalName string `mapstructure:"local_name" docs:";The host name to be used for unauthenticated SMTP."` 43 } 44 45 // NewSMTPCredentials creates a new SMTPCredentials object with the details of the passed object with sane defaults. 46 func NewSMTPCredentials(c *SMTPCredentials) *SMTPCredentials { 47 creds := c 48 49 if creds.SMTPPort == 0 { 50 creds.SMTPPort = 587 51 } 52 if !creds.DisableAuth && creds.SenderPassword == "" { 53 creds.SenderPassword = os.Getenv("REVA_SMTP_SENDER_PASSWORD") 54 } 55 if creds.LocalName == "" { 56 tokens := strings.Split(creds.SenderMail, "@") 57 creds.LocalName = tokens[len(tokens)-1] 58 } 59 if creds.SenderLogin == "" { 60 creds.SenderLogin = creds.SenderMail 61 } 62 return creds 63 } 64 65 // SendMail allows sending mails using a set of client credentials. 66 func (creds *SMTPCredentials) SendMail(recipient, subject, body string) error { 67 68 headers := map[string]string{ 69 "From": creds.SenderMail, 70 "To": recipient, 71 "Subject": subject, 72 "Date": time.Now().Format(time.RFC1123Z), 73 "Message-ID": uuid.New().String(), 74 "MIME-Version": "1.0", 75 "Content-Type": "text/plain; charset=\"utf-8\"", 76 "Content-Transfer-Encoding": "base64", 77 } 78 79 message := "" 80 for k, v := range headers { 81 message += fmt.Sprintf("%s: %s\r\n", k, v) 82 } 83 message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body)) 84 85 if creds.DisableAuth { 86 return creds.sendMailSMTP(recipient, subject, message) 87 } 88 return creds.sendMailAuthSMTP(recipient, subject, message) 89 } 90 91 func (creds *SMTPCredentials) sendMailAuthSMTP(recipient, subject, message string) error { 92 93 auth := smtp.PlainAuth("", creds.SenderLogin, creds.SenderPassword, creds.SMTPServer) 94 95 err := smtp.SendMail( 96 fmt.Sprintf("%s:%d", creds.SMTPServer, creds.SMTPPort), 97 auth, 98 creds.SenderMail, 99 []string{recipient}, 100 []byte(message), 101 ) 102 if err != nil { 103 err = errors.Wrap(err, "smtpclient: error sending mail") 104 return err 105 } 106 107 return nil 108 } 109 110 func (creds *SMTPCredentials) sendMailSMTP(recipient, subject, message string) error { 111 112 c, err := smtp.Dial(fmt.Sprintf("%s:%d", creds.SMTPServer, creds.SMTPPort)) 113 if err != nil { 114 return err 115 } 116 defer c.Close() 117 118 if err = c.Hello(creds.LocalName); err != nil { 119 return err 120 } 121 if err = c.Mail(creds.SenderMail); err != nil { 122 return err 123 } 124 if err = c.Rcpt(recipient); err != nil { 125 return err 126 } 127 128 wc, err := c.Data() 129 if err != nil { 130 return err 131 } 132 defer wc.Close() 133 134 buf := bytes.NewBufferString(message) 135 if _, err = buf.WriteTo(wc); err != nil { 136 return err 137 } 138 139 return nil 140 }