资讯专栏INFORMATION COLUMN

JavaMail邮件发送不成功的那些坑人情况及分析说明

y1chuan / 3405人阅读

摘要:网上也有不少人反馈用手机客户端无法使用新浪邮箱发送邮件,随后我尝试用登录新浪邮箱,也出现只能接收邮件而不能发送邮件的情况。三附录错误码及建议解决方法发送邮件成功却收不到邮件或收到邮件无主题无收件人乱码新浪邮箱诚信平台

前言

  JavaMail的使用本身并不难,网上有不少案例,简单易懂,而且有详细的中文注解。但是由于JavaMail的机制设置不够完善,特别是异常出错时的参考信息太少,给初学者造成了不少麻烦,而我就是其中之一。在此,把我遇到过得那些坑总结出来,以免大家重蹈覆辙,浪费时间。(注:后续还有遇到新的问题,我会持续更新到这里)

一、JavaMail概述

  JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类。但它并没有包含在JDK中,而是作为JavaEE的一部分。

  厂商所提供的JavaMail服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括:

SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;

POP3:用于接收电子邮件的标准协议;

IMAP:互联网消息协议,是POP3的替代协议。

  这三种协议都有对应SSL加密传输的协议,分别是SMTPS,POP3S和IMAPS。除JavaMail服务提供程序之外,JavaMail还需要JAF(JavaBeans Activation Framework)来处理不是纯文本的邮件内容,这包括MIME(多用途互联网邮件扩展)、URL页面和文件附件等内容。下图描述了JavaMail的体系结构。

(图片来源:http://blog.csdn.net/t12x3456...)

mail.jar:此JAR文件包含JavaMail API和Sun提供的SMTP、IMAP和POP3服务提供程序;

activation.jar:此JAR文件包含JAF API和Sun的实现。

(有关JavaMail的介绍我只摘要部分,详细介绍请参考:http://blog.csdn.net/zapldy/a...)

二、各种问题及分析说明

  后面列举出来的报错信息需要开启Session的debug模式,具体配置方式如下:

Session sendMailSession = Session.getInstance(pro, authenticator);
sendMailSession.setDebug(true);
1、后台显示邮件发送成功但未收到邮件 问题现象

  使用新浪邮箱发送邮件,尝试两种邮件发送方式,分别是“A@sina .cn发送给A@sina .cn”和“A@sina .cn发送给B@sina .cn”,摘要部分后台打印信息:

250 ok queue id 355937395546
QUIT
221 smtp-5-121.smtpsmail.fmail.xd.sinanode.com
Sent message ***@sina.cn successfully....

  使用163邮箱发送邮件,尝试C@126.com发送给A@sina .cn,摘要部分后台打印信息:

250 Mail OK queued as smtp7,C8CowADnDNooqmNYHWsYGw--.30359S3 1482926655
QUIT
221 Bye
Sent message ***@sina.cn successfully....

  登录新浪邮箱确认有smtp服务且处于开通状态,也尝试重新开启smtp服务,仍然邮件发送不成功。网上也有不少人反馈用手机客户端无法使用新浪邮箱发送邮件,随后我尝试用foxmail登录新浪邮箱,也出现只能接收邮件而不能发送邮件的情况。

问题分析

  基本确定是新浪邮箱问题,至于是smtp服务问题,还是做什么限制就不清楚了。好像平时也没多少人用新浪邮箱发邮件,通过网页登录也是能发邮件的,凑合能用,毕竟是免费邮箱嘛。

  这是用JavaMail发送邮件遭遇的第一个问题,案例都是参考别人原封不动拿过来用的,却发了收不到邮件。换了几个参考案例,问题现象相同。我开始怀疑别人给的案例代码问题,毕竟堂堂的新浪邮箱还不至于这么不靠谱。然后,就是基于这样的判断,我就吃了大亏,一直在分析代码和配置方式,也在各大论坛搜“发送邮件成功却收不到邮件”,发现出现问题的不在少数,而且多半给出的建议是检查代码有没有问题,然后提问的人也没了回复下文,这就导致了很大的误导性。这正是因为这个原因,我也白白地耗了好几天时间,直到最后发现原来原因是这么简单...有时别人的解答能够事半功倍,但是这种依赖性还是不靠谱的,有时自己的排错思路更重要

2、向新浪邮箱发信被退信 问题现象

  平时开发测试,不想用私人常用邮箱,于是注册了搜狐邮箱,并尝试向新浪邮箱发送邮件,不过很快搜狐邮箱收到退信(这种情况JavaMail是不会提示判断信息的),退信内容如下:

: host freemx1.sinamail.sina.com.cn[202.108.35.47] said:
554 Rejected due to the sending MTA"s poor reputation. Please refer
http://mail.sina.com.cn/help2... Please refer to
http://chengxin.mail.sina.com... 123.125.123.1
(in reply to DATA command)

问题分析

  通过访问退信信息里面的链接(新浪邮箱诚信平台),基本确定搜狐邮箱服务器被拉黑了。当然,不是被新浪拉黑,而是进了RBL黑名单,新浪参考其数据进行了屏蔽。这个已经超出了个人能力范围,果断放弃新浪邮箱,改向其他邮箱发送。

【RBL黑名单】

RBL是英文Realtime Blackhole
List的缩写,即实时黑名单列表。在该列表中的IP地址对外发布过垃圾邮件。是由第三方的反垃圾邮件组织提供的检查垃圾邮件发送者地址的服务。

【查询网站】

MXToolBox:http://mxtoolbox.com/
BlackListAlert:http://www.blacklistalert.org/

3、向163邮箱发信未收到且也无未退信 问题现象

  通过搜狐邮箱向新浪邮箱发信遭遇退信后,我尝试自己发给自己,正常收到邮件。考虑模拟测试要尽量真实,我改向163邮箱发信,结果出现后台显示发信成功,163邮箱却没收到邮件,但本地邮箱并没收到退信通知。

问题分析

  这说明“后台显示邮件发送成功但未收到邮件”的情况,原因还是多种多样的,不仅可能发件服务器有问题,还可能是收件服务器的问题。收件服务器有的给你退信,有的还收了直接丢弃,真是什么奇葩情况都有,多加注意吧。

4、jar包重叠存在javax.mail.* 问题现象

  从Oracle官网下载下来JavaMail相关jar包是mail.jar,导入进去测试后报各种奇葩错误。下面的异常信息是在项目中已有geronimo-javamail_1.4_spec-1.3.jar的情况下导入mail.jar后报出来的:

com.sun.mail.smtp.SMTPSendFailedException: 530 Authentication required
 at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)
 at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)
 at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)

  不仔细看还以为是账号或密码填错了,其实只要把geronimo-javamail_1.4_spec-1.3.jar剔除,重新发邮件就正常了。

