项目场景:
java mail集成james邮件服务器,发送邮件时需要判断邮件是否发送成功。我们会发现JavaMail给用户发送邮件,但是调用Transport类的sendMessage方法发送的邮件是没有返回值的,所以判断不了。
但是我们可以用另一个解决方案,就是采用“系统退信”的方式来达到目的,我们会发现163、qq等邮件发送失败就会“系统退信”。
需求
什么情况下会系统退信
邮箱地址错误或访问不通;
邮箱地址正确,但是用户不存在;
解决方案:
修改james配置,windows文件路径:james\apps\james\SAR-INF\config.xml,搜索关键字:maxRetries
原内容:
<mailet match="All" class="RemoteDelivery">
<outgoing>file://var/mail/outgoing/</outgoing>
<!-- Delivery Schedule based upon RFC 2821, 4.5.4.1 -->
<!-- 5 day retry period, with 4 attempts in the first
hour, two more within the first 6 hours, and then
every 6 hours for the rest of the period. -->
<delayTime> 5 minutes </delayTime>
<delayTime> 10 minutes </delayTime>
<delayTime> 45 minutes </delayTime>
<delayTime> 2 hours </delayTime>
<delayTime> 3 hours </delayTime>
<delayTime> 6 hours </delayTime>
<maxRetries> 25 </maxRetries>
<!-- The number of threads that should be trying to deliver outgoing messages -->
<deliveryThreads> 50 </deliveryThreads>
<!-- If false the message will not be sent to given server if any recipients fail -->
<sendpartial>false</sendpartial>
<!-- By default we send bounces to the "bounce" processor -->
<!-- By removing this configuration James will fallback to hardcoded bounce -->
<!-- notifications -->
<bounceProcessor>bounces</bounceProcessor>
</mailet>
修改后的内容:
<mailet match="All" class="RemoteDelivery">
<outgoing>file://var/mail/outgoing/</outgoing>
<!-- Delivery Schedule based upon RFC 2821, 4.5.4.1 -->
<!-- 5 day retry period, with 4 attempts in the first
hour, two more within the first 6 hours, and then
every 6 hours for the rest of the period. -->
<delayTime> 0 minutes </delayTime>
<maxRetries> 0 </maxRetries>
<!-- The number of threads that should be trying to deliver outgoing messages -->
<deliveryThreads> 50 </deliveryThreads>
<!-- If false the message will not be sent to given server if any recipients fail -->
<sendpartial>false</sendpartial>
<!-- By default we send bounces to the "bounce" processor -->
<!-- By removing this configuration James will fallback to hardcoded bounce -->
<!-- notifications -->
<bounceProcessor>bounces</bounceProcessor>
</mailet>
其实就是改了delayTime、maxRetries这两个标签
......
<delayTime> 0 minutes </delayTime>
<maxRetries> 0 </maxRetries>
......
解析:
这段内容就是邮件发送失败,重试的机制,这个outgoing文件夹里面就是需要重试的邮件
delayTime:重试的时间
maxRetries:最大重试次数
所以原来默认是:
5天重试期,第一次尝试4次小时,前6小时内再增加两次,然后在剩余时间内,每6小时一次。
需要重试5天,时间太长了
我们改为了0分钟重试0次
这样可以立刻收到系统退信,当然也可以按自己的需求来改,这里单位只能是minutes和hours,试了0.5minutes和1second都没效果。
结果:
接收退信,就平时接收邮件一样就行了,在inboxes文件夹
邮箱地址错误或访问不通,测试的邮箱地址:test@test.com,系统退信的邮件内容
Hi. This is the James mail server at XT-PC. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. Below I include the list of recipients and the reason why I was unable to deliver your message. Failed recipient(s): test@test.com Error message: There are no DNS entries for the hostname test.com. I cannot determine where to send this message.
邮箱地址正确,但是用户不存在,测试的邮箱地址:test1111@163.com,系统退信的邮件内容
Hi. This is the James mail server at XT-PC. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. Below I include the list of recipients and the reason why I was unable to deliver your message. Failed recipient(s): test1111@163.com Error message: 550 User not found: test1111@163.com
总结:
我试过Java检测网络是否能ping通和Java使用Socket验证邮箱是否存在的方式,结果发现都不能保证100%准确,只有系统退信这种方式是没问题的。
我这里邮件服务器是james,如果是其他的邮件服务器应该也有类似的配置。