对接邮件服务器问题总结

技术文档网 2021-05-26

『问题描述』

用Go语言写了一个服务,在对接客户的邮件服务器的时候,对方邮件服务器返回unencrypted connection的错误。
Go版本1.7.3

『排查过程』

  1. 首先确认,对方邮件服务器未启用TLS
  2. 跟踪查看Go语言的底层代码,查看抛出错误的地方,代码如下:
    func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
     if !server.TLS {
         advertised := false
         for _, mechanism := range server.Auth {
             if mechanism == "PLAIN" {
                 advertised = true
                 break
             }
         }
         if !advertised {
             return "", nil, errors.New("unencrypted connection")
         }
     }
     if server.Name != a.host {
         return "", nil, errors.New("wrong host name")
     }
     resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password)
     return "PLAIN", resp, nil
    }
    
      我在与对方邮件服务器连接的时候采用了Go语言smtp包中的PlainAuth,即PLAIN的认证方式,代码中表明会先检测是否启用TLS,如果未启用则遍历server.Auth,server.Auth表示的是邮件服务器端支持的认证方式,如果服务端不支持PLAIN的认证,就会抛出以上错误。
  • PLAIN方式:基于明文的SMTP验证,其发送用户名与口令的格式应该是“timtanstaaftanstaaf”。“tim”是用户名,后边的字符串是口令,NULL是ASCII的0
  • LOGIN方式:其验证序列如下 (C:表示Client,S:表示Server)
C:auth login --------------------------------- 进行用户身份认证
S:334 VXNlcm5hbWU6 --------------------------- BASE64编码“Username:”
C:Y29zdGFAYW1heGl0Lm5ldA== ------------------- 用户名,使用BASE64编码
S:334 UGFzc3dvcmQ6 ----------------------------BASE64编码"Password:"
C:MTk4MjIxNA== ------------------------------- 密码,使用BASE64编码
S:235 auth successfully ---------------------- 身份认证成功
  • CRAM-MD5方式:这种不太常用,此处不进行整理,企业内部最常见的应该就是LOGIN认证了。

3.有没有什么方法知道当前邮件服务器支持哪些认证方式吗?

// 说明:方括号内表示参数,你需要自己填写。敏感信息本人用xxxxx打码
telnet [mail-server-ip] [mail-server-port]
Trying xxxxx...
Connected to xxxxx.
Escape character is '^]'.
220 xxxxx ESMTP Postfix
ehlo localhost          // 与服务器打招呼,并告知客户端使用的名字,这里可以随便填
250-xxxxx
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN    // 这里就是邮件服务器返回的它支持的认证方式
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

后来,我用此方法拿到了对方支持的认证方式,结果中只有LOGIN的方式而没有PLAIN,这也难怪会出现以上错误。随后,我去Go的包中去找LoginAuth的接口,结果竟然没有!!!没有!!没! 搜寻一番,网上给出了自己实现这个功能的方案,把下面代码写入自己的项目,在调用PlainAuth认证的地方替换成这里的LoginAuth即可解决。代码如下:

package smtpex

import (
    "errors"
    "net/smtp"
)

type loginAuth struct {
    username, password string
}

func LoginAuth(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("Unkown fromServer")
        }
    }
    return nil, nil
}

参考链接: SMTP验证方式种类 Telnet登陆SMTP发邮件 Postfix+Dovecot邮件服务器架设傻瓜版指南 使用Postfix dovecot配置简单的邮件系统

相关文章

  1. 硅谷互联网公司的开发流程

    开发流程包括这么几个阶段: OKR 的设立; 主项目及其子项目的确立; 每个子项目的生命周期; 主项目的生命周期; 收尾、维护、复盘。 第一点,OKR 的设立 所有项目的起始,都应该从 Ro

  2. RESTful-表述性状态转移风格

    REST英文全拼:Representational State Transfer 面向资源编程 资源指的就是一类数据 产品表->就是产品资源 最重要的是如何表示一个资源 地址即

  3. 稳定性思考

    产品功能线 0-1: 当系统从无到有的时候,首要考虑的是研发效率,功能快速迭代,满足快速增长的业务需求 1-10 系统已经搭建起来,此时考虑的是系统的稳定性。 可用性:1.隔离:区分出核心和非核心功能

  4. Supervisor守护队列发邮件

    安装 CentOS: yum -y install supervisor Debien/Ubuntu适用:apt-get install supervisor 配置 修改主配置文件:vim /et

  5. 安装libsodium,让服务器支持chacha20等加密方式

    用chacha20加密方式需要安装libsodium 注意:libsodium从1.0.15开始就废弃了aes-128-ctr yum install wget m2crypto git libsod

随机推荐

  1. 硅谷互联网公司的开发流程

    开发流程包括这么几个阶段: OKR 的设立; 主项目及其子项目的确立; 每个子项目的生命周期; 主项目的生命周期; 收尾、维护、复盘。 第一点,OKR 的设立 所有项目的起始,都应该从 Ro

  2. RESTful-表述性状态转移风格

    REST英文全拼:Representational State Transfer 面向资源编程 资源指的就是一类数据 产品表->就是产品资源 最重要的是如何表示一个资源 地址即

  3. 稳定性思考

    产品功能线 0-1: 当系统从无到有的时候,首要考虑的是研发效率,功能快速迭代,满足快速增长的业务需求 1-10 系统已经搭建起来,此时考虑的是系统的稳定性。 可用性:1.隔离:区分出核心和非核心功能

  4. Supervisor守护队列发邮件

    安装 CentOS: yum -y install supervisor Debien/Ubuntu适用:apt-get install supervisor 配置 修改主配置文件:vim /et

  5. 安装libsodium,让服务器支持chacha20等加密方式

    用chacha20加密方式需要安装libsodium 注意:libsodium从1.0.15开始就废弃了aes-128-ctr yum install wget m2crypto git libsod