问题分析

  上面只是我贴出来的报错情况之一,这些报错是不一定能够复现,因为导包就存在问题,重叠存在javax.mail.*。我是在出现第一个问题(“后台显示邮件发送成功但未收到邮件”)的时候,在网上看到别人说的这种情况(javaMail发送邮件成功却收不到邮件或收到邮件无主题无收件人乱码),而后我就开始逐个排查定位,目前通过我所知道的情况来看,重叠存在javax.mail.*的jar有mail.jar、geronimo-javamail_1.4_spec-1.x.jar、mailapi.jar和javaee.jar。
  排查的方法也很简单,比如打开javax.mail.Session,然后定位它所在的jar,剔除后再找下一个jar包。

5、jar包正确的情况下也出现报错 问题现象

  在jar包正常且配置正确的情况下,我也遇到过不少报错情况。出现的情况基本是前几次发邮件都正常,然后再发一次又突然出现报错,再试一次问题又不复现,贴出几种报错信息如下:

(报错1)

DEBUG SMTP: Sending failed because of invalid destination addresses
RSET
DEBUG SMTP: MessagingException while sending, THROW: 
javax.mail.SendFailedException: Invalid Addresses;
  nested exception is:
    com.sun.mail.smtp.SMTPAddressFailedException: 554 5.7.1 <*@163.com>: Relay access denied
    at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1862)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1118)

(报错2)

Exception in thread "main" java.lang.RuntimeException: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed

(报错3)

javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: smtp.sohu.com, port: 25 (java.net.ConnectException: Connection timed out: connect))
    at javax.mail.Transport.send(Transport.java:163)
    at javax.mail.Transport.send(Transport.java:48)
    at javamail.EmailSender.sendMail(EmailSender.java:91)
    at javamail.EmailSender.main(EmailSender.java:64)

(报错4)

