Go发送Email

本文探讨了使用Go语言发送邮件时遇到的问题,特别是在不同SMTP认证方式下的处理方法。介绍了如何解决因邮件服务器支持的认证方式(如NTLM和LOGIN)与Go标准库net/smtp仅支持CRAM-MD5和PLAIN认证方式之间的冲突。提供了实现LOGIN认证的具体代码示例。
摘要由CSDN通过智能技术生成

使用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()
}

 

转载于:https://www.cnblogs.com/sz-wenbin/p/11112553.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值