package gomail import ( "crypto/tls" "io" "net" "net/smtp" ) func (m *Mailer) getSendMailFunc(ssl bool) SendMailFunc { return func(addr string, a smtp.Auth, from string, to []string, msg []byte) error { var c smtpClient var err error if ssl { c, err = sslDial(addr, m.host, m.config) } else { c, err = starttlsDial(addr, m.config) } if err != nil { return err } defer c.Close() if a != nil { if ok, _ := c.Extension("AUTH"); ok { if err = c.Auth(a); err != nil { return err } } } if err = c.Mail(from); err != nil { return err } for _, addr := range to { if err = c.Rcpt(addr); err != nil { return err } } w, err := c.Data() if err != nil { return err } _, err = w.Write(msg) if err != nil { return err } err = w.Close() if err != nil { return err } return c.Quit() } } func sslDial(addr, host string, config *tls.Config) (smtpClient, error) { conn, err := initTLS("tcp", addr, config) if err != nil { return nil, err } return newClient(conn, host) } func starttlsDial(addr string, config *tls.Config) (smtpClient, error) { c, err := initSMTP(addr) if err != nil { return c, err } if ok, _ := c.Extension("STARTTLS"); ok { return c, c.StartTLS(config) } return c, nil } var initSMTP = func(addr string) (smtpClient, error) { return smtp.Dial(addr) } var initTLS = func(network, addr string, config *tls.Config) (*tls.Conn, error) { return tls.Dial(network, addr, config) } var newClient = func(conn net.Conn, host string) (smtpClient, error) { return smtp.NewClient(conn, host) } type smtpClient interface { Extension(string) (bool, string) StartTLS(*tls.Config) error Auth(smtp.Auth) error Mail(string) error Rcpt(string) error Data() (io.WriteCloser, error) Quit() error Close() error }