解决项目迁移到阿里云后发送不了邮件的问题

最近把项目迁移到阿里云,这几天观察后台日志,发现这么一段异常:

2020-04-09 20:51:39 ERROR MailUtils:228 : 发送邮件失败!com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.163.com, 25; timeout -1;
  nested exception is:
	java.net.ConnectException: Connection timed out (Connection timed out)

然后去调发送邮件的接口,还真的发不了。刚开始也是觉得很奇怪,之前项目在另一台服务器上运行好好的,在本地也可以正常的,为什么一迁移到阿里云服务器上就不行了呢?在阿里云官网上提交工单,他们的售后工程师说了一堆,为了防止垃圾邮件的泛滥,阿里加入了中国什么反垃圾邮件协会,禁用25端口。并给出两种解决方案:

其一:使用SSL安全端口465发送,

其二,使用他们阿里邮箱,他们将25重定向到80端口了。

果断排除第二种,这一来嘛,公司买了第三方邮箱的服务,未到期,重新买阿里邮箱,会造成资源浪费,这二来嘛,还需要修改各个项目涉及到邮件发送的代码。除了核心业务方面的代码,基础配置的代码我一向懒得去改。

所以就毅然决然踏上使用465端口这条路。首先找到项目中邮件发送的代码,可找来找去,没发现涉及到端口方面的配置,于是联系邮件服务提供方,他们说已经开放465端口了的,不信,你用下面的命令测试一下就知道了:

telnet smtp.163.com 465

打开终端,输入以上命令,确实出来welcome的欢迎语。那说明问题不在他们那,于是又找到阿里,阿里小姐姐可真敬业啊,大中午我在吃着午饭,她打来电话,此时已过北京时间12:30。电话里态度也是很好,说了一大堆,挂了电话一想,她话中“是,邮件提供方开放了465端口,但不代表他就使用默认的465端口来发邮件啊,万一他使用25呢”是解决问题的中心思想呀。又联系邮件服务提供方,他们明确告诉我,他们并不能指定使用哪个端口来发送邮件,使用哪个端口发送邮件在于客户端的设定。转了几圈,才猛地发现,原来需要自己编码手动指定邮件发送所使用的端口,如果不指定端口,那么系统将会使用25端口来发送。于是进行编码和测试,终于通了。下面是实现的源码:

/**
 * 使用SSL 465安全方式发送
 * @param toEmail 收件人邮箱
 * @param content 邮件内容
 * @param subject 邮件主题
 */
public static void sendSSLEmail(String toEmail, String content, String subject) {
	boolean isSSL = true;
	String host = "smtp.163.com";
	int port = 465;
	final String from = "smtp@163.com"; // 发件人的email
	boolean isAuth = true;
	final String password = "123456";

	Properties props = new Properties();
	props.put("mail.smtp.ssl.enable", isSSL); //指定使用SSL方式发送
	props.put("mail.smtp.host", host);        //邮件主机
	props.put("mail.smtp.port", port);       //指定使用465安全端口
	props.put("mail.smtp.auth", isAuth);     //需要验证

	Session session = Session.getDefaultInstance(props, new Authenticator() {
	
	/**
	 * 身份验证
	 */
	@Override
	protected PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication(from , password);
	}
	});
	
	/**
	 * 实现邮件发送功能
	 */
	try {
		Message message = new MimeMessage(session);
		message.setFrom(new InternetAddress(from));
		message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
		message.setSubject(subject);
		message.setText(content);
		LOGGER.info("准备发送");
		Transport.send(message);
		LOGGER.info("发送完毕");
	} catch (AddressException e) {
		LOGGER.error(e.getMessage(),e);
	} catch (MessagingException e) {
		LOGGER.error(e.getMessage(),e);
	}

}

注:文中涉及到host、账号和密码为虚构,使用时请替换为自己真实的信息。

在实际使用中可能还会遇到这样的异常:

使用465加密端口发邮件时,提示如下信息:

com.sun.mail.smtp.SMTPSendFailedException: 553 authentication is 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)
    at javax.mail.Transport.send0(Transport.java:169)
    at javax.mail.Transport.send(Transport.java:98)

解决方法为:

      

  props.put("mail.smtp.auth", "true");     /*是"true"不是true,需重点注意*/


 

更新到服务器终于能正常发送邮件了。 

最近将项目部署到另一台阿里云服务器上,又遇到开头的问题,提示使用25端口号连接不到邮件服务器,可是代码里边明明指定的是465端口。百思不得其解之际,我想到这一行代码:

props.put("mail.smtp.auth", "true");     /*是"true"不是true,需重点注意*/

会不会跟声明的类型有关系呢,上面这行代码编码时写true也能编译通过,但是如果要加这个属性,只能传字符串类型,传boolean型就不可以。于是试着把port的类型由int改成String,重新运行后,终于能发送邮件了。这里我想是不是只能接收字符串类型,传递int类型接收不了,系统当作没传端口号使用默认的25端口号来处理了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值