使用Go发送邮件,目前官网GO 1.12的版本的文档中,包 "net/smtp" 仅支持支持两种SMTP的认证方式。CRAM-MD5和PLAIN 认证方式。
CRAM-MD5 是基于Keyed-MD5的认证方式
PLAIN 是一种明文的验证方式
我们公司使用的邮件服务器SMTP支持两种认证方式:NTLM 和 LOGIN
查看邮件服务器支持SMTP的认证方式的方法:
在这种情况下:
1、直接使用Go官网"net/smtp"的认证方式发送邮件回报错
报错:x509: certificate signed by unknown authority
理解: 这个是GO的客户端对服务器传过来数字证书进行校验,可以进行关闭,不进行校验。
代码:
if ok, _ := c.Extension("STARTTLS"); ok { config := &tls.Config{ServerName: c.serverName, InsecureSkipVerify: true} if testHookStartTLS != nil { testHookStartTLS(config) } if err = c.StartTLS(config); err != nil { return err } }
报错:504 5.7.4 Unrecognized authentication type
理解:GO官网包 "net/smtp" 仅支持 CRAM-MD5和PLAIN 而我们公司邮件服务器支持认证方式 NTLM 和 LOGIN
2、支持SMTP的LOGIN认证方式的代码
type LoginAuth struct { username string password string } func NewLoginAuth(username, password string) smtp.Auth { return &LoginAuth{username, password} } func (a *LoginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { return "LOGIN", []byte{}, nil } func (a *LoginAuth) Next(fromServer []byte, more bool) ([]byte, error) { if more { switch string(fromServer) { case "Username:": return []byte(a.username), nil case "Password:": return []byte(a.password), nil default: return nil, errors.New("Unknown fromServer") } } return nil, nil } func SendMail(addr string, a smtp.Auth, subject string, from string, to []string, msg []byte) error { c, err := smtp.Dial(addr) host, _, _ := net.SplitHostPort(addr) if err != nil { fmt.Println("call dial") return err } defer c.Close() if ok, _ := c.Extension("STARTTLS"); ok { config := &tls.Config{ServerName: host, InsecureSkipVerify: true} if err = c.StartTLS(config); err != nil { fmt.Println("call start tls") return err } } if a != nil { if ok, _ := c.Extension("AUTH"); ok { if err = c.Auth(a); err != nil { fmt.Println("check auth with err:", err) 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 } header := make(map[string]string) header["Subject"] = subject header["MIME-Version"] = "1.0" header["Content-Type"] = "text/plain; charset=\"utf-8\"" header["Content-Transfer-Encoding"] = "base64" message := "" for k, v := range header { message += fmt.Sprintf("%s: %s\r\n", k, v) } message += "\r\n" + base64.StdEncoding.EncodeToString(msg) _, err = w.Write([]byte(message)) if err != nil { return err } err = w.Close() if err != nil { return err } return c.Quit() }