github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+incompatible/utils/mail.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package utils
     5  
     6  import (
     7  	"crypto/tls"
     8  	"mime"
     9  	"net"
    10  	"net/mail"
    11  	"net/smtp"
    12  	"time"
    13  
    14  	"gopkg.in/gomail.v2"
    15  
    16  	"net/http"
    17  
    18  	l4g "github.com/alecthomas/log4go"
    19  	"github.com/mattermost/html2text"
    20  	"github.com/mattermost/mattermost-server/model"
    21  )
    22  
    23  func encodeRFC2047Word(s string) string {
    24  	return mime.BEncoding.Encode("utf-8", s)
    25  }
    26  
    27  func connectToSMTPServer(config *model.Config) (net.Conn, *model.AppError) {
    28  	var conn net.Conn
    29  	var err error
    30  
    31  	if config.EmailSettings.ConnectionSecurity == model.CONN_SECURITY_TLS {
    32  		tlsconfig := &tls.Config{
    33  			InsecureSkipVerify: *config.EmailSettings.SkipServerCertificateVerification,
    34  			ServerName:         config.EmailSettings.SMTPServer,
    35  		}
    36  
    37  		conn, err = tls.Dial("tcp", config.EmailSettings.SMTPServer+":"+config.EmailSettings.SMTPPort, tlsconfig)
    38  		if err != nil {
    39  			return nil, model.NewAppError("SendMail", "utils.mail.connect_smtp.open_tls.app_error", nil, err.Error(), http.StatusInternalServerError)
    40  		}
    41  	} else {
    42  		conn, err = net.Dial("tcp", config.EmailSettings.SMTPServer+":"+config.EmailSettings.SMTPPort)
    43  		if err != nil {
    44  			return nil, model.NewAppError("SendMail", "utils.mail.connect_smtp.open.app_error", nil, err.Error(), http.StatusInternalServerError)
    45  		}
    46  	}
    47  
    48  	return conn, nil
    49  }
    50  
    51  func newSMTPClient(conn net.Conn, config *model.Config) (*smtp.Client, *model.AppError) {
    52  	c, err := smtp.NewClient(conn, config.EmailSettings.SMTPServer+":"+config.EmailSettings.SMTPPort)
    53  	if err != nil {
    54  		l4g.Error(T("utils.mail.new_client.open.error"), err)
    55  		return nil, model.NewAppError("SendMail", "utils.mail.connect_smtp.open_tls.app_error", nil, err.Error(), http.StatusInternalServerError)
    56  	}
    57  
    58  	hostname := GetHostnameFromSiteURL(*config.ServiceSettings.SiteURL)
    59  	if hostname != "" {
    60  		err := c.Hello(hostname)
    61  		if err != nil {
    62  			l4g.Error(T("utils.mail.new_client.helo.error"), err)
    63  			return nil, model.NewAppError("SendMail", "utils.mail.connect_smtp.helo.app_error", nil, err.Error(), http.StatusInternalServerError)
    64  		}
    65  	}
    66  
    67  	if config.EmailSettings.ConnectionSecurity == model.CONN_SECURITY_STARTTLS {
    68  		tlsconfig := &tls.Config{
    69  			InsecureSkipVerify: *config.EmailSettings.SkipServerCertificateVerification,
    70  			ServerName:         config.EmailSettings.SMTPServer,
    71  		}
    72  		c.StartTLS(tlsconfig)
    73  	}
    74  
    75  	if *config.EmailSettings.EnableSMTPAuth {
    76  		auth := smtp.PlainAuth("", config.EmailSettings.SMTPUsername, config.EmailSettings.SMTPPassword, config.EmailSettings.SMTPServer+":"+config.EmailSettings.SMTPPort)
    77  
    78  		if err = c.Auth(auth); err != nil {
    79  			return nil, model.NewAppError("SendMail", "utils.mail.new_client.auth.app_error", nil, err.Error(), http.StatusInternalServerError)
    80  		}
    81  	}
    82  	return c, nil
    83  }
    84  
    85  func TestConnection(config *model.Config) {
    86  	if !config.EmailSettings.SendEmailNotifications {
    87  		return
    88  	}
    89  
    90  	conn, err1 := connectToSMTPServer(config)
    91  	if err1 != nil {
    92  		l4g.Error(T("utils.mail.test.configured.error"), T(err1.Message), err1.DetailedError)
    93  		return
    94  	}
    95  	defer conn.Close()
    96  
    97  	c, err2 := newSMTPClient(conn, config)
    98  	if err2 != nil {
    99  		l4g.Error(T("utils.mail.test.configured.error"), T(err2.Message), err2.DetailedError)
   100  		return
   101  	}
   102  	defer c.Quit()
   103  	defer c.Close()
   104  }
   105  
   106  func SendMailUsingConfig(to, subject, htmlBody string, config *model.Config) *model.AppError {
   107  	if !config.EmailSettings.SendEmailNotifications || len(config.EmailSettings.SMTPServer) == 0 {
   108  		return nil
   109  	}
   110  
   111  	l4g.Debug(T("utils.mail.send_mail.sending.debug"), to, subject)
   112  
   113  	htmlMessage := "\r\n<html><body>" + htmlBody + "</body></html>"
   114  
   115  	fromMail := mail.Address{Name: config.EmailSettings.FeedbackName, Address: config.EmailSettings.FeedbackEmail}
   116  
   117  	txtBody, err := html2text.FromString(htmlBody)
   118  	if err != nil {
   119  		l4g.Warn(err)
   120  		txtBody = ""
   121  	}
   122  
   123  	m := gomail.NewMessage(gomail.SetCharset("UTF-8"))
   124  	m.SetHeaders(map[string][]string{
   125  		"From":                      {fromMail.String()},
   126  		"To":                        {to},
   127  		"Subject":                   {encodeRFC2047Word(subject)},
   128  		"Content-Transfer-Encoding": {"8bit"},
   129  		"Auto-Submitted":            {"auto-generated"},
   130  		"Precedence":                {"bulk"},
   131  	})
   132  	m.SetDateHeader("Date", time.Now())
   133  
   134  	m.SetBody("text/plain", txtBody)
   135  	m.AddAlternative("text/html", htmlMessage)
   136  
   137  	conn, err1 := connectToSMTPServer(config)
   138  	if err1 != nil {
   139  		return err1
   140  	}
   141  	defer conn.Close()
   142  
   143  	c, err2 := newSMTPClient(conn, config)
   144  	if err2 != nil {
   145  		return err2
   146  	}
   147  	defer c.Quit()
   148  	defer c.Close()
   149  
   150  	if err := c.Mail(fromMail.Address); err != nil {
   151  		return model.NewAppError("SendMail", "utils.mail.send_mail.from_address.app_error", nil, err.Error(), http.StatusInternalServerError)
   152  	}
   153  
   154  	if err := c.Rcpt(to); err != nil {
   155  		return model.NewAppError("SendMail", "utils.mail.send_mail.to_address.app_error", nil, err.Error(), http.StatusInternalServerError)
   156  	}
   157  
   158  	w, err := c.Data()
   159  	if err != nil {
   160  		return model.NewAppError("SendMail", "utils.mail.send_mail.msg_data.app_error", nil, err.Error(), http.StatusInternalServerError)
   161  	}
   162  
   163  	_, err = m.WriteTo(w)
   164  	if err != nil {
   165  		return model.NewAppError("SendMail", "utils.mail.send_mail.msg.app_error", nil, err.Error(), http.StatusInternalServerError)
   166  	}
   167  	err = w.Close()
   168  	if err != nil {
   169  		return model.NewAppError("SendMail", "utils.mail.send_mail.close.app_error", nil, err.Error(), http.StatusInternalServerError)
   170  	}
   171  
   172  	return nil
   173  }