由于最近自己业余开发的一个项目用到邮件通知,一直想写一篇博客记录,拖到现在,下面带大家从头开始介绍。
一、RFC882文档简单说明
RFC882文档规定了如何编写一封简单的邮件(纯文本邮件),一封简单的邮件包含邮件头和邮件体两个部分,邮件头和邮件体之间使用空行分隔。
邮件头包含的内容有:
from字段 --用于指明发件人
to字段 --用于指明收件人
subject字段 --用于说明邮件主题
cc字段 -- 抄送,将邮件发送给收件人的同时抄送给另一个收件人,收件人可以看到邮件抄送给了谁
bcc字段 -- 密送,将邮件发送给收件人的同时将邮件秘密发送给另一个收件人,收件人无法看到邮件密送给了谁
邮件体指的就是邮件的具体内容。
二、MIME协议简单介绍
在我们的实际开发当中,一封邮件既可能包含图片,又可能包含有附件,在这样的情况下,RFC882文档规定的邮件格式就无法满足要求了。
MIME协议是对RFC822文档的升级和补充,它描述了如何生产一封复杂的邮件。通常我们把MIME协议描述的邮件称之为MIME邮件。MIME协议描述的数据称之为MIME消息。
对于一封复杂邮件,如果包含了多个不同的数据,MIME协议规定了要使用分隔线对多段数据进行分隔,并使用Content-Type头字段对数据的类型、以及多个数据之间的关系进行描述。
三、使用JavaMail创建邮件和发送邮件
JavaMail创建的邮件是基于MIME协议的。因此可以使用JavaMail创建出包含图片,包含附件的复杂邮件。
发送包含内嵌图片和附件的复杂邮件
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class SendMail {
/* 发件人账户名 */
public static String senderAccount = "xxxxxxxx@foxmail.com";
/* 发件人账户密码(授权码) */
public static String senderPassword = "xxxxxx";
/* 发件人地址 */
public static String senderAddress = "xxxxxxxx@foxmail.com";
public static void main(String[] args) throws Exception {
/* 设置多个收件人 */
String[] recipientAddress = {"xxxx@163.com","xxxx@qq.com"};
Map<String, String> map = new HashMap();
map.put("imageAddr", "E:\\11.jpg"); /* 设置邮件图片 */
/* 以下参数为空,默认不传 */
/* 设置邮件主题 */
map.put("subject", "小主,请查收你的一周小结");
/* 设置邮件内容 */
map.put("content", "简单的纯文本邮件!");
/* 设置邮件附件 */
map.put("attach", "E:\\11.jpg");
perform(map, recipientAddress);
}
/**
* 发送邮件
*/
public static void perform(Map<String, String> map, String[] recipientAddress) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com"); /* 主机名 */
prop.setProperty("mail.transport.protocol", "smtp"); /* 连接协议 */
prop.setProperty("mail.smtp.auth", "true");
prop.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
prop.setProperty("mail.smtp.port", "465");// 端口号
prop.setProperty("mail.smtp.socketFactory.port", "465");
/* 使用JavaMail发送邮件的5个步骤 */
Session session = Session.getInstance(prop); /* 1.创建session */
/* 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态 */
session.setDebug(true);
/* 2.通过session得到transport对象 */
Transport ts = session.getTransport();
/* 3.连上邮件服务器 */
ts.connect(senderAccount, senderPassword);
Message message = createMixedMail(session, map, recipientAddress); /* 4.创建邮件 */
ts.sendMessage(message, message.getAllRecipients()); /* 5.发送邮件 */
ts.close();
}
/**
* @param session
* @param map
* @param recipientAddress
* @return
* @throws Exception
* @Method: createMixedMail
* @Description: 创建邮件
* @Anthor:米斯特李
*/
public static MimeMessage createMixedMail(Session session, Map<String, String> map, String[] recipientAddress) throws Exception {
MimeMessage message = new MimeMessage(session); /* 创建邮件 */
message.setFrom(new InternetAddress(senderAddress)); /* 设置发件人地址 */
/* 设置收件人地址(可以增加多个收件人、抄送、密送),即下面这一行代码书写多行
* MimeMessage.RecipientType.TO:发送
* MimeMessage.RecipientType.CC:抄送
* MimeMessage.RecipientType.BCC:密送
*/
InternetAddress[] sendTo = new InternetAddress[recipientAddress.length];
for (int i = 0; i < recipientAddress.length; i++)
sendTo[i] = new InternetAddress(recipientAddress[i]);
/* 设置多个收件人 */
message.setRecipients(MimeMessage.RecipientType.TO, sendTo);
message.setSubject(map.get("subject"), "UTF-8"); /* 设置邮件主题 */
MimeBodyPart image = new MimeBodyPart();
DataHandler dh1 = new DataHandler(new FileDataSource(map.get("imageAddr")));
image.setDataHandler(dh1); /* 将数据添加到节点 */
/* 为"节点"设置一个唯一编号 */
image.setContentID("image_id");
MimeBodyPart text = new MimeBodyPart();/* 设置邮件内容 */
/** 生成的图片唯一编号,需要引用到内容当中 */
String contentStr = map.get("content")+"这是一张图片<br/><img src='cid:image_id'/>";
if (StringUtils.isNotEmpty(contentStr))
text.setContent(contentStr, "text/html;charset=UTF-8");
else
text.setContent("", "text/html;charset=UTF-8");
MimeBodyPart attach = new MimeBodyPart(); /* 附件 */
MimeMultipart mp2 = new MimeMultipart(); /* 描述关系:正文和附件 */
String attachStr = map.get("attach");
if (StringUtils.isNotEmpty(attachStr)) {
DataHandler dh = new DataHandler(new FileDataSource(attachStr));
attach.setDataHandler(dh);
attach.setFileName(dh.getName());
mp2.addBodyPart(attach);
}
/* 描述关系:正文和图片 */
MimeMultipart mp1 = new MimeMultipart();
mp1.addBodyPart(text);
mp1.addBodyPart(image);
mp1.setSubType("related");
//代表正文的bodypart
MimeBodyPart content = new MimeBodyPart();
content.setContent(mp1);
mp2.addBodyPart(content);
mp2.setSubType("mixed");
message.setContent(mp2);
message.saveChanges();
message.writeTo(new FileOutputStream("E:\\MixedMail.eml"));
return message;
}
}
这边介绍两种QQ和163邮箱获取授权码的方式。
除了需要授权码以外还需要两个jar包,如果是使用maven管理的请在pom.xml中加上
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
若需要下载,这边提供
百度链接:https://pan.baidu.com/s/1gxAHNtp8xwqI3wsbFGMm5w
提取码:hkqz
永久有效,楼主总结的技术有需要到jar一律免费提供,不需要积分。