250-zw_71_47
250-AUTH PLAIN LOGIN
250 STARTTLS
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
问题分析

  因为这些报错不具有可复现性,测试过程中我也司空见惯,当然90%以上的情况邮件发送都是正常,代码方面也是综合了多个案例提炼出来的,而且代码大同小异,也看过官方提供的样例,配置内容都差不多,代码问题可能性较小,也不排除smtp服务器抽风了,目前我暂时忽略。
  当然,如果有分析出是代码问题,也欢迎留言告知分享。(注:后面文章我会将我的代码粘贴出来共享)

6、发信成功后,回应的信息不同 问题现象

  我将JavaMail代码在外网测试邮件发送成功时,后台打印信息结尾内容基本如下:

250 Mail OK queued as smtp7,C8CowADnDNooqmNYHWsYGw--.30359S3 1482926655
QUIT
221 Bye

  当我将JavaMail代码移植到内部环境测试邮件发送成功时,后台打印信息结尾内容如下:

250 Message accepted for delivery
QUIT
221 srv201.mail.*.* SMTP Service closing transmission channel
问题分析

  通过上网查询资料得知,250和221这样的编码实际是smtp交互的消息编码,其中221代表邮件会话即将结束,这意味着所有消息都已被处理。编码后面的信息“srv201.mail.. SMTP Service closing transmission channel”和“Bye”的意思类似,可以忽略具体内容,知道221代表邮件发送正常即可。

221 The server is closing its transmission channel. It can come with side messages like "Goodbye" or "Closing connection". The mailing session is going to end, which simply means that all messages have been processed.
三、附录

1、SMTP错误码及建议解决方法
2、SMTP errors and reply codes
3、javaMail发送邮件成功却收不到邮件或收到邮件无主题无收件人乱码
4、新浪邮箱诚信平台

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66452.html

相关文章

  • 【已实测通过】JavaMail常用几种邮件发送方式

    摘要:代码测试过程出现的问题,请参看邮件发送成功但未收到邮件的问题及解决办法和使用发送邮件的有关说明分析解决。类电子邮件发送器,包含各种邮件发送方法,如文本形式形式和含附件形式等。 前言   关于JavaMail发送邮件的代码,网上随便搜搜就可以找到,但是要么写得简单且没有注释解释,要么写得复杂又非常杂乱。由于项目需要,花了一段时间搜集网上各类案例,熟悉JavaMail邮件发送涉及的配置,取...

    ShowerSun 评论0 收藏0
  • 慕课网_《Java实现邮箱验证》学习总结

    摘要:时间年月日星期三说明本文部分内容均来自慕课网。用户过生日,系统发送生日祝福邮件。将最新活动和优惠以邮件的形式告知会员。通常把处理用户请求邮件发送请求的邮件服务器称为服务器。提供了加密的协议被称为。 时间:2017年06月07日星期三说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https://github.com/zcc...

    marser 评论0 收藏0
  • Java mail 使用记录

    摘要:它是发布的用来处理的。入门第一篇邮件简介及概述摘自入门第二篇创建邮件摘自入门第三篇发送邮件摘自入门第四篇接收邮件摘自入门第五篇解析邮件摘自第二讲使用表示消息常用邮箱的地址及对应的端口 JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口。它是Sun发布的用来处理email的API。它可以方便地执行一些常用的邮件传输。JavaMail API是Sun公司为方便Java开发人...

    villainhr 评论0 收藏0
  • 刚刚学习到Android使用Javamail通过XOauth调用Gmail API发送邮件方法

    摘要:关键在于的的获取,在这篇文章中讲的很清楚了,需要使用来获取,关键代码如下获得本机第一个账号注意在获得前要一下,否则会得到的通过回调方法获得获取到了后,剩下的就简单了,按部就班使用发送邮件就可以了,发送邮件的方法参照就可以了。 前景知识:OAuth,Javamail-android,Javamail api in android using XOauth 我的一个App项目需要在Ser...

    ityouknow 评论0 收藏0
  • Camunda: 把邮件扩展集成到业务过程管理中

    摘要:在业务过程系统中集成邮件服务功能发送邮件收取邮件删除邮件收到邮件时执行操作安装要求对于嵌入式过程引擎添加作为应用程序依赖如果使用需要添加如下依赖到文件中对于共享过程引擎添加到服务器的目录中比如还要保证包括下面的依赖 https://github.com/camunda/ca... 在业务过程系统中集成邮件服务. showImg(https://segmentfault.com/img/...

    leo108 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<