Java Email 发HTML邮件工具 采用 freemarker模板引擎
1.常用方式对比
Java发送邮件有很多的实现方式
-
第一种:Java 原生发邮件
mail.jar
和activation.jar
<!-- 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>
原生的java可以发送普通文本和HTML邮件,同时也可以发送带附件的邮件,但是缺点也很明显,配置非常繁琐,不同的邮件需要不同的实现类去完成,不适合项目中使用。
-
第二种:使用框架提供的去实现,在SpringBoot中有实现这个功能的组件
spring-boot-starter-mail
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
这种实现起来特别方便,仅仅只要在SpringBoot项目中引入组件,在配置文件中配置好各种参数,就可以实现依赖注入,调用接口完成发送邮件,同时支持普通文本、HTML邮件、以及携带附件的邮件。同时缺点就是和框架集成太高了,如果项目中没有使用SpringBoot就不是那么好用了。
-
第三种:采用Apache提供的邮件工具
commons-email
,项目中已经封装好了一些常用的发邮件的接口供开发者使用,并且配置起来也比较简单,和其他技术耦合低是比较好的解决问题的方案。<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-email</artifactId> <version>1.5</version> </dependency>
2.项目中使用
项目使用的jar包,采用maven工程。
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-email</artifactId> <version>1.5</version> </dependency>
第三方jar包引入时下载:https://mvnrepository.com/artifact/org.apache.commons/commons-email
(1)创建配置文件email.properties
- 建议将配置文件统一放置在
resources
文件夹中
# 邮件服务器的地址
host=smtp.exmail.qq.com
# 邮件服务器的端口(百度上有,或者邮件提供商开发文档有)
port=456
# 发件人邮箱
username=
# 密码或授权码
password=
# 发件人名称,如果不提供会使用发件人邮件作为发件人
formName=
(2)发邮件的核心代码
package com.zhongcode.demo.email;
import org.apache.commons.mail.*;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
/**
* 邮件发送实例
*/
public class SendEmail {
/**
* 邮件服务器 host
*/
private String host;
/**
* 邮件服务器端口 port
*/
private int port;
/**
* 用户名
*/
private String username;
/**
* 密码(授权码)
*/
private String password;
/**
* 发件人名称
*/
private String formName;
/**
* 是否开启debug
*/
private boolean debug;
public SendEmail() {
}
public SendEmail(Properties pro) {
this.host = pro.getProperty("host");
this.port = Integer.parseInt(pro.getProperty("port", "0"));
this.username = pro.getProperty("username");
this.password = pro.getProperty("password");
this.formName = pro.getProperty("formName");
}
public SendEmail(String host, int port, String username, String password, String formName, boolean debug) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.formName = formName;
this.debug = debug;
}
public SendEmail(String host, int port, String username, String password, String formName) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.formName = formName;
}
public SendEmail(String host, int port, String username, String password) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFormName() {
return formName;
}
public void setFormName(String formName) {
this.formName = formName;
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
/**
* 发邮件
*
* @param to 收件件人
* @param subject 主题
* @param msg 消息
* @throws EmailException 邮件异常
*/
public synchronized void sendEmail(String to, String subject, String msg) throws EmailException {
sendEmail(Collections.singletonList(to), subject, msg, null, null);
}
/**
* 发邮件
*
* @param toEmails 发送列表
* @param subject 主题
* @param msg 内容支持html
* @param attaches 附件
* @param fromName 发送名称
* @throws EmailException 邮件异常
*/
public synchronized void sendEmail(List<String> toEmails, String subject, String msg, List<String> attaches, String fromName) throws EmailException {
// 创建邮件对象
MultiPartEmail email;
// 当附件不为空时,使用MultiPartEmail添加附件
if (attaches != null) {
email = new MultiPartEmail();
for (String att : attaches) {
EmailAttachment attachment = new EmailAttachment();
attachment.setPath(att);
// 截取文件名
attachment.setName(att.substring(att.lastIndexOf("/") + 1));
email.attach(attachment);
}
// 当使用MultiPartEmail时渲染html要使用Part进行添加
email.addPart(msg, "text/html; charset=UTF-8");
} else {
// 默认使用HtmlEmail创建
email = new HtmlEmail();
email.setMsg(msg);
}
// 设置主机
email.setHostName(host);
// 设置端口
email.setSmtpPort(port);
email.setDebug(debug);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setCharset("UTF-8");
email.setSSLOnConnect(true);
email.setFrom(username, fromName == null ? (this.formName == null ? username : this.formName) : fromName);
email.setSubject(subject);
for (String to : toEmails) {
email.addTo(to);
}
email.send();
}
}
(3)程序发邮件测试
public static void main(String[] args) throws EmailException, IOException, TemplateException {
// 加载配置文件
InputStream is = Main.class.getClassLoader().getResourceAsStream("email.properties");
Properties pro = new Properties();
pro.load(is);
// 创建邮件
SendEmail sendEmail = new SendEmail(pro);
sendEmail.sendEmail("收件人", "test", "测试邮件");
}
3.发送HTML模板邮件
当我们想发送模板HTML时,需要发送HTML格式的代码,主要是纯文本的邮件并不好看,而且项目中经常使用的是好看的模板,比如系统用户注册时需要发送验证码,很多情况下都要发邮件。
这里我们采用的freemarker
模板引擎来渲染我们的HTML模板,下面是以发送邮箱验证码为例。
(1)引入freemarker模板引擎
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
(2)创建HTML模板
文件名:code.ftl
<meta charset="utf-8"><table width="100%"><tr><td style="width: 100%;"><center><table class="content-wrap" style="margin: 0px auto; width: 600px;"><tr><td style="margin: 0px auto; overflow: hidden; padding: 0px; border: 0px dotted rgb(238, 238, 238);"><!----><div class="full" tindex="1" style="margin: 0px auto; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td class="fullTd" style="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-color: rgb(170, 0, 170); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="vertical-align: top;"><tr><td align="left" style="font-size: 0px; padding: 20px;"><div class="text" style="font-family: 微软雅黑, "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: center; line-height: 1.6; color: rgb(255, 255, 255); font-size: 18px; font-weight: normal;"><div><p style="text-size-adjust: none; word-break: break-word; line-height: 1.6; font-size: 18px; margin: 0px;"><strong>系统提示</strong></p></div></div></td></tr></table></td></tr></tbody></table></div><div class="full" tindex="2" style="margin: 0px auto; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td class="fullTd" style="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="vertical-align: top;"><tr><td align="left" style="font-size: 0px; padding: 20px 20px 5px;"><div class="text" style="font-family: 微软雅黑, "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: left; line-height: 20px; color: rgb(102, 102, 102); font-size: 14px; font-weight: normal;"><div><p style="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 14px; margin: 0px;">您的验证码为:</p></div></div></td></tr></table></td></tr></tbody></table></div><div class="full" tindex="3" style="margin: 0px auto; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td class="fullTd" style="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="vertical-align: top;"><tr><td align="left" style="font-size: 0px; padding: 20px;"><div class="text" style="font-family: 微软雅黑, "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: center; line-height: 20px; color: rgb(0, 0, 0); font-size: 24px; font-weight: normal;"><div><p style="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 24px; margin: 0px;"><strong>${code}</strong></p></div></div></td></tr></table></td></tr></tbody></table></div><div class="full" tindex="4" style="margin: 0px auto; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td class="fullTd" style="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="vertical-align: top;"><tr><td align="left" style="font-size: 0px; padding: 8px 20px 20px;"><div class="text" style="font-family: 微软雅黑, "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: left; line-height: 20px; color: rgb(102, 102, 102); font-size: 12px; font-weight: normal;"><div><p style="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 12px; margin: 0px;"><span style="color: #333333;">验证码10分钟内有效。</span></p></div></div></td></tr></table></td></tr></tbody></table></div><div class="full" tindex="5" style="margin: 0px auto; line-height: 0px; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td align="center" class="fullTd" style="direction: ltr; font-size: 0px; padding: 10px 20px; text-align: center; vertical-align: top; word-break: break-word; width: 600px; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table align="center" border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse; border-spacing: 0px;"><tbody><tr><td style="width: 600px; border-top: 1px solid rgb(204, 204, 204);"></td></tr></tbody></table></td></tr></tbody></table></div><div class="full" tindex="6" style="margin: 0px auto; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td class="fullTd" style="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="vertical-align: top;"><tr><td align="left" style="font-size: 0px; padding: 10px 20px 0px;"><div class="text" style="font-family: 微软雅黑, "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: left; line-height: 20px; color: rgb(170, 170, 170); font-size: 12px; font-weight: normal;"><div><p style="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 12px; margin: 0px;">此为系统邮件请勿回复</p></div></div></td></tr></table></td></tr></tbody></table></div><div class="full" tindex="7" style="margin: 0px auto; max-width: 600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" class="fullTable" style="width: 600px;"><tbody><tr><td class="fullTd" style="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="vertical-align: top;"><tr><td align="left" style="font-size: 0px; padding: 20px;"><div class="text" style="font-family: 微软雅黑, "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: center; line-height: 20px; color: rgb(170, 170, 170); font-size: 12px; font-weight: normal;"><div><p style="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 12px; margin: 0px;">Copyright © zhongcode 2020 All Right Reserved</p></div></div></td></tr></table></td></tr></tbody></table></div></td></tr></table></center></td></tr></table>
(3)代码测试
public class Main {
public static void main(String[] args) throws EmailException, IOException, TemplateException {
//1.创建配置类
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
//2.设置模板所在的目录
configuration.setDirectoryForTemplateLoading(new File("E:\\tmp\\ftl"));
//3.设置字符集
configuration.setDefaultEncoding("utf-8");
//4.加载模板
//模板名自动在模板所在目录寻找
Template template = configuration.getTemplate("code.ftl");
Map<String, String> data = new HashMap<>();
data.put("code", "999999");
StringWriter out = new StringWriter();
template.process(data, out);
// 加载配置文件
InputStream is = Main.class.getClassLoader().getResourceAsStream("email.properties");
Properties pro = new Properties();
pro.load(is);
// 创建邮件
SendEmail sendEmail = new SendEmail(pro);
sendEmail.sendEmail("收件人", "验证码", out.toString());
}
}
就这样,一封好看的HTML邮件就完成了,任何问题都可以私信我哦