MIME介绍详见:https://www.w3school.com.cn/media/media_mimeref.asp
通过Java发送电子邮件需要导入如下包:
javax-mail.jar:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7
以下通过QQ邮箱进行演示:
发送纯文本消息
- 创建Properties文件,配置协议、地址、端口、SSL认证
- 创建session对象
- 创建邮件消息对象
- 设置发件人、标题、正文、收件人、抄送人、密送人、发件时间
- 获取连接对象,并使用发件人账号与邮箱服务器建立连接
- 发送邮件
/**
* 创建邮件方法
* @param session javax.mail.session对象
* @param sender 发件人地址
* @param receive 收件人地址
* @param cReceive 抄送人
* @param bReceive 密送人
* @return
*/
public static MimeMessage createMIMEMessage(Session session,String sender,
String receive,String cReceive,String bReceive) {
MimeMessage message = new MimeMessage(session);
try {
// 标题、正文、发件人、收件人
message.setSubject("Title","UTF-8");// 标题、标题编码
Address addr = new InternetAddress(sender,"Hero","UTF-8");// 构建发件人对象
message.setFrom(addr);// 设置发件人
message.setContent("Hello World", "text/html;charset=utf-8");// 设置正文内容
/**
* 设置收件人
* 收件人:MimeMessage.RecipientType.TO
* 抄送:MimeMessage.RecipientType.CC
* 密送:MimeMessage.RecipientType.BCC
*/
message.setRecipient(MimeMessage.RecipientType.TO,
new InternetAddress(receive,"A","UTF-8"));// 收件人
message.setRecipient(MimeMessage.RecipientType.CC,
new InternetAddress(cReceive,"B","UTF-8"));// 抄送人
message.setRecipient(MimeMessage.RecipientType.BCC,
new InternetAddress(bReceive,"C","UTF-8"));// 密送人
message.setSentDate(new Date());// 设置发件时间
message.saveChanges();// 保存邮件
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
public static void main(String[] args) {
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");// 使用协议:smtp
props.setProperty("mail.smtp.host", "smtp.qq.com");// 协议地址
props.setProperty("mail.smtp.port", "465");// 协议端口
props.setProperty("mail.smtp.auth", "true");// 开启授权(QQ邮箱)
// QQ开启SSL安全认证
props.setProperty("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");// 配置SSL认证类
props.setProperty("mail.smtp.socketFactory.fallback",
"false");// 是否处理非SSL认证请求
props.setProperty("mail.smtp.socketFactory.port",
"465");// 配置SSL认证端口
Session session = Session.getInstance(props);// 产生session对象
session.setDebug(true);
// 创建邮件对象
MimeMessage message = createMIMEMessage(session, "邮箱1", "邮箱2", "邮箱3", "邮箱4");
try {
Transport transport = session.getTransport();// 创建连接对象
transport.connect("用户名", "授权码");// 建立连接(用户名、授权码)
transport.sendMessage(message, message.getAllRecipients());
transport.close();// 发送完毕关闭连接对象
} catch (Exception e) {
e.printStackTrace();
}
}
发送带附件邮件
邮件内容都是由单节点MimeBodyPart
构成,通过将这些单节点组合成复合节点MimeMultipart
从而实现附件操作。
实现步骤:
- 创建纯文本子节点(构造正文)
- 创建内嵌资源子节点(构造正文)
- 将正文子节点合并为复合节点(合并正文子节点)
- 将复合对象转换为子节点(正文只有拆分为子节点才能传输)
- 创建附件子节点
- 将正文子节点与附件子节点合并为复合节点
- 将合并后的复合节点内容作为邮件内容发送
代码实现:
由于邮件需要配置的信息较多,这里使用一个对象Mail
来承载邮件配置信息。
private String subject;// 邮件标题
private String senderMail;// 发件人邮箱
private String senderName;// 发件人名字
private String content;// 正文内容
private String sourcePath;// 内嵌资源路径
private String attachPath;// 附件路径
private String rReceive;// 收件人邮箱
private String ccReceive;// 抄送人邮箱
private String bccReceive;// 密送人邮箱
public Mail() {
super();
}
// 只有收件人的构造方法
public Mail(String subject, String senderMail, String senderName, String content, String sourcePath,
String attachPath, String rReceive) {
super();
this.subject = subject;
this.senderMail = senderMail;
this.senderName = senderName;
this.content = content;
this.sourcePath = sourcePath;
this.attachPath = attachPath;
this.rReceive = rReceive;
}
public Mail(String subject, String senderMail, String senderName, String content, String sourcePath,
String attachPath, String rReceive, String ccReceive, String bccReceive) {
super();
this.subject = subject;
this.senderMail = senderMail;
this.senderName = senderName;
this.content = content;
this.sourcePath = sourcePath;
this.attachPath = attachPath;
this.rReceive = rReceive;
this.ccReceive = ccReceive;
this.bccReceive = bccReceive;
}
// 省略getter and setter
/**
* 创建复杂邮件方法
* @param session javax.mail.Session对象
* @param sender 发件人
* @param rReceive 收件人
* @return MimeMessage
*/
public static MimeMessage createCompMail(Session session,Mail mail) {
MimeMessage message = new MimeMessage(session);// 构建邮件对象
try {
message.setSubject("Multipart Mail","UTF-8");// 标题
Address addr = new InternetAddress(mail.getSenderMail(),mail.getSenderName(),"UTF-8");
message.setFrom(addr);// 发件人
// 生成正文内容
MimeBodyPart contentPart = createContent(
mail.getContent(), mail.getSourcePath());
// 创建附件节点
MimeBodyPart attachmentPart = createAttachment(mail.getAttachPath());
// 将附件与正文关联
MimeMultipart part = new MimeMultipart();
part.addBodyPart(contentPart);
part.addBodyPart(attachmentPart);
/**
* Content-Type中MIME子类型
* 附件:mixed
* 内嵌资源:related
* 超文本:alternative
*/
part.setSubType("mixed");// 设置边界标识(附件与正文)
message.setContent(part,"text/html;charset=utf-8");// 邮件内容
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(mail.getrReceive(),"UTF-8"));// 收件人
// 判断抄送人是否填写
if(mail.getCcReceive() != null && mail.getCcReceive() != "") {
message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress(mail.getCcReceive(),"UTF-8"));// 抄送人
}
// 判断密送人是否填写
if(mail.getBccReceive() != null && mail.getBccReceive() != "") {
message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress(mail.getBccReceive(),"UTF-8"));// 密送人
}
message.setSentDate(new Date());// 发件时间
message.saveChanges();// 保存邮件内容
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
/**
* 创建正文内容方法
* @param str 正文内容
* @return MimeBodyPart
*/
public static MimeBodyPart createContent(String str) {
MimeBodyPart part = new MimeBodyPart();
try {
part.setContent(str, "text/html;charset=utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return part;
}
/**
* 创建正文内容方法
* @param str 文本内容
* @param source 图片路径
* @return MimeBodyPart
*/
public static MimeBodyPart createContent(String str,String source) {
MimeBodyPart part = null;
String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();// 生成UUID
try {
// 加载内嵌资源节点
MimeBodyPart sourcePart = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource(source));
sourcePart.setDataHandler(dh);
sourcePart.setContentID(uuid);
// 加载正文内容节点
MimeBodyPart contentPart = new MimeBodyPart();
contentPart.setContent(str + "<img src=cid:" + uuid + "/>", "text/html;charset=utf-8");
// 构造复合对象
MimeMultipart multiplePart = new MimeMultipart();
multiplePart.setSubType("related");// 设置分界标识
multiplePart.addBodyPart(sourcePart);
multiplePart.addBodyPart(contentPart);
// 将复合节点转换为子节点
part = new MimeBodyPart();
part.setContent(multiplePart);
} catch (Exception e) {
e.printStackTrace();
}
return part;
}
/**
* 创建附件内容方法
* @param filePath 附件文件路径
* @return MimeBodyPart
*/
public static MimeBodyPart createAttachment(String filePath) {
MimeBodyPart attachmentPart = new MimeBodyPart();
DataHandler handler = new DataHandler(new FileDataSource(filePath));
try {
attachmentPart.setDataHandler(handler);// 加载附件文件
attachmentPart.setFileName(handler.getName());// 设置附件文件名称
} catch (Exception e) {
e.printStackTrace();
}
return attachmentPart;
}
/**
* 配置Properties对象方法
* @return
*/
public static Properties configProps() {
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");// 使用协议:smtp
props.setProperty("mail.smtp.host", "smtp.qq.com");// 协议地址
props.setProperty("mail.smtp.port", "465");// 协议端口
props.setProperty("mail.smtp.auth", "true");// 开启授权(QQ邮箱)
// QQ开启SSL安全认证
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");// 配置SSL认证类
props.setProperty("mail.smtp.socketFactory.fallback", "false");// 是否处理非SSL认证请求
props.setProperty("mail.smtp.socketFactory.port", "465");// 配置SSL认证端口
return props;
}
public static void main(String[] args) {
Properties props = configProps();// 创建配置文件
Session session = Session.getInstance(props);// 创建Session对象
session.setDebug(true);// 开启邮件debug
Mail mail = new Mail();
mail.setSubject("Hello World");// 邮件标题
mail.setSenderName("Mystery Man");// 发件人名字
mail.setSenderMail("xxx@qq.com");// 发件人邮箱
mail.setContent("<h1>这是正文内容,这是一个网址:https://www.baidu.com,这是我的LOGO:</h1>");// 正文文本内容
mail.setSourcePath("src/icon.png");// 正文内嵌资源
mail.setAttachPath("src/icon.png");// 附件
mail.setrReceive("xxx@qq.com");// 收件人
mail.setCcReceive("xxx@qq.com");// 抄送人
mail.setBccReceive("xxx@qq.com");// 密送人
MimeMessage message = createCompMail(session,mail);
try {
Transport transport = session.getTransport();// 获取连接对象
transport.connect("xxx@qq.com", "xxx");// 通过用户名、授权码
transport.sendMessage(message, message.getAllRecipients());
transport.close();// 关闭连接
} catch (Exception e) {
e.printStackTrace();
}
}
注意:
在正文中显示的内容需要将复合节点
MimeMultipart
组装成单节点MimeBodyPart
,否则,不需要将复合节点MimeMultipart
组装成单节点MimeBodyPart
。
加载内嵌资源时需要通过DataHandler加载内嵌资源,并设置ContentID。该内嵌资源作为图片引用时,src路径设置为以下格式:cid:ContentID,如果内嵌图片资源无法加载,请检查src路径是否设置正确。
加载附件资源时需要通过DataHandler加载附件资源,并设置FileName。
以上并不完善,邮件中可能会包含多个内嵌资源、多个附件,这里只是演示包含单个内嵌资源及附件的情况。