依赖
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
package com.rjj.demo.tools.mail;
import com.jfinal.log.Log;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
/**
** 邮件
* * 1.普通文本 sendText html消息 sendHtml
* * 2.图片
* * 3.附件 sendFile
* * 4.文本+图片 sendTextPhoto
* * 5.图片文本附件 sendTextPhotoFile
* * 6.抄送,密送
* * 7.群发【普通发送的时候把发送地址拼接字符串a,b.c】
*/
public class MailUtilMe {
private Log logger = Log.getLog(MailUtil.class);
//发件箱
private String fromEmail = "215060580@qq.com";
//发件箱别名
private String personel = "淡淡人生过";
//发件箱密码
private String password = "rylihxxxxxxzcajb";
//端口
private String port = "465";
//主机地址
private String host = "smtp.qq.com";
//收件人邮箱
private String toEmail = "253481340@qq.com";
//主题
private String subject ="淡淡人生过的第一份邮件";
//获取基本配置,这种可能会报错
/**
* 会报错javax.net.ssl.SSLHandshakeException:
* sun.security.validator.ValidatorException:
* PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
* unable to find valid certification path to requested target
*
* 错误很简单,就是证书路径无效,网上有人说使用代码下载证书到本地jre证书库中,
* 或者直接导入此证书到jre证书;确实可以;但是我们可以在代码中信任此站点证书
* @return
*/
public Properties getProperties(){
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties props = System.getProperties();
props.setProperty("mail.host", host);//主机
props.put("mail.transport.protocol", "smtp");//链接协议
props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.port", port);
props.setProperty("mail.smtp.socketFactory.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable","true");//开启ssl加密
props.put("mail.debug", "true");// 设置是否显示debug信息 true 会在控制台显示相关信息
return props;
}
/**
* 基本不会出现问题
* @return
*/
public Properties getProp(){
Properties props = System.getProperties();
props.setProperty("mail.host", host);//主机地址
props.put("mail.transport.protocol", "smtp");//链接协议
props.setProperty("mail.smtp.port", port);//端口
props.put("mail.smtp.auth", "true"); // 允许smtp校验
MailSSLSocketFactory sf = null;
try {
sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
} catch (GeneralSecurityException e) {
logger.info("error", e);
}
props.put("mail.smtp.ssl.enable", "true");//开启ssl加密
props.put("mail.smtp.ssl.socketFactory", sf);
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.socketFactory.port", port);
props.put("mail.debug", "true");// 设置是否显示debug信息 true 会在控制台显示相关信息
return props;
}
/**
* 获取session
*/
public Session getSession(){
Properties prop = getProp();
Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail,password);
}
});
return session;
}
public MimeMessage getMineMessage() {
Session session = getSession();
// 创建默认的 MimeMessage 对象
MimeMessage message = new MimeMessage(session);
try {
// Set From: 头部头字段,设置了默认名称,就会显示发送人为 "淡淡人生过"
message.setFrom(new InternetAddress(fromEmail,personel));
/**
* Set To: 头部头字段
*
* Message.RecipientType.TO 普通发送
* Message.RecipientType.CC 抄送
* Message.RecipientType.BCC 密送
*/
//给一个人发送邮件
message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
//给多个人发送邮件
//message.addRecipients(Message.RecipientType.TO,new Address[]{new InternetAddress(toEmail),new InternetAddress(toEmail)});
//message.addRecipients(Message.RecipientType.CC,new Address[]{new InternetAddress(toEmail)});
//message.addRecipients(Message.RecipientType.BCC,new Address[]{new InternetAddress(toEmail)});
// Set Subject: 头部头字段
message.setSubject(subject,"UTF-8");
//设置邮件的发送时间
message.setSentDate(new Date());
} catch (MessagingException e) {
logger.info("1出现异常:" + e.getMessage());
} catch (UnsupportedEncodingException e) {
logger.info("2出现异常:" + e.getMessage());
}
return message;
}
/**
* 发送邮件
*
* 普通文本消息
*/
public void sendText(String content) {
MimeMessage message = getMineMessage();
// 设置消息体
try {
message.setText(content);
Transport.send(message);
} catch (MessagingException e) {
logger.info("设置文本内容出现异常:" + e.getMessage());
}
}
/**
* 发送邮件
*
* html消息
*/
public void sendHtml(String content){
MimeMessage message = getMineMessage();
try {
message.setContent(content,"text/html;charset=UTF-8");
Transport.send(message);
} catch (MessagingException e) {
logger.info("设置html内容出现异常:" + e.getMessage());
}
}
/**
* 发送带附件的邮件
*/
public void sendFile(String content, String pathFileName){
MimeMessage message = getMineMessage();
// 创建多重消息
Multipart multipart = new MimeMultipart();
try {
// 创建消息部分
BodyPart messageBodyPart = new MimeBodyPart();
// 消息,这里的消息不发送也是可以的
// messageBodyPart.setText(content);
messageBodyPart.setContent(content, "text/html; charset=utf-8");
// 设置文本消息部分
multipart.addBodyPart(messageBodyPart);
// 附件部分
messageBodyPart = new MimeBodyPart();
//获取文件
DataSource source = new FileDataSource(pathFileName);
messageBodyPart.setDataHandler(new DataHandler(source));
//设置文件名称
messageBodyPart.setFileName(MimeUtility.encodeText(source.getName()));
//添加到多重消息容器中
multipart.addBodyPart(messageBodyPart);
// 发送完整消息
message.setContent(multipart);
// 发送消息
Transport.send(message);
} catch (MessagingException e) {
logger.info("发送附件邮件出现异常:" + e.getMessage());
} catch (UnsupportedEncodingException e) {
logger.info("文件名称编码异常:" + e.getMessage());
}
}
/**
* 多文件下载
* @param content 信息
* @param pathFileName 多个附件的路径
*/
public void sendFileList(String content, List<String> pathFileName){
MimeMessage message = getMineMessage();
try {
// 创建多重消息
Multipart multipart = new MimeMultipart();
//消息
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(content,"text/html; charset=utf-8");
multipart.addBodyPart(messageBodyPart);
for (String filePath : pathFileName) {
// 附件部分
// 创建消息部分
messageBodyPart = new MimeBodyPart();
//获取文件
DataSource source = new FileDataSource(filePath);
messageBodyPart.setDataHandler(new DataHandler(source));
//设置文件名称
messageBodyPart.setFileName(MimeUtility.encodeText(source.getName()));
//添加到多重消息容器中
multipart.addBodyPart(messageBodyPart);
}
// 发送完整消息
message.setContent(multipart);
// 发送消息
Transport.send(message);
} catch (MessagingException e) {
logger.info("发送附件邮件出现异常:" + e.getMessage());
} catch (UnsupportedEncodingException e) {
logger.info("文件名称编码异常:" + e.getMessage());
}
}
/**
* 发送图片和附件邮件
*/
public void sendTextPhotoFile(){
String pathName = "/Users/renjianjun/study/ideaWorkSpace/jfinal_demo/src/main/webapp/static/img/lyf.jpg";
MimeMessage message = getMineMessage();
try {
// 1.创建图片"节点"
MimeBodyPart image = new MimeBodyPart();
// 读取本地文件
DataHandler dh = new DataHandler(new FileDataSource(pathName));
// 将图片数据添加到"节点"
image.setDataHandler(dh);
// 为"节点"设置一个唯一编号(在文本"节点"将引用该ID)
image.setContentID("mailTestPic");
// 2. 创建文本"节点"
MimeBodyPart text = new MimeBodyPart();
// 这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片
/**
*
这里在img标签中src属性中添加了cid:mailTestPic 其实就是把图片和我发送的图片关联起来了,点击图片就会跳到我的路径所在的地址
这里使用a标签包裹了,我的图片,发送的内容其实时html的,所以有些标签不显示,其实一html的标签
*/
text.setContent(
"这是一张图片<br/><a href='http://www.cnblogs.com/ysocean/p/7666061.html'>" + //我想要点击图片跳到的地址
"<img src='cid:mailTestPic'/>" + //图片,可以写网络图片的地址
"</a>"
, "text/html;charset=UTF-8");//html,使用utf-8,识别
// 3. (文本+图片)设置 文本 和 图片"节点"的关系(将 文本 和 图片"节点"合成一个混合"节点")
MimeMultipart mm_text_image = new MimeMultipart();
mm_text_image.addBodyPart(text);
mm_text_image.addBodyPart(image);
mm_text_image.setSubType("related"); // 关联关系
// 4. 将 文本+图片 的混合"节点"封装成一个普通"节点"
// 最终添加到邮件的 Content 是由多个 BodyPart 组成的 Multipart, 所以我们需要的是 BodyPart,
// 上面的 mailTestPic 并非 BodyPart, 所有要把 mm_text_image 封装成一个 BodyPart
MimeBodyPart text_image = new MimeBodyPart();
text_image.setContent(mm_text_image);
// 5. 创建附件"节点"
MimeBodyPart attachment = new MimeBodyPart();
// 读取本地文件
DataHandler dh2 = new DataHandler(new FileDataSource(pathName));
// 将附件数据添加到"节点"
attachment.setDataHandler(dh2);
// 设置附件的文件名(需要编码)
attachment.setFileName(MimeUtility.encodeText(dh2.getName()));
// 6. 设置(文本+图片)和 附件 的关系(合成一个大的混合"节点" / Multipart )
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text_image);
mm.addBodyPart(attachment); // 如果有多个附件,可以创建多个多次添加
mm.setSubType("mixed"); // 混合关系
// 7. 设置整个邮件的关系(将最终的混合"节点"作为邮件的内容添加到邮件对象)
message.setContent(mm);
Transport.send(message);
} catch (MessagingException e) {
logger.info("图片文本文件消息异常:" + e.getMessage());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void sendTextPhoto(){
String pathName = "/Users/renjianjun/study/ideaWorkSpace/jfinal_demo/src/main/webapp/static/img/lyf.jpg";
MimeMessage message = getMineMessage();
try {
// 1.创建图片"节点"
MimeBodyPart image = new MimeBodyPart();
// 读取本地文件
DataHandler dh = new DataHandler(new FileDataSource(pathName));
// 将图片数据添加到"节点"
image.setDataHandler(dh);
// 为"节点"设置一个唯一编号(在文本"节点"将引用该ID)
image.setContentID("mailTestPic");
// 2. 创建文本"节点"
MimeBodyPart text = new MimeBodyPart();
// 这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片
/**
*
这里在img标签中src属性中添加了cid:mailTestPic 其实就是把图片和我发送的图片关联起来了,点击图片就会跳到我的路径所在的地址
这里使用a标签包裹了,我的图片,发送的内容其实时html的,所以有些标签不显示,其实一html的标签
*/
text.setContent(
"这是一张图片<br/><a href='http://www.cnblogs.com/ysocean/p/7666061.html'>" + //我想要点击图片跳到的地址
"<img src='cid:mailTestPic'/>" + //图片,可以写网络图片的地址
"</a>"
, "text/html;charset=UTF-8");//html,使用utf-8,识别
// 3. (文本+图片)设置 文本 和 图片"节点"的关系(将 文本 和 图片"节点"合成一个混合"节点")
MimeMultipart mm_text_image = new MimeMultipart();
mm_text_image.addBodyPart(text);
mm_text_image.addBodyPart(image);
/**
* 邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。常见的简单类型有text/plain(纯文本)和text/html(超文本)。有时也会出现的multipart类型,是MIME邮件的精髓。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。
*
* multipart/mixed:附件。
*
* multipart/related:内嵌资源。
*
* multipart/alternative:纯文本与超文本共存。
*/
mm_text_image.setSubType("mixed"); // 关联关系,这里图片相当于附件了,只是在正文内容中一img标签显示出来了
// 7. 设置整个邮件的关系(将最终的混合"节点"作为邮件的内容添加到邮件对象)
message.setContent(mm_text_image);
Transport.send(message);
} catch (MessagingException e) {
logger.info("发送文本图片消息出现异常:" + e.getMessage());
}
}
public static void main(String[] args) {
String pathName = "/Users/renjianjun/study/ideaWorkSpace/jfinal_demo/src/main/webapp/static/img/lyf.jpg";
MailUtilMe m = new MailUtilMe();
//m.sendTextPhotoFile();
//m.sendText("a");
//m.sendHtml("<b>你好</b>");
// m.sendFile("刘亦菲哦",pathName);
// m.sendTextPhoto();
List<String> list = new ArrayList<>(2);
list.add("/Users/renjianjun/study/ideaWorkSpace/demo/src/main/resources/static/img/lyf.jpg");
list.add("/Users/renjianjun/study/ideaWorkSpace/demo/src/main/resources/static/img/lyf.jpg");
m.sendFileList("刘亦菲",list);
}
}