diff options
Diffstat (limited to 'modules/mailer/mailer.go')
-rw-r--r-- | modules/mailer/mailer.go | 71 |
1 files changed, 51 insertions, 20 deletions
diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go index 474e1481..e2d185d8 100644 --- a/modules/mailer/mailer.go +++ b/modules/mailer/mailer.go @@ -8,6 +8,7 @@ import ( "crypto/tls" "fmt" "net" + "net/mail" "net/smtp" "strings" @@ -20,7 +21,6 @@ type Message struct { From string Subject string Body string - User string Type string Massive bool Info string @@ -35,8 +35,7 @@ func (m Message) Content() string { } // create mail content - content := "From: \"" + m.From + "\" <" + m.User + - ">\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body + content := "From: " + m.From + "\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body return content } @@ -67,29 +66,67 @@ func processMailQueue() { } // sendMail allows mail with self-signed certificates. -func sendMail(hostAddressWithPort string, auth smtp.Auth, from string, recipients []string, msgContent []byte) error { - client, err := smtp.Dial(hostAddressWithPort) +func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte) error { + host, port, err := net.SplitHostPort(settings.Host) if err != nil { return err } - host, _, _ := net.SplitHostPort(hostAddressWithPort) - tlsConn := &tls.Config{ - InsecureSkipVerify: true, + tlsconfig := &tls.Config{ + InsecureSkipVerify: settings.SkipVerify, ServerName: host, } - if err = client.StartTLS(tlsConn); err != nil { + + conn, err := net.Dial("tcp", net.JoinHostPort(host, port)) + if err != nil { return err } + defer conn.Close() + + isSecureConn := false + // Start TLS directly if the port ends with 465 (SMTPS protocol) + if strings.HasSuffix(port, "465") { + conn = tls.Client(conn, tlsconfig) + isSecureConn = true + } - if ok, _ := client.Extension("AUTH"); ok && auth != nil { - if err = client.Auth(auth); err != nil { + client, err := smtp.NewClient(conn, host) + if err != nil { + return err + } + + // If not using SMTPS, alway use STARTTLS if available + hasStartTLS, _ := client.Extension("STARTTLS") + if !isSecureConn && hasStartTLS { + if err = client.StartTLS(tlsconfig); err != nil { return err } } - if err = client.Mail(from); err != nil { + canAuth, options := client.Extension("AUTH") + + if canAuth && len(settings.User) > 0 { + var auth smtp.Auth + + if strings.Contains(options, "CRAM-MD5") { + auth = smtp.CRAMMD5Auth(settings.User, settings.Passwd) + } else if strings.Contains(options, "PLAIN") { + auth = smtp.PlainAuth("", settings.User, settings.Passwd, host) + } + + if auth != nil { + if err = client.Auth(auth); err != nil { + return err + } + } + } + + if fromAddress, err := mail.ParseAddress(settings.From); err != nil { return err + } else { + if err = client.Mail(fromAddress.Address); err != nil { + return err + } } for _, rec := range recipients { @@ -116,7 +153,6 @@ func sendMail(hostAddressWithPort string, auth smtp.Auth, from string, recipient // Direct Send mail message func Send(msg *Message) (int, error) { log.Trace("Sending mails to: %s", strings.Join(msg.To, "; ")) - host := strings.Split(setting.MailService.Host, ":") // get message body content := msg.Content() @@ -127,17 +163,12 @@ func Send(msg *Message) (int, error) { return 0, fmt.Errorf("empty email body") } - var auth smtp.Auth - if len(setting.MailService.Passwd) > 0 { - auth = smtp.PlainAuth("", setting.MailService.User, setting.MailService.Passwd, host[0]) - } - if msg.Massive { // send mail to multiple emails one by one num := 0 for _, to := range msg.To { body := []byte("To: " + to + "\r\n" + content) - err := sendMail(setting.MailService.Host, auth, msg.From, []string{to}, body) + err := sendMail(setting.MailService, []string{to}, body) if err != nil { return num, err } @@ -148,7 +179,7 @@ func Send(msg *Message) (int, error) { body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content) // send to multiple emails in one message - err := sendMail(setting.MailService.Host, auth, msg.From, msg.To, body) + err := sendMail(setting.MailService, msg.To, body) if err != nil { return 0, err } else { |