一. 什么是接收连接器?
上图显示出了Exchange 2013完整安装后默认的5种接收连接器。
接收连接器用于控制发送到Exchange组织的入站邮件流,不同的接收连接器负责监听不同的网络端口,独立控制客户的认证等。
接收连接器的作用域限于单台服务器,及每个接收连接器都属于单台服务器,其设置仅对此台服务器生效。例如,我们在域中部署了多台Exchange服务器,每台服务器都拥有独立的5种接收连接器。
接收连接器按角色分只有两类,分别为:FrontendTransport(前端传输),和HubTransport(集线器传输)。其中,FrontendTransport存在于客户端访问角色服务器,即前端服务器;HubTransport存在于邮箱角色服务器,即后端服务器。
5个默认接收连接器中,FrontendTransport角色有3个,HubTransport角色有2个。因此,如果邮件服务器仅安装前端角色,则只有3个默认接收连接器,如果仅安装后端角色则只有2个默认接受连接器,只有安装了全角色的服务器才包含全部的5个默认接收连接器。
二. 五种接收连接器的区别
接收连接器 | 角色 | 端口 | 简介 |
Default FrontEnd <Server> | FrontendTransport | 25 | 接受来自 SMTP 发件人的连接。这是进入组织的常用邮件入口点。正常情况外部邮件都是通过这个接收连接器进入组织的。并且,因为此接收连接器属于前端服务器,所以我们要接收外部邮件时需要将前端服务器的地址映射出去。 端口25是SMTP的第一个正式端口。 1982年,端口25专用于SMTP。SMTP端口25使用TCP作为传输协议。 另外,端口25是SMTP最著名和最受欢迎的端口。 端口25作为一个古老,流行且知名的端口,被广泛滥用,并且某些ISP,网络和云提供程序自动或默认情况下阻止TCP 25 SMTP端口,以防止滥用和安全攻击。 |
Client Frontend <Server> | FrontendTransport | 587 | 接受应用了传输层安全性 (TLS) 的安全连接,即使用pop3或者imap协议的邮件客户端通过TLS加密通道提交的邮件,因为pop3和imap都是接收邮件的协议,它们发送邮件都是使用SMTP(加密)协议。 587端口是STARTTLS协议的 属于TLS通讯协议 只是他是在STARTTLS命令执行后才对之后的原文进行保护的。 |
Outbound Proxy Frontend <Server> | FrontendTransport | 717 | 接受来自后端服务器(启用了前端代理)上的发送连接器的邮件,即当后端服务器开启了前端代理后,前端服务器才使用这个接收连接器接收后端提交的邮件。 |
Default <Server> | HubTransport | 2525 | 用于接受来自运行传输服务的邮箱服务器和来自边缘服务器的连接,因为在Exchange 2013,邮箱服务器承载传输服务,因此这个连接器也可接收自己本身的邮件提交。 SMTP端口2525是一个棘手的端口,通过键入25两次来创建,因为端口25是SMTP的第一个端口号。 未正式为SMTP使用分配端口2525,因为IETF或IANA当局无法识别该端口。 但是数字的相似性使2525端口变得流行,并且大多数ISP,云服务提供商和电子邮件服务器都支持并允许访问2525端口SMTP服务。 |
Client Proxy <Server> | HubTransport | 465 | 接受来自前端服务器的连接。邮件会通过 SMTP 发送到前端服务器。465端口是为SMTPS(SMTP-over-SSL)协议服务开放的,这是SMTP协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。SMTPS和SMTP协议一样,也是用来发送邮件的,只是更安全些,防止邮件被黑客截取泄露,还可实现邮件发送者抗抵赖功能。防止发送者发送之后删除已发邮件,拒不承认发送过这样一份邮件。 465端口是第一个使用SMTP over SSL方法的安全加密电子邮件提交端口。 在端口587出现一段时间后,SMTP端口465正式被弃用,并提供使用其他协议。 但是今天,许多ISP和云托管提供商都支持并提供465端口用于SMTP提交。 |
三. 邮件客户端若干问题
1. 发送匿名邮件
Default FrontEnd <Server>接收连接器监听25端口,这是经典的SMTP服务端口,该接收连接器默认允许匿名用户使用,因此,我们可以不经过用户认证,任意填写发件人信息,直接利用该接收器发送邮件。
javax.mail配置:
properties.put("mail.debug", "true");
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.host", "exchange2013-03.ad.com");
properties.put("mail.smtp.port", "25");
properties.put("mail.smtp.auth", "false");
MyMailConfig mailConfig = new MyMailConfig(null, null, properties);
MyMailMessenger mailMessenger = new MyMailMessenger(mailConfig);
对于其他的接收连接器也是如此,如果允许匿名用户使用,那么邮件客户端就可以不经过认证直接利用对应的连接器发送邮件。为了安全起见,我们应当禁止各个接收连接器允许匿名用户使用。
2. 客户端错误:535 5.7.3 Authentication unsuccessful
javax.mail配置:
properties.put("mail.debug", "true");
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.host", "exchange2013-03.ad.com");
properties.put("mail.smtp.port", "25");
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.auth.mechanisms", "NTLM");
MyMailConfig mailConfig = new MyMailConfig("qa@ad.com", "xxx", properties);
MyMailMessenger mailMessenger = new MyMailMessenger(mailConfig);
客户端配置正确以后,无法发送邮件,提示:
535 5.7.3 Authentication unsuccessful
即用户认证失败。
2.1 邮箱密码和授权码
对于某些邮件服务提供商,例如网易163等,其邮箱密码不能用于第三方邮件客户端的用户认证,第三方邮件客户端的用户认证需要使用专门的授权码,这一点需要和邮件服务提供商确认清楚。
在这种情况下,在第三方邮件客户端使用邮箱密码进行用户认证会返回认证错误。因此,必须从邮件服务提供商处索取授权码来代替邮箱密码使用。
2.2. Exchange权限组
另外,该错误提示具有相当的误导性。例如,对于Exchange邮箱服务,如果你确定密码正确,用户是合法的,仍然收到了用户认证错误,那么问题可能不在客户端,你需要在邮件服务器对应的接收连接器上开启“Exchange用户”权限组。
3. 25端口屏蔽问题
当在客户端使用25端口发送邮件时,可能出现MailConnectException,即无法连接邮件服务器。这是因为一些服务器运营商为了防止25端口被滥用,关闭了该端口。
就阿里云而言,开启了阿里云安全组的25号端口之后,问题依旧。经过测试得知,阿里云的ECS服务器根本没有启用25号端口,25号端口始终处于封禁状态,即便用户手动开启安全组的25号端口也没用。
解决方法除了联系阿里云客服开放25端口之外,就是使用465端口替代。由于465端口和25端口的差异不是简单的端口修改,而是增加了SSL安全协议,因此,代码配置层面上也需要进行对应的修改。
javax.mail配置:
properties.put("mail.debug", "true");
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.host", "exchange2013-02.ad.com");
properties.put("mail.smtp.port", "465");
properties.put("mail.smtp.socketFactory.port", "465");
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.auth", "true");
MyMailConfig mailConfig = new MyMailConfig("qa@ad.com", "xxx", properties);
MyMailMessenger mailMessenger = new MyMailMessenger(mailConfig);
4. Java邮件客户端的“匿名”邮件
在禁止匿名用户使用邮件服务器之后,使用Java编写邮件发送程序时,必须使用认证用户登录邮件服务器才可以发送邮件。但是,我们仍然可以自定义邮件发件人地址(可以是虚构的,但是需要符合邮件地址格式),在一定程度上实现匿名。
Message message = …
message.setHeader("From", "ccc@ad.com");
邮件服务器似乎可以对这一行为进行限制,因为在测试过程中,我发现部分用户可以自定义From Header实现匿名,而另外一些用户则不行,会收到报错:
550 5.7.1 Client does not have permissions to send as this sender
暂时不知道在邮件服务器上如何配置以控制这一行为。
是否可以实现收件人匿名呢?
message.setHeader("To", "ddd@ad.com");
经测试并不可以。
5. Python邮件客户端的“匿名”邮件
在禁止匿名用户使用邮件服务器之后,使用Python编写邮件发送程序时,必须使用认证用户登录邮件服务器才可以发送邮件。但是,我们仍然可以自定义邮件发件人地址,在一定程度上实现匿名。
msg = MIMEText(mail_content, "plain", 'utf-8')
msg["Subject"] = Header(“点餐提醒”, 'utf-8').encode()
msg["From"] = Header("SAFSLKJNFL", 'utf-8')
需要指出的是,在Python中,可以任意填写From Header,非邮件地址也支持;并且收件人也可以匿名。因此,收到的此类邮件收件人地址和发件人地址都无法展开,匿名程度较高。
在邮件服务器配置相同的情况下,Java邮件客户端某些用户可以伪造发件人地址,其他用户不行,伪造收件人地址后,邮件显示发送成功,但真实的收件人无法收到邮件;而Python中所有用户都可以伪造发件人地址,也可以伪造收件人地址,暂不知道在邮件服务器上如何阻止这一行为。
6. 在 Outlook 中查看 Internet 邮件头(Office 2016)
在面临这些匿名邮件时,如何追踪邮件的发件人呢,查看邮件头有一定的帮助。
在Java匿名邮件中,邮件头中有关发件人地址的信息都会被伪造的邮件地址替换,但可以找到发件人的主机信息。
在Python匿名邮件中,邮件头中Return-Path字段会显示真实的发件人地址。
Outlook查看邮件头的方法:
a. 双击电子邮件以在阅读窗格外部打开它。
b. 有两条路径:
方式1:单击 "文件 > 属性"。
方式2:点击“邮件 > 标记 > 邮件选项”。
c. 邮件头信息显示在“Internet 邮件头”框中。