发送邮件要提前准备好要发送的数据类容,还要提前将发件箱协议名,身份验证信息,服务主机名准备好以outlook邮箱为例,如图所示:
在SMTP中可以看见相关设置。
接下来直接上代码:
//这个Map存放Html模板中的类容
Map<String, Object> emap = new HashMap();
emap.put("top0", "你好");
emap.put("top1", "11111");
emap.put("top2", "22222");
//插入Html页面的图片,imageBase64List是多张图片转Base64的字符串
emap.put("Base64Urllist", imageBase64List);
String sendHtml = null;
try {
//模板页面整合,parseTemplate在另一个类中写,email/agree目录顺序
sendHtml = ThymeleafTemplateUtil.parseTemplate("email/agree", emap);
} catch (Exception exception) {
exception.printStackTrace();
}
String content = sendHtml;
Map<String, String> map = new HashMap<String, String>();
//邮件服务器主机名(smtp服务器地址) smtp.office365.com
map.put("smtp", Constants.EMAIL_SMTP);
//邮件传输协议 smtp
map.put("protocol", EMAIL_PROTOCOL);
//登录邮箱的用户名
map.put("username", USERNAME);
//登录邮箱的密码
map.put("password", PASSWORD);
//发送人的帐号
map.put("from", FROM);
//接收人的帐号,多个以","号隔开
//收件人
map.put("to", email);
//设置邮件主题
map.put("subject","主题名称");
//邮件内容
map.put("body", content);
//端口 587
map.put("port", PROT);
//内嵌了多少张图片,如果没有,则new一个不带值的Map
Map<String, String> image = new HashMap<String, String>();
//例image.put("a00000001","E:\\usr\\local\\posweb\\store_plat_file\\IN2041683.jpg");
//附件的绝对路径,不发附件则new一个不带值的List
List<String> list = new ArrayList<String>();
//例:list.add("D:/ccc.sql");
//创建实例
SendMail sm = new SendMail(map, list, image);
//执行发送
sm.send();
整合java中数据到Html中:
public class ThymeleafTemplateUtil {
//项目中必须有resources目录下面有templates目录,Html页面写在templates下
public static final String TEMPLATES_PATH = "templates/";
public static final String TEMPLATES_SUFFIX = ".html";
TemplateEngine templateEngine = new TemplateEngine();
private static ThymeleafTemplateUtil util = new ThymeleafTemplateUtil();
public ThymeleafTemplateUtil() {
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
// 构造模板引擎
resolver.setPrefix(TEMPLATES_PATH);// 模板所在目录,相对于当前classloader的classpath。
resolver.setSuffix(TEMPLATES_SUFFIX);// 模板文件后缀
templateEngine.setTemplateResolver(resolver);
}
public String parseThymeleafTemplate(String templateName, Map<String, Object> contextMap) {
Context context = new Context();
if (contextMap != null) {
// 构造上下文(Model)
contextMap.forEach((key, value) -> {
context.setVariable(key, value);
});
}
// 渲染模板
String str = templateEngine.process(templateName, context);
return str;
}
/**
* 提供外部的静态方法 根据模板名称和上下文Map生成模板文件内容
*
* @param templateName
* 模板名称 templates/ 下的,无需后缀
* @param contextMap
* 上下文参数
* @return
*/
public static String parseTemplate(String templateName, Map<String, Object> contextMap) {
return util.parseThymeleafTemplate(templateName, contextMap);
}
}
Html模板目录如下:
HTML模这么写:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Email</title>
<style>
table tr {
height: 3.5rem;
border: 1px solid #ccc;
}
table {
width: 50%;
border-collapse: collapse;
border: 1px solid #ccc;
text-align: center;
}
table tr:nth-child(2n+1) {
background-color: rgb(248, 235, 218);
}
img {
margin-top: 30px;
margin-right: 30px;
max-height: 50vh;
max-width: 40vw;
}
.name {
font-weight: 600;
text-align: right;
}
</style>
</head>
<body>
<!--文本类容-->
<b th:text="${top0}"><br></b><br>
<b th:text="${top1}"><br></b><br>
<table>
<thead>
<th colspan="10">
<h2 th:text="${top2}"></h2>
</th>
</thead>
<tbody>
<!--表格类容-->
<tr>
<td class="name">Store:</td>
<!--可根据需求拼接-->
<td th:text="${prodDefect.storeId}+'-'+${prodDefect.storeName}"></td>
</tr>
<tr>
<td class="name">Name:</td>
<td th:text="${prodDefect.prodName}"></td>
</tr>
<tr>
<td class="name">Item Code:</td>
<td th:text="${prodDefect.prodCode}"></td>
</tr>
<!--如果为1不显示-->
<tr th:if="${prodDefect.barcode}!='1'">
<td class="name">Barcode:</td>
<td th:text="${prodDefect.barcode}"></td>
</tr>
<tr>
<td class="name">PoNumber:</td>
<td th:text="${prodDefect.poNumber}"></td>
</tr>
</tbody>
</table>
<!--图片转Base64循环装填-->
<tr th:each="stat : ${Base64Urllist}">
<img th:src= "'data:image/jpg;base64,'+${stat}"alt="" width="50%"/>  
</tr>
</body>
</html>
public class SendMail {
private String smtp=""; //邮件服务器主机名
private String protocol=""; //邮件传输协议
private String username=""; //登录用户名
private String password=""; //登录密码
private String from=""; //发件人地址
private String to=""; //收件人地址
private String subject=""; //邮件主题
private String body=""; //邮件内容
private String port=""; //端口
//一个有规则的map,用作嵌入图片
Map<String,String> map;
//存放附件
List<String> list;
public SendMail(Map<String,String> map,List<String> filelist,Map<String,String> image){
this.smtp=map.get("smtp");
this.protocol=map.get("protocol");
this.username=map.get("username");
this.password=map.get("password");
this.from=map.get("from");
this.to=map.get("to");
this.subject=map.get("subject");
this.body=map.get("body");
this.port=map.get("port");
this.list=filelist;
this.map=image;
}
public void send()throws Exception{
Properties pros=new Properties();
// 发送服务器需要身份验证
pros.setProperty("mail.smtp.auth", "true");
// 设置邮件服务器主机名
pros.setProperty("mail.host",Constants.EMAIL_SMTP);
// 发送邮件协议名称
pros.setProperty("mail.transport.protocol", this.protocol);
pros.setProperty("mail.smtp.port", this.port);
//outlook邮箱要有,其他邮箱的不需要mail.smtp.starttls.enable设置
pros.put("mail.smtp.starttls.enable", "true");
// 开启debug调试
pros.setProperty("mail.debug", "true");
MySendMailAuthenticator ma=new MySendMailAuthenticator(this.username,this.password);
Session session=Session.getInstance(pros,ma);
//获取Session对象
session.setDebug(true);
MimeMessage msg=createMessage(session);
Transport ts=session.getTransport();
ts.connect();
ts.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));
ts.close();
}
public MimeMessage createMessage(Session session)throws Exception{
MimeMessage message=new MimeMessage(session);
message.setFrom(new InternetAddress(this.from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject(this.subject);
MimeMultipart allMultipart=new MimeMultipart();
//创建代表邮件正文和附件的各个MimeBodyPart对象
MimeBodyPart contentpart=createContent(this.body);
allMultipart.addBodyPart(contentpart);
//创建用于组合邮件正文和附件的MimeMultipart对象
for(int i=0;i<list.size();i++){
allMultipart.addBodyPart(createAttachment(list.get(i)));
}
//设置整个邮件内容为最终组合出的MimeMultipart对象
message.setContent(allMultipart);
message.saveChanges();
return message;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public MimeBodyPart createContent(String body)throws Exception{
//创建代表组合Mime消息的MimeMultipart对象,将该MimeMultipart对象保存到MimeBodyPart对象
MimeBodyPart contentPart=new MimeBodyPart();
MimeMultipart contentMultipart=new MimeMultipart("related");
//创建用于保存HTML正文的MimeBodyPart对象,并将它保存到MimeMultipart中
MimeBodyPart htmlbodypart=new MimeBodyPart();
htmlbodypart.setContent(this.body,"text/html;charset=UTF-8");
contentMultipart.addBodyPart(htmlbodypart);
if(map!=null && map.size()>0) {
Set<Entry<String, String>> set=map.entrySet();
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
Entry<String, String> entry = (Entry<String, String>) iterator.next();
//创建用于保存图片的MimeBodyPart对象,并将它保存到MimeMultipart中
MimeBodyPart gifBodyPart=new MimeBodyPart();
FileDataSource fds=new FileDataSource(entry.getValue());//图片所在的目录的绝对路径
gifBodyPart.setDataHandler(new DataHandler(fds));
gifBodyPart.setContentID(entry.getKey()); //cid的值
contentMultipart.addBodyPart(gifBodyPart);
}
}
//将MimeMultipart对象保存到MimeBodyPart对象
contentPart.setContent(contentMultipart);
return contentPart;
}
public MimeBodyPart createAttachment(String filename)throws Exception {
//创建保存附件的MimeBodyPart对象,并加入附件内容和相应的信息
MimeBodyPart attachPart=new MimeBodyPart();
FileDataSource fsd=new FileDataSource(filename);
attachPart.setDataHandler(new DataHandler(fsd));
attachPart.setFileName(fsd.getName());
return attachPart;
}
}
//向邮件服务器提交认证信息
class MySendMailAuthenticator extends Authenticator{
String username="";
String password="";
public MySendMailAuthenticator(String user,String pass){
this.username=user;
this.password=pass;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username,password);
}
}
如上是发送主流程。
图片转Base64
//imgList 多张图片地址路径
private static List getImageBase64Str(List<String> imgList) throws IOException {
List Base64Urllist = new ArrayList();
for (String imgPath : imgList) {
InputStream inputStream = null;
try {
Base64.Encoder encoder = Base64.getEncoder();
String requestMethod = "GET";
String outputStr = null;
inputStream = HttpUtils.httpRequest2(imgPath, requestMethod, outputStr);
byte[] bytes = read(inputStream);
String base64Str = encoder.encodeToString(bytes);
Base64Urllist.add(base64Str);
} catch (Exception e) {
e.printStackTrace();
} finally {
inputStream.close();
}
}
return Base64Urllist;
}
下面这个方法处理图片转Base64后显示不全的问题
public static byte[] read(InputStream inputStream) throws IOException {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int num = inputStream.read(buffer);
while (num != -1) {
baos.write(buffer, 0, num);
num = inputStream.read(buffer);
}
baos.flush();
return baos.toByteArray();
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
这样就可以发送模板邮件了。
本代码稍加修改可发送文本邮件,附件邮件。