注意:hutool
工具包对邮件发送封装的非常简单了,但是他使用的是非SSL
的形式发送。非SSL
发送邮箱使用的25
端口,但是这个端口开放是非常危险的,阿里云和腾讯云默认是关闭的。如果需要开启需要申请,最终能不能开启还是一个未知数。当然,如果你在本地测试是没有问题的,如果你的是本地服务器,那么可以不用考虑这个问题。如果是云服务器,那么自己封装邮件。详细参考第三节。
hutool
发送邮件详细参考官方文档:https://www.hutool.cn/docs/#/extra/邮件工具-MailUtil
163邮箱官网:https://mail.163.com/
最主要的是要获取到授权码。
将手机扫描这个二维码,会显示一个数字和一个号码。使用注册邮箱的这个手机号发送这个数字到指定的这个号码中,点击这个我已发送。
这样就设置完了,如果授权码丢失了,或者是授权密码管理这里删除了,就从新在上面开启,重新获取授权码即可。
登录地址:https://m0.mail.sina.com.cn/
点击授权码状态,点击开启会有一个手机号认证,认证通过就可以拿到授权码了。这个授权码只显示一次,如果忘记就只能重新获取。
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.1.4version>
dependency>
<dependency>
<groupId>javax.mailgroupId>
<artifactId>mailartifactId>
<version>1.4.7version>
dependency>
如果是springboot
应用,那么mail
依赖可以更换为一下。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
MailUtil.send("[email protected]", "测试", "邮件来自Hutool测试", false);
MailUtil.send("[email protected]", "测试", "邮件来自Hutool测试
", true, FileUtil.file("d:/aaa.xml"));
ArrayList<String> tos = CollUtil.newArrayList(
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]");
MailUtil.send(tos, "测试", "邮件来自Hutool群发测试", false);
发送邮件非常简单,只需一个方法即可搞定其中按照参数顺序说明如下:
tos
: 对方的邮箱地址,可以是单个,也可以是多个(Collection
表示)subject
:标题content
:邮件正文,可以是文本,也可以是HTML
内容isHtml
: 是否为HTML
,如果是,那参数3识别为HTML
内容files
: 可选:附件,可以为多个或没有,将File
对象加在最后一个可变参数中即可 @Test
public void sendMail(){
MailAccount account = new MailAccount();
// 邮箱服务地址
account.setHost("smtp.163.com");
// 端口,针对不同服务器的端口不同
account.setPort(25);
// 设置是否需要用户名密码验证
account.setAuth(true);
// 设置为发送方,就是刚才开启授权的这个邮箱
account.setFrom("[email protected]");
// 设置用户名,这个用户名必须是发送方的这个邮箱
account.setUser("[email protected]");
// 授权码,既是刚才获取的那个授权码
account.setPass("XLHBTOHQRTEXNNLE");
// 群发
// MailUtil.send(account, CollUtil.newArrayList("[email protected]","[email protected]"), "邮箱标题", "这是邮箱的内容区", false);
// 单发
// MailUtil.send(account,"[email protected]", "测试", "邮件来自Hutool测试", false);
// 最后一个参数true:表示将内容区识别为HTML代码,但是标题不能识别
MailUtil.send(account,"[email protected]", "测试", "邮件来自Hutool测试redis延迟队列", true);
}
邮箱的服务器地址在邮箱设置这里可以看到。
对应端口如下
详细信息参考:http://help.mail.163.com/faqDetail.do?code=d7a5dc8471cd0c0e8b4b8f4f8e49998b374173cfe9171305fa1ce630d7f67ac2cda80145a1742516
注意:这种新式端口号为 465
,而上面的非SSL
端口号是25
,就是因为25
端口号的特殊性,所以才选择SSL
发送的。
package com.centre.common.model;
import lombok.Getter;
import lombok.Setter;
/**
* 发送邮箱实体类
* @Author: Stars
* @Date: 2021/1/10 19:00
*/
@Getter
@Setter
public class MailAccounts {
/**
* 邮箱地址,就是邮箱服务器的地址,在获取授权码那个页面可以获取到
*/
private String host = "smtp.163.com" ;
/**
* 端口号,SSL模式
*/
private Integer port = 465 ;
/***
* 设置是否需要用户名密码验证,一般为true
*/
private Boolean auth = true;
/***
* 发送方地址,获取授权码的邮箱
*/
private String from = "[email protected]" ;
/**
* 设置用户名,这个用户名必须是发送方的这个邮箱
*/
private String user = "[email protected]" ;
/***
* 授权码,既是刚才获取的那个授权码
*/
private String pass = "XXXXXXX" ;
/**
* 发送地址
*/
private String toAddress ;
/**
* 发送主题
*/
private String subject ;
/**
* 发送内容
*/
private String content ;
/**
* 是否为HTML格式,true:是,false:不是
*/
private Boolean isHtml = false ;
/**
* 发送者名称
*/
private String personal = "XXXX";
/**
* 对象邮箱
*/
private String[] to ;
/**
* 附件路径信息集合
*/
private String[] fileUploadNames = null ;
public void setTo(String ... to){
this.to = to;
}
public void setFileUploadNames(String ... fileUploadNames){
this.fileUploadNames = fileUploadNames ;
}
}
除了 fileUploadNames
附件地址和 toAddress
发送地址(不用,可以删除)以外,其他字段都是需要的,但是有很多我已经设置了默认值了。
package com.centre.common.utils;
import com.centre.common.exception.BusinessException;
import com.centre.common.model.MailAccounts;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
/**
* @Author: Stars
* @Date: 2021/1/10 18:41
*/
public class MailSendUtils {
/**
* 邮箱发送
* @param mailAccounts
* @throws Exception
*/
public void send(MailAccounts mailAccounts)throws Exception{
Message message = getMessage(mailAccounts);
// MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象
Multipart multipart = new MimeMultipart();
// 创建一个包含HTML内容的MimeBodyPart
BodyPart htmlOrTest = new MimeBodyPart();
if (mailAccounts.getIsHtml()) {
// 设置HTML内容
htmlOrTest.setContent(mailAccounts.getContent(), "text/html; charset=utf-8");
}else {
htmlOrTest.setText(mailAccounts.getContent());
}
// 添加发送内容
multipart.addBodyPart(htmlOrTest);
if (mailAccounts.getFileUploadNames() != null){
// 添加附件
for (String fileName : mailAccounts.getFileUploadNames()) {
addEnclosure(multipart,fileName);
}
}
// 将MiniMultipart对象设置为邮件内容
message.setContent(multipart);
Transport.send(message);
}
/**
* 添加附件
* @param multipart
* @param fileName 附件所在的地址
* @throws Exception
*/
private void addEnclosure(Multipart multipart,String fileName) throws Exception{
BodyPart adjunct = new MimeBodyPart();
FileDataSource fileDataSource = new FileDataSource(fileName);
adjunct.setDataHandler(new DataHandler(fileDataSource));
adjunct.setFileName(changeEncode(fileDataSource.getName()));
multipart.addBodyPart(adjunct);
}
/**
* 进行base64加密,防止中文乱码
* */
public String changeEncode(String str) {
try {
str = MimeUtility.encodeText(new String(str.getBytes(), "UTF-8"),
"UTF-8", "B"); // "B"代表Base64
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return str;
}
private Message getMessage(MailAccounts mailAccounts) throws Exception{
Properties properties = System.getProperties() ;
properties.setProperty("mail.smtp.host", mailAccounts.getHost());
properties.setProperty("mail.smtp.auth", mailAccounts.getAuth().toString());
properties.setProperty("mail.smtp.user", mailAccounts.getFrom());
properties.setProperty("mail.smtp.pass", mailAccounts.getPass());
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); //使用JSSE的SSL socketfactory来取代默认的socketfactory
properties.put("mail.smtp.socketFactory.fallback", "false"); // 只处理SSL的连接,对于非SSL的连接不做处理
properties.put("mail.smtp.port", mailAccounts.getPort());
properties.put("mail.smtp.socketFactory.port", mailAccounts.getPort());
// 根据邮件会话属性和密码验证器构造一个发送邮件的session
Session session = Session.getInstance(properties, new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(properties.getProperty("mail.smtp.user"),properties.getProperty("mail.smtp.pass"));
}
});
session.setDebug(true);
Message message = new MimeMessage(session);
//消息发送的主题
message.setSubject(mailAccounts.getSubject());
//消息的发送者
message.setFrom(new InternetAddress(properties.getProperty("mail.smtp.user"),mailAccounts.getPersonal()));
if (mailAccounts.getTo().length <= 0){
throw new BusinessException("收件人不能为空!!");
}
for (String strAdd : mailAccounts.getTo()) {
// 创建邮件的接收者地址,并设置到邮件消息中
message.setRecipient(Message.RecipientType.TO,new InternetAddress(strAdd));
}
// 消息发送的时间
message.setSentDate(new Date());
return message ;
}
}
public static void main(String[] args) {
MailAccounts mailAccounts = new MailAccounts();
mailAccounts.setTo("[email protected]");
mailAccounts.setSubject("这是发送主题");
mailAccounts.setContent("这是发送内容");
mailAccounts.setIsHtml(true);
mailAccounts.setFileUploadNames("D:\\我靠.txt","D:\\admin.txt");
try {
new MailSendUtils().send(mailAccounts);
}catch (Exception e){
e.printStackTrace();
}
}
这样就可以了,我个人推荐使用SSL
的形式发送邮件,虽然工具封装的稍微有点复杂。但是可以直接copy
我写好的去使用就行了,几乎可以满足要求了。