Windows下java发送邮件代码部署在linux上

这篇文章是记录windows下的发送邮件的java代码部署在linux服务器上的一些经历和总结。

最后是用java调用shell脚本来完成发送邮件的,还有些坑留着继续踩。

1.Windows发送邮件的java代码

以qq为例子:

首先,有说授权码的获取。

在Windows下正常运行,但是放到linux下,就不行了。

// 需要用户名密码邮件发送实例
//文件名 SendEmail2.java
//本实例以QQ邮箱为例,你需要在qq后台设置

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendEmail2
{
   public static void main(String [] args)
   {
      // 收件人电子邮箱
      String to = "xxx@qq.com";

      // 发件人电子邮箱
      String from = "xxx@qq.com";

      // 指定发送邮件的主机为 smtp.qq.com
      String host = "smtp.qq.com";  //QQ 邮件服务器

      // 获取系统属性
      Properties properties = System.getProperties();

      // 设置邮件服务器
      properties.setProperty("mail.smtp.host", host);

      properties.put("mail.smtp.auth", "true");
      // 获取默认session对象
      Session session = Session.getDefaultInstance(properties,new Authenticator(){
        public PasswordAuthentication getPasswordAuthentication()
        {
         return new PasswordAuthentication("xxx@qq.com", "qq邮箱授权码"); //发件人邮件用户名、授权码
        }
       });

      try{
         // 创建默认的 MimeMessage 对象
         MimeMessage message = new MimeMessage(session);

         // Set From: 头部头字段
         message.setFrom(new InternetAddress(from));

         // Set To: 头部头字段
         message.addRecipient(Message.RecipientType.TO,
                                  new InternetAddress(to));

         // Set Subject: 头部头字段
         message.setSubject("This is the Subject Line!");

         // 设置消息体
         message.setText("This is actual message");

         // 发送消息
         Transport.send(message);
         System.out.println("Sent message successfully....from runoob.com");
      }catch (MessagingException mex) {
         mex.printStackTrace();
      }
   }
}

2.qq邮箱授权码

qq邮箱授权码不是邮箱密码。

打开qq邮箱,点击设置,再点击账户

然后找到这里

开启相应的smtp服务获取响应的授权码

3.查看tomcat服务器日志

直接把代码部署在linux上之后会报异常

tomcat服务器下logs文件下各个文件的含义

这个时候,会看到这个异常

排查原因后,可能是linux服务器没有开放相应的端口。

于是,开始着手,准备打开25号端口。

4.打开25号端口

查看开放的端口号

netstat -nupl (UDP类型的端口)
netstat -ntpl (TCP类型的端口)

a 表示所有

n表示不查询dns

t表示tcp协议

u表示udp协议

p表示查询占用的程序

l表示查询正在监听的程序

netstat -nupl|grep 25 //这个表示查找处于监听状态的,端口号为25的进程

专注It的csdn博客 Linux 查看服务器开放的端口号

linux防火墙iptables常用命令与基础知识

后来知道,阿里云轻量级应用服务器里面的防火墙默认是firewall。

因为我操作的是iptables,所以每次启动服务器之后,应该开启iptables防火墙,否则不会生效。

红豆110的csdn firewall防火墙详解(持续更新中...)

如果你用的是阿里云ECS服务器,打开了端口后,还是解决不了问题,那么是因为阿里云服务器禁掉了25号端口。

5.阿里云服务器禁25号端口

阿里云服务器出于安全原因封掉了25号端口,可以申请解封。

https://help.aliyun.com/knowledge_detail/56130.htm

如果你的是轻量级应用服务器,申请解封时,输入你的IP地址和域名时,会提示你不是你的本人资产。

咨询售后工程师,如果是轻量级应用服务器,那么不提供申请解封25号端口。

这个时候,就只能绕开25号端口。

6.配置mail.rc使用SMTP发送邮件

阿里云售后工程师建议可以使用465端口

关于465和587端口

​ 接着看465端口和587端口。我们知道25端口刚被设计出来时是用于转发邮件的,没有考虑认证、加密等问题。随着垃圾邮件泛滥、网络安全问题严重,MSA、ESMTP/SMTPS等概念和协议被设计出来。1997年465端口被注册用于加密方式(SMTPS)提交邮件,那时STARTTLS还没有捣腾出来。1998年STARTLS标准出炉,规定用587端口以STARTTLS方式提交邮件,465端口被吊销。然而许多客户端不支持STARTTLS,加上非常多邮件服务提供商都在使用465端口作为加密提交端口,于是465就一直这么被用到今天。

  简单来说,465端口只支持加密传输,不符合互联网号码分配结构(The Internet Assigned Numbers Authority,IANA)的标准,但一直被使用和支持;587端口专门被设计用来提交邮件,传输可以加密也可以不加密。

mail命令的系统级配置文件是/etc/mail.rc

可以参考

配置mail.rc使用SMTP发送邮件

set smtp=smtps://smtp.xxx.com:465   # 这里填入smtp地址

set smtp-auth=login                 # 认证方式

set smtp-auth-user=user@xxx.com     # 这里输入邮箱账号

set smtp-auth-password=password     # 这里填入密码

set ssl-verify=ignore               # 忽略证书警告

set nss-config-dir=/etc/pki/nssdb   # 证书所在目录

set from=user@xxx.com               # 设置发信人邮箱和昵称

#set smtp-use-starttls=yes          # STARTTLS时使用

7.java调用shell脚本

最后为了先快速解决发送邮件的问题,我想要不使用java调用shell脚本

参考博客: vcfriend的csdn博客

        ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, ip,hostname);
        pb.directory(new File(SHELL_FILE_DIR));
        int runningStatus = 0;
        String s = null;
        try {
            Process p = pb.start();
                try {
                    runningStatus = p.waitFor();
                } catch (InterruptedException e) {
                
                }
        } catch (IOException e) {
        
        }

RUNNING_SHELL_FILE:要运行的脚本
SHELL_FILE_DIR:要运行的脚本所在的目录; 当然你也可以把要运行的脚本写成全路径。
runningStatus:运行状态,0标识正常。 详细可以看java文档。
param1, param2, param3:可以在RUNNING_SHELL_FILE脚本中直接通过1,2,$3分别拿到的参数。

echo '邮件内容' | mail -s '邮件主题'

echo '访问者的IP地址为:'$1 '访问者的主机名称为'$2 | mail -s '有人访问了你的隐藏页面' 409265663@qq.com

到现在为止,目的达到了。

img

8.服务器运行的好好的,突然报的异常

javax.mail.AuthenticationFailedException

本来在windows下的tomcat上运行的好好的突然,报出这样异常,之前遇到服务器报出异常,是编译之后,而不是运行之中。

清理过项目缓存,清理过eclipse缓存,最终.....

经过了无数的排查方法,最后清掉浏览器缓存,给好了。

9.第一次惩罚

在把项目放到linux下的时候,如果重启tomcat之后,一时打不开项目不要着急,有可能你在经历“第一次惩罚”,意思为重启服务器的时候,第一次打开项目的时候特别特别慢,虽然windows下能快点,但是云服务器上可能会特别慢,慢到以为是自己的操作出了问题,进而进行重启之类的操作。

有一次,同学把课设项目部署在了linux上,以为是自己出错了,各种排查问题,后来无意发现过了好久自动好了,耽误了好长时间。所以部署上去,重启的时候,如果没有报错,右下角一直显示连接,那么继续等就好了。

不要误以为搞错了,去瞎操作。

这个问题,同学犯过两次。

Last modification:November 19th, 2019 at 12:42 am
如果觉得我的文章对你有用,请随意赞赏