SMTP服务以及SMTPS服务
1、场景介绍(为什么要使用SMTPS)
1、SMTP 服务使用明文通信,邮箱账号、密码极易被监听,导致邮箱被盗事件频繁发生、甚至发生泄密事件。
2、SMTPS是SSL/TLS通讯协议的 内容一开始就被保护起来了 是看不到原文的
它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。
为了加强网络安全管理,所以要使用SMTPS服务进行邮箱业务的完善
3、若只是简单的实现邮箱功能可以使用SMTP服务,若是追求安全性的邮箱业务必须要使用SMTPS服务
2、准备工作(业务实现的jar包等)
1、使用JAVA发送邮件前需要准备两个JAR包,分别为activation.jar与mail-1.4.7.jar
2、由于是使用SPring的JavaMailSenderImp实现的,所以JDK与Spring这些基础的也要准备好环境
jar包下载地址
链接:https://pan.baidu.com/s/1DiQDFjCPzc6y85JeZuGf-Q
提取码:rodb
- 1
- 2
3、使用 25 端口简单的实现SMTP服务(代码演示)
本次使用163邮箱为实例进行展示
3.1、首先创建一个公共方法类
package com.yadong.mailUtil;
import javax.mail.PasswordAuthentication;
class MailAuthenticator extends javax.mail.Authenticator {
private String strUser;
private String strPwd;
public MailAuthenticator(String user, String password) {
this.strUser = user;
this.strPwd = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(strUser, strPwd);
}
}
3.2、代码的实现内容
package com.yadong.mailUtil;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class MailUtil {
// 邮件分发器
public static JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
//这是发送邮件的标题
public static String subject = "这是发送邮件的标题";
//这是发送邮件的内容
public static String content = "这是发送邮件的内容";
//这是发送者Email
public static String fromAddress = "******@163.com";
//这是发送者的用户名
public static String smtpUserName = "*********@163.com";
//163邮箱的授权码,并不是163邮箱的密码,而是开启SMTP服务时给予的授权码
public static String smtpPassword = "******";
//接收者Email
public static String toAddress = "*******@qq.com";
//SMTP服务器
public static String ServerFromDB = "smtp.163.com";
//服务器的端口
private static String port = "25";
/**
* 发送邮件
*
* @param subject 标题
* @param content 内容
* @param fromAddress 发送者Email
* @param toAddress 接收者Email
* @throws Exception
*/
public static void sendEmail(final String subject, final String content,
final String fromAddress, final String toAddress) throws Exception {
mailSender.setHost(ServerFromDB);//SMTP服务器
mailSender.setPort(Integer.parseInt(port));//端口
Properties props = System.getProperties();
props.put("mail.smtp.auth", "true");
MailAuthenticator mailAuth = new MailAuthenticator(smtpUserName, smtpPassword);
Session session = Session.getInstance(props, mailAuth);
mailSender.setSession(session);
final InternetAddress[] mailToAddresses = new InternetAddress[1];
mailToAddresses[0] = new InternetAddress(toAddress);
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage)
throws MessagingException, UnsupportedEncodingException {
mimeMessage
.setRecipients(RecipientType.TO, mailToAddresses);
InternetAddress ia = new InternetAddress(fromAddress);
ia.setPersonal(fromAddress);
mimeMessage.setFrom(ia);
mimeMessage.setSentDate(new Date());
mimeMessage.setSubject(subject);
mimeMessage.setText(content);
}
};
mailSender.send(preparator);
}
public static void main(String[] args) throws Exception {
sendEmail(subject,content,fromAddress,toAddress);
}
}
4、使用 465 端口实现SMTPS服务(代码演示)
本次使用163邮箱服务器的465端口为实例进行展示
4.1、首先创建一个公共方法类
package com.yadong.mailUtil;
import javax.mail.PasswordAuthentication;
class MailAuthenticator extends javax.mail.Authenticator {
private String strUser;
private String strPwd;
public MailAuthenticator(String user, String password) {
this.strUser = user;
this.strPwd = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(strUser, strPwd);
}
}
4.2、代码实现的内容
package com.yadong.mailUtil;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class MailUtil {
// 邮件分发器
public static JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
//这是发送邮件的标题
public static String subject = "这是发送邮件的标题";
//这是发送邮件的内容
public static String content = "这是发送邮件的内容";
//这是发送者Email
public static String fromAddress = "******@163.com";
//这是发送者的用户名
public static String smtpUserName = "********@163.com";
//163邮箱的授权码,并不是163邮箱的密码,而是开启SMTP服务时给予的授权码
public static String smtpPassword = "******";
//接收者Email
public static String toAddress = "*******@qq.com";
//SMTP服务器
public static String ServerFromDB = "smtp.163.com";
//服务器的端口
private static String port = "465";
/**
* 发送邮件
*
* @param subject 标题
* @param content 内容
* @param fromAddress 发送者Email
* @param toAddress 接收者Email
* @throws Exception
*/
public static void sendEmail(final String subject, final String content,
final String fromAddress, final String toAddress) throws Exception {
mailSender.setHost(ServerFromDB);//SMTP服务器
mailSender.setPort(Integer.parseInt(port));//端口
Properties props = System.getProperties();
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.port", port);
props.setProperty("mail.smtp.socketFactory.port", port);
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");
MailAuthenticator mailAuth = new MailAuthenticator(smtpUserName, smtpPassword);
Session session = Session.getInstance(props, mailAuth);
mailSender.setSession(session);
final InternetAddress[] mailToAddresses = new InternetAddress[1];
mailToAddresses[0] = new InternetAddress(toAddress);
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage)
throws MessagingException, UnsupportedEncodingException {
mimeMessage
.setRecipients(RecipientType.TO, mailToAddresses);
InternetAddress ia = new InternetAddress(fromAddress);
ia.setPersonal(fromAddress);
mimeMessage.setFrom(ia);
mimeMessage.setSentDate(new Date());
mimeMessage.setSubject(subject);
mimeMessage.setText(content);
}
};
mailSender.send(preparator);
}
public static void main(String[] args) throws Exception {
sendEmail(subject,content,fromAddress,toAddress);
}
}
4.3、SMTP与SMTPS代码实现的区别
//代码的主体并没有变化,而是在properties配置类中增加一些配置,分别为以下配置
Properties props = System.getProperties();
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.port", "465");
props.setProperty("mail.smtp.socketFactory.port", "465");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");
5、可能遇到的错误
5.1、Could not connect to SMTP host: smtp.163.com, port: 465;
5.1.1、解决方案一
查看自己设备是否可以PING通服务器
1、首先打开设备的telnet功能
控制面板(查看方式小图标) -》 程序与功能 -》启用或关闭window功能
打开CMD 输入 telnet smtp.163.com 465
显示黑窗口则表示可以PING通,如果PING不通则显示链接失败
5.1.2、解决方案二
添加配置
props.setProperty("mail.smtp.ssl.enable", true);
//将smtp.163.com修改为IP地址
props.setProperty("mail.smtp.host", "220.181.12.16"); //smtp.163.com
5.1.3、解决方案二
修改java.security:不要SSL3,TLSv1, TLSv1.1
# dk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
jdk.tls.disabledAlgorithms=RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
5.2、Unrecognized SSL message, plaintext connection?
5.2.1、解决方案一
检查端口是否正确
检查是否使用的25端口,却是465端口的配置?
5.3、unable to find valid certification path to requested target
5.2.1、解决方案一
一、导入证书
因为ssl 465端口是加密的https,所以需要将邮箱服务器的证书导入到java虚拟机环境。
更加详情的步骤可以查看 使用keytool将https证书导入JDK详情步骤
导入https证书具体路径如下:
1. 从邮箱服务器上下载证书,具体步骤可以参考网页:
https://jingyan.baidu.com/article/e75aca851e0b5f142edac632.html
2. 保存证书到服务器磁盘后,打开cmd命令行窗口,进入到项目使用的java环境的bin目录
3. 在cmd命令行窗口执行如下两条命令:
keytool.exe -importcert -file C:\Users\Administrator\Desktop\163.cer -keystore F:\Java\jdk1.8.0_171\jre\lib\security\cacerts -storepass changeit -alias 163.cer
keytool.exe -importcert -file C:\Users\Administrator\Desktop\163.cer -keystore F:\Java\jdk1.8.0_171\jre\lib\security\jssecacerts -storepass changeit -alias 163.cer
其中C:\Users\Administrator\Desktop\youjianbuding\163.cer为第一步导出的证书的磁盘路径;
F:\Java\jdk1.8.0_171\jre\lib\security\cacerts为项目使用的jdk的证书环境。
-alias 163.cer 为起别名
4. 执行命令后会出现如下提示:是否信任证书。输入Y即可。然后证书就导入java环境成功。
DNSName 中含有SMTP 服务器地址的证书才能成功发送邮件,若证书中不包含SMTP 服务器地址,则无法发送
关于导入证书,详情可以查看 https://blog.csdn.net/qq_45728838/article/details/128547568?spm=1001.2014.3001.5501