发送邮件应该是网站的必备功能之一,什么注册验证,忘记密码或者是给用户发送营销信息。最早期的时候我们会使用JavaMail相关api来写发送邮件的相关代码,后来spring退出了JavaMailSender更加简化了邮件发送的过程,在之后springboot对此进行了封装就有了现在的spring-boot-starter-mail,本章文章的介绍主要来自于此包。

首先呢肯定是要加入依赖

   <!-- springboot集成的email --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>

然后呢配置下yml

spring:mail:host: smtp.163.comusername: 13103779727@163.compassword: nibuzhidaomimaproperties:mail:smtp:auth: truetimeout: 25000

写个最简单的服务

package com.mail;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;@Component
public class MailService {@AutowiredJavaMailSender jms;public void send() {//建立邮件消息SimpleMailMessage mainMessage = new SimpleMailMessage();//发送者mainMessage.setFrom("13103779727@163.com");//接收者mainMessage.setTo("????@qq.com");//发送的标题mainMessage.setSubject("嗨喽");//发送的内容mainMessage.setText("hello world");jms.send(mainMessage);}
}

这样就实现了发送邮件,其实发模版html的也能实现,但是总感觉不那么大气代码量也死多死多,干脆封装下吧。


首先呢,创建一个实体

package com.maoxs.email.entity;import lombok.Data;import java.io.Serializable;
import java.util.Map;/*** @Description: 邮件实体** @author fulin* @Project*/
@Data
public class Mail implements Serializable {private static final long serialVersionUID = 1L;/** 邮件标题 */private String title;/** 邮件内容 */private String content;/** 内容格式(默认html) */private String contentType;/** 接收邮件地址 */private String to;/*************模板发送****************//** 模板名称 */private String templateName;/** 模板变量替换 */private Map<String, Object> maps;
}

创建类型枚举类

package com.maoxs.email.enums;/*** @Description: 邮件内容的类型** @author fulin* @Project*/
public enum MailContentTypeEnum {//text格式TEXT("text"),//html格式HTML("html"),//模板TEMPLATE("template");private String value;MailContentTypeEnum(String value) {this.value = value;}public String value() {return value;}
}

创建一个基于spring的工厂类

package com.maoxs.email.factory;import com.maoxs.email.enums.MailContentTypeEnum;import java.util.HashMap;
import java.util.Map;/*** @Description: 邮件发送bean工厂类** @author fulin* @Project*/
public class MailFactory {private MailFactory() {}private static final class InnerMailFactory {private static final MailFactory MAIL_FACTORY = new MailFactory();}private static Map<String, String> maps = new HashMap<>();static {maps.put(MailContentTypeEnum.TEXT.value(), getStrategyClassName("simple"));maps.put(MailContentTypeEnum.HTML.value(), getStrategyClassName("html"));maps.put(MailContentTypeEnum.TEMPLATE.value(), getStrategyClassName("template"));}public static final MailFactory getInstance() {return InnerMailFactory.MAIL_FACTORY;}public String get(String type) {return maps.get(type);}/*** 获取策略类名** @param classNamePrefix:类名前缀* @return*/private static String getStrategyClassName(String classNamePrefix) {return classNamePrefix + "MailStrategy";}}

创建 邮件发送策略类的接口

package com.maoxs.email.strategy;import com.maoxs.email.entity.Mail;/*** @Description: 发送邮件策略接口** @author fulin* @Project*/
public interface MailStrategy {/*** 发送邮件** @param from:谁发送* @param mail:邮件信息*/void sendMail(String from, Mail mail);}

然后是三个基础实现类

package com.maoxs.email.strategy.impl;import com.maoxs.email.entity.Mail;
import com.maoxs.email.strategy.MailStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;/*** @Description: HTML格式发送邮件** @author fulin* @Project*/
@Component
public class HtmlMailStrategy implements MailStrategy {private static final Logger LOG = LogManager.getLogger("bizLog");@Autowiredprivate JavaMailSender javaMailSender;@Overridepublic void sendMail(String from, Mail mail) {MimeMessage message = javaMailSender.createMimeMessage();try {//true表示需要创建一个multipart messageMimeMessageHelper helper = new MimeMessageHelper(message, true);helper.setFrom(from);helper.setTo(mail.getTo());helper.setSubject(mail.getTitle());helper.setText(mail.getContent(), true);javaMailSender.send(message);LOG.info("html邮件已经发送{}。", mail.getTo());} catch (MessagingException e) {LOG.error("发送html邮件时发生异常!", e);}}
}
package com.maoxs.email.strategy.impl;import com.maoxs.email.entity.Mail;
import com.maoxs.email.strategy.MailStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;/*** @Description: 简单文本发送邮件** @author fulin* @Project*/
@Component
public class SimpleMailStrategy implements MailStrategy {private static final Logger LOG = LogManager.getLogger("bizLog");@Autowiredprivate JavaMailSender javaMailSender;@Overridepublic void sendMail(String from, Mail mail) {SimpleMailMessage message = new SimpleMailMessage();try {message.setFrom(from);message.setTo(mail.getTo());message.setSubject(mail.getTitle());message.setText(mail.getContent());javaMailSender.send(message);LOG.info("纯文本的邮件已经发送给【{}】。", mail.getTo());} catch (Exception e) {LOG.error("纯文本邮件发送时发生异常!", e);}}}
package com.maoxs.email.strategy.impl;import com.maoxs.email.entity.Mail;
import com.maoxs.email.strategy.MailStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Locale;
import java.util.Map;/*** @Description: 自定义模板格式发送邮件** @author fulin* @Project*/
@Component
public class TemplateMailStrategy implements MailStrategy {private static final Logger LOG = LogManager.getLogger("bizLog");@Autowiredprivate JavaMailSender javaMailSender;@Autowiredprivate TemplateEngine templateEngine;@Overridepublic void sendMail(String from, Mail mail) {final Context ctx = new Context(new Locale(""));if (null != mail.getMaps() && mail.getMaps().size() != 0) {for (Map.Entry<String, Object> entry : mail.getMaps().entrySet()) {ctx.setVariable(entry.getKey(), entry.getValue());}}final String htmlContent = templateEngine.process(mail.getTemplateName(), ctx);final MimeMessage mimeMessage = javaMailSender.createMimeMessage();final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8");try {message.setFrom(from);message.setTo(mail.getTo());message.setSubject(mail.getTitle());message.setText(htmlContent, true);javaMailSender.send(mimeMessage);LOG.info("模板邮件已经发送{}。", mail.getTo());} catch (MessagingException e) {e.printStackTrace();LOG.error("发送模板邮件【{}】时发生异常!", mail.getTemplateName());}}
}

然后就是邮件的发送类

package com.maoxs.email.biz;import com.maoxs.email.entity.Mail;
import com.maoxs.email.enums.MailContentTypeEnum;
import com.maoxs.email.factory.MailFactory;
import com.maoxs.email.strategy.MailStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Map;/*** @Description: 邮件发送类** @author fulin* @Project**/
@Component
public class MailBiz {@Autowiredprivate Map<String, MailStrategy> mailStrategy;@Value("${spring.mail.username}")private String from;/** 邮件实体 */private Mail mail = new Mail();/*** 设置邮件标题** @param title:邮件标题* @return*/public MailBiz title(String title) {mail.setTitle(title);return this;}/*** 设置邮件内容** @param content:内容* @return*/public MailBiz content(String content) {mail.setContent(content);return this;}/*** 设置邮件格式** @param typeEnum:邮件格式* @return*/public MailBiz contentType(MailContentTypeEnum typeEnum) {mail.setContentType(typeEnum.value());return this;}/*** 设置请求目标邮件地址** @param to:请求目标邮件地址* @return*/public MailBiz to(String to) {mail.setTo(to);return this;}/*** 设置模板名称** @param templateName* @return*/public MailBiz templateName(String templateName) {mail.setTemplateName(templateName);return this;}/*** 模板发送的变量** @param maps:maps* @return*/public MailBiz maps(Map<String, Object> maps) {mail.setMaps(maps);return this;}/*** 执行发送邮件*/public void send() {String key = MailFactory.getInstance().get(mail.getContentType());this.mailStrategy.get(key).sendMail(from, mail);}
}

然后呢就封装完毕了 在发送类里使用了对象级联的方式,使其调用更方便如果使用的是freemarker

这边我也提供了发送方式,建议大家自己扩展。

package com.maoxs.email.strategy.impl;import com.maoxs.email.entity.Mail;
import com.maoxs.email.strategy.MailStrategy;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;@Component
public class FreemarkerMailStrategy implements MailStrategy {private static final Logger LOG = LogManager.getLogger("bizLog");@Autowiredprivate Configuration configuration;@Autowiredprivate JavaMailSender javaMailSender;@Overridepublic void sendMail(String from, Mail mail) {try {final Template t = configuration.getTemplate(mail.getTemplateName());final String htmlContent = FreeMarkerTemplateUtils.processTemplateIntoString(t, mail.getMaps());final MimeMessage mimeMessage = javaMailSender.createMimeMessage();final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8");message.setFrom(from);message.setTo(mail.getTo());message.setSubject(mail.getTitle());message.setText(htmlContent, true);javaMailSender.send(mimeMessage);LOG.info("FreeMarker模板邮件已经发送{}。", mail.getTo());} catch (IOException e) {e.printStackTrace();} catch (TemplateException e) {e.printStackTrace();} catch (MessagingException e) {e.printStackTrace();LOG.error("FreeMarker发送模板邮件【{}】时发生异常!", mail.getTemplateName());}}
}

具体怎么使用呢 来看下测试类

package com;import com.maoxs.email.biz.MailBiz;
import com.maoxs.email.enums.MailContentTypeEnum;
import com.mail.MailService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.Date;
import java.util.HashMap;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest
public class TestApplicationTests {@Autowiredprivate MailBiz mailBiz;@Testpublic void sendMail() {mailBiz.contentType(MailContentTypeEnum.HTML).title("测试").to("??????@qq.com").content("<h1>测试content</h1>").send();}@Testpublic void sendMail2() {Map<String, Object> params = new HashMap<>();params.put("username", "昴先生");params.put("methodName", "???");params.put("errorMessage", "出错了唉");params.put("occurredTime", new Date());mailBiz.contentType(MailContentTypeEnum.TEMPLATE).title("测试").to("??????@qq.com").content("测试content").templateName("Test").maps(params).send();}
}

然后呢这是邮件 thy的 由于上面提供了freemarker的发送方式,建议大家自己扩展

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><title>Hello World</title><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css"th:href="@{https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css}"/>
</head>
<style type="text/css">.full-screen {height: fit-content;width: fit-content;}.fixed-page {overflow-x: scroll;overflow-y: scroll;}.container {width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto}.jumbotron {padding: 2rem 1rem;margin-bottom: 2rem;background-color: #e9ecef;border-radius: .3rem}.jumbotron-fluid {padding-right: 0;padding-left: 0;border-radius: 0}</style>
<body class="fixed-page">
<table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#ffffff"style="font-family:'Microsoft YaHei';"><div class="jumbotron jumbotron-fluid full-screen"><div class="container  full-screen"><img class="c-img c-img6" src="https://ss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2222976400,3502441702&amp;fm=58&amp;bpow=440&amp;bpoh=440"><img class="currentImg" id="currentImg" onload="alog &amp;&amp; alog('speed.set', 'c_firstPageComplete', +new Date); alog.fire &amp;&amp; alog.fire('mark');" src="https://timgsa.baidu.com/timg?image&amp;quality=80&amp;size=b9999_10000&amp;sec=1532597177454&amp;di=aec784f189c38b207ee88ea296f2457f&amp;imgtype=0&amp;src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fblog%2F201308%2F13%2F20130813185613_T4nxf.thumb.700_0.jpeg" data-ispreload="0" width="485.91370558376" height="547" style="top: 0px; left: 382px; width: 318.02px; height: 358px; cursor: pointer;" log-rightclick="p=5.102" title="点击查看源网页"><img class="currentImg" id="currentImg" onload="alog &amp;&amp; alog('speed.set', 'c_firstPageComplete', +new Date); alog.fire &amp;&amp; alog.fire('mark');" src="https://timgsa.baidu.com/timg?image&amp;quality=80&amp;size=b9999_10000&amp;sec=1532597216973&amp;di=5a1b48da42304a2dd63ec9697084bb11&amp;imgtype=0&amp;src=http%3A%2F%2Fi2.hdslb.com%2Fbfs%2Farchive%2Fb55830fe8fb1d3221b3494442b0b5c1902c6ef3a.jpg" width="288.71287128713" height="162" style="top: 48px; left: 397px; width: 288.713px; height: 162px; cursor: pointer;" log-rightclick="p=5.102" title="点击查看源网页"><img class="currentImg" id="currentImg" onload="alog &amp;&amp; alog('speed.set', 'c_firstPageComplete', +new Date); alog.fire &amp;&amp; alog.fire('mark');" src="https://timgsa.baidu.com/timg?image&amp;quality=80&amp;size=b9999_10000&amp;sec=1532597216973&amp;di=5d72892a3193c4462b45d87f6a5370b2&amp;imgtype=0&amp;src=http%3A%2F%2Fi2.hdslb.com%2Fbfs%2Fface%2Faff582421bd0e8331255cb92622328d19616e2c0.jpg" width="288.71287128713" height="162" style="top: 29px; left: 392px; width: 300px; height: 300px; cursor: pointer; display: block;" log-rightclick="p=5.102" title="点击查看源网页"><h3>Hi,<span th:text="${username}">Developer</span></h3><p>There is an exception occurred in method<code style="color: #d57e13;"><span th:text="${methodName}">methodName</span></code>,the error message is :</p><div><pre><code style="font-family: 'Source Code Pro';"><span th:text="${errorMessage}">Error Message</span></code></pre></div><span th:text="${occurredTime}">occurredTime</span></div></div>
</table>
</body>
</html>

然后呢我们跑去邮箱里去看看

okokok,完事,这边还有一个多邮件轮训发送没有扩展,有时间在扩展

本博文是基于springboot2.x 如果有什么不对的请在下方留言。

一起来学SpringBoot(十二)发送邮件相关推荐

  1. 从头开始学Tableau-第十二章(实战3 地图实践)

    从头开始学Tableau-第十二章(实战3 地图实践) 第一章 第二章 第三章 第四章 第五章 第六章 第七章 第八章 第九章 第十章 第十章 数据源 这个实践主要是用地图来呈现数据,我们所用的是保险 ...

  2. 跟我学springboot(二十五)springboot-过滤器之拦截不需要走过滤器的链接使用方法

    1.创建项目 springboot怎么创建不多说了,前面博客已经有讲解,下面是我们创建好的项目目录. 2.编写代码 过滤器可以指定我们排除的参数exclusions,我们把需要隔离的url统一封装在这 ...

  3. SpringBoot(十二):springboot如何测试打包部署

    原文出处: 纯洁的微笑 有很多网友会时不时的问我,spring boot项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下spring boot 如何开发.调试.打包到最后的投 ...

  4. springboot(十二)-分布式锁(redis)

    什么是分布式锁? 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁.进程锁. 线程锁:主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同一 ...

  5. SpringBoot(十二)_springboot整合PageHelper

    我之所以会发现这个PageHelper这个东东 是因为公司在使用 ,刚开始我也没太注意这个插件,感觉不就是个分页插件吗?也就那样,直到一天,我在网上找了个代码生成器,用来构建代码,因为它是针对mysq ...

  6. 【杂学第十二篇】oracledb_exporter监听oracle19c数据库出现libclntsh、ORA-12162、ORA-00942异常解决

    背景 最近帮公司安装监控系统,就是prometheus+grafana+各种exporter 然后启动oracledb_exporter的时候,出现了许多问题 最后一一都解决了,记录下,希望帮助下一个 ...

  7. Java程序猿必学第二十二篇—— 网络编程

    //1.File相关 //1.1 FileFilter //FileFilter:文件过滤器 //listFiles方法用于将当前层的文件和目录的File对象放入数组 //FileFilter则是在放 ...

  8. 教妹学Java(二十二):来吧,一文彻底搞懂Java命名约定

    你好呀,我是沉默王二,是<Web 全栈开发进阶之路>的作者,CSDN 博客之星.<教妹学 Java>是一套非常有趣的付费专栏,除了继续保持幽默风趣的行风风格,我还力求把每一个知 ...

  9. Spring boot(十二):Spring boot 如何测试、打包、部署

    博文引用:springboot(十二):springboot如何测试打包部署 开发阶段 单元测试 Spring boot对单元测试的支持已经很完善了. 1 在pom包中添加Spring-boot-st ...

  10. 教妹学Java(十九):continue 关键字详解

    你好呀,我是沉默王二,是<Web 全栈开发进阶之路>的作者,CSDN 2019 年度的博客之星.<教妹学 Java>是一套非常有趣的付费专栏,除了继续保持幽默风趣的行风风格,我 ...

最新文章

  1. day20 文件上传下载
  2. NSInputStream和NSMutableURLRequest-实现保存文件到服务器
  3. 美国客户商城系统的校验JS脚本
  4. 次小生成树(Prim + Kruaskal)
  5. HOJ 1991 Happy 2005 HOJ 2635 Weights 快速幂
  6. leetcode1103. 分糖果 II 该模拟就模拟,别老想着优化
  7. LSP(分层服务提供程序)
  8. c++ 获取文件夹创建时间_手把手教学免费创建个人网站
  9. 你不知道你不懂javascript
  10. SQL 审核:基于PG数据库插件hook的SQL规范审核工具
  11. 百度Apolloscapes,亚马逊评论,最强数据集50个最佳机器学习公共数据
  12. 构建自己的地理信息空间数据库及与客户端简单交互(内含彩蛋)
  13. 视频联网云平台EasyCVR集成海康EHome协议系列——Ehome协议调用流程介绍
  14. 【rfc5506】RTCP mode
  15. Session的活化与钝化
  16. 列车停站方案_基于节点分级的高速铁路列车停站方案设计策略
  17. Bootstrap第一章初识
  18. IOS界面push跳转后navigationController不显示
  19. bind dlz mysql rpm_BIND+DLZ+MYSQL | 学步园
  20. 【高光谱、多光谱和全色图像融合】

热门文章

  1. 安卓手机主题软件_用AI软件制作手机主题图标
  2. oracle 应收未传总账,oracleEBS应收系统中的未标识收款是什么?
  3. “守住养老钱·幸福享晚年”
  4. 千万不要把comsol livelink matlab客户端和其对应的comsol文件同时打开
  5. 什么是互操作协议LayerZero?
  6. mysql 李天生_超级菜鸟怎么学习数据分析?
  7. 科技行者公布人工智能2017年度评选: 10大AI事件、50家AI概念股、61位AI人物
  8. svm训练特征提取——图像特征提取三大法宝:HOG特征,LBP特征,Haar特征
  9. Tool-360关闭健康助手,关闭360的弹窗(自动倒计时出现锁屏页面)
  10. Adobe 观察 |最低工资标准来了,学会这几招,让加薪更简单