Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringBoot开发案例之整合mail发送服务

SpringBoot开发案例之整合mail发送服务

原创
作者头像
小柒2012
修改于 2018-03-30 10:59:28
修改于 2018-03-30 10:59:28
1.7K0
举报
文章被收录于专栏:IT笔记IT笔记
spring-boot-mail.jpg
spring-boot-mail.jpg

记得上个月做过这样一篇笔记,微服务架构实践之邮件通知系统改造。

当时用的是开源的第三方插件mail和Thymeleaf做发送服务,显然这样子你需要配置一些东西,麻烦!!!接触了Spring Boot以后,显然有更好的解决方案,我们只需要引入spring-boot-starter-mail模块就实现了自动化配置。

好,废话不扯,言归正题(文中大部分是部分代码,详细代码见Git)。

开发环境

JDK1.7、Maven、Eclipse、SpringBoot1.5.2、spring-boot-starter-mail、spring-boot-starter-thymeleaf,spring-boot-starter-freemarker

项目结构

springboot-mail.png
springboot-mail.png

引入依赖

在工程中的pom.xml中引入以下依赖:

代码语言:txt
AI代码解释
复制
       <!-- email -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!-- thymeleaf 模版 -->
        <dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
	    <!-- freemarker 模版 -->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>

application.properties中配置以下内容:

代码语言:txt
AI代码解释
复制
spring.mail.host=smtp.qq.com
spring.mail.username=345849402@qq.com
#授权码g,在QQ邮箱客户端生成 修改成自己的  设置-账户-开启服务-获取授权码
spring.mail.password=XXXXXXX
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

#freemarker
spring.freemarker.template-loader-path=classpath:/static/template/
spring.freemarker.enabled=true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.allow-request-override=false
spring.freemarker.check-template-location=true
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false

#thymeleaf
spring.thymeleaf.prefix=classpath:/static/template/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html  
spring.thymeleaf.cache=false

封装实体

首先我们,封装一个Email实体Email.java:

代码语言:txt
AI代码解释
复制
/**
 * Email封装类 
 * 创建者 科帮网 
 * 创建时间 2017年7月20日
 *
 */
public class Email implements Serializable {
	private static final long serialVersionUID = 1L;
	//必填参数
	private String email;//接收方邮件
	private String subject;//主题
	private String content;//邮件内容
	//选填
	private String template;//模板
	private HashMap<String, String> kvMap;// 自定义参数
	... 省略 get set

业务实现

既然用了spring,就按照spring的方式来,先定义一个接口IMailService,接着是实现MailServiceImpl。

以下代码,实现了四种方式:纯文本,富文本(图片,附件),Freemarker模版以及Thymeleaf模版。

这里需要注意的是,springboot 1.4.0以后 Velocity 废弃了,官方建议用freemaker。而thymeleaf是博主自己实现的,显然效率没有freemaker高(评测对比见文章底部)。

代码语言:txt
AI代码解释
复制
@Service
public class MailServiceImpl implements IMailService {
	@Autowired
	private JavaMailSender mailSender;//执行者
	@Autowired
	public Configuration configuration;//freemarker
	@Autowired
	private SpringTemplateEngine  templateEngine;//thymeleaf
	@Value("${spring.mail.username}")
	public String USER_NAME;//发送者

	@Override
	public void send(Email mail) throws Exception {
		MailUtil mailUtil = new MailUtil();
		SimpleMailMessage message = new SimpleMailMessage();
		message.setFrom(USER_NAME);
		message.setTo(mail.getEmail());
		message.setSubject(mail.getSubject());
		message.setText(mail.getContent());
		mailUtil.start(mailSender, message);
	}

	@Override
	public void sendHtml(Email mail) throws Exception {
		MailUtil mailUtil = new MailUtil();
		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setFrom(USER_NAME);
		helper.setTo(mail.getEmail());
		helper.setSubject(mail.getSubject());
		helper.setText(
				"<html><body><img src=\"cid:springcloud\" ></body></html>",
				true);
		// 发送图片
		File file = ResourceUtils.getFile("classpath:static"
				+ Constants.SF_FILE_SEPARATOR + "image"
				+ Constants.SF_FILE_SEPARATOR + "springcloud.png");
		helper.addInline("springcloud", file);
		// 发送附件
		file = ResourceUtils.getFile("classpath:static"
				+ Constants.SF_FILE_SEPARATOR + "file"
				+ Constants.SF_FILE_SEPARATOR + "关注科帮网获取更多源码.zip");
		helper.addAttachment("科帮网", file);
		mailUtil.startHtml(mailSender, message);
	}

	@Override
	public void sendFreemarker(Email mail) throws Exception {
		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setFrom(USER_NAME);
		helper.setTo(mail.getEmail());
		helper.setSubject(mail.getSubject());
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("content", mail.getContent());
		Template template = configuration.getTemplate(mail.getTemplate()+".flt");
		String text = FreeMarkerTemplateUtils.processTemplateIntoString(
				template, model);
		helper.setText(text, true);
		mailSender.send(message);
	}
	@Override
	public void sendThymeleaf(Email mail) throws Exception {
		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setFrom(USER_NAME);
		helper.setTo(mail.getEmail());
		helper.setSubject(mail.getSubject());
		Context context = new Context();
		context.setVariable("email", mail);
		String text = templateEngine.process(mail.getTemplate(), context);
		helper.setText(text, true);
		mailSender.send(message);
	}
}

测试用例

老司机带你去开车SpringbootMailApplication.java:

代码语言:txt
AI代码解释
复制
@SpringBootApplication
@ComponentScan(basePackages={"com.itstyle.mail"})
public class SpringbootMailApplication implements CommandLineRunner {
	@Autowired
	private IMailService mailService;
	public static void main(String[] args) {
		SpringApplication.run(SpringbootMailApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		Email mail = new Email();
		mail.setEmail("345849402@qq.com");
		mail.setSubject("你个小逗比");
		mail.setContent("科帮网欢迎您");
		mail.setTemplate("welcome");
		mailService.sendFreemarker(mail);
	}
}

好了,不出意外,这四种方式应该绝对是没问题的,小伙伴们就等着右下角弹窗窗吧。

最后,做了一个小小的评测,生成模版时间对比(1000次循环)

  • Thymeleaf用时:2686ms
  • Freemarker用时:498ms

对比测试,建议使用Freemarker模版。

项目:http://git.oschina.net/52itstyle/spring-boot-mail

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C#-窗体之自制记事本
C#-窗体之自制记事本 展示结果: 功能: 1.登录判断账号密码 2.重置账户密码 3.自动换行 4.保存到桌面
用户9857551
2022/06/28
2370
C#-窗体之自制记事本
使用C#简单制作一个看门狗程序
在有些特殊项目中,软件可能是无人值守的,如果程序莫名其妙挂了或者进程被干掉了等等,这时开发一个看门狗程序是非常有必要的,它就像一只打不死的小强,只要程序非正常退出,它就能立即再次将被看护的程序启动起来。
沙漠尽头的狼
2022/11/29
9430
手把手带你开发一款 IIS 模块后门
记得之前看一篇 APT 组织的报告时偶然间看到过 IIS 模块后门然后在网上找了找了资料,想自己开发一款然后开发到一半因为一些事情就停止了很久,这次清理项目文件的时候又有想了起来就打算重新用 C# 继续写出来。
信安之路
2019/09/17
1.9K0
手把手带你开发一款 IIS 模块后门
C#-进程类-多线程
一个进程需要多个线程完成 一个进程是由多个线程组成的。 前台线程:只有所有的前台线程都关闭才能完成程序关闭。 后台线程:只要所有的前台线程结束,后台线程自动结束。 在.net下,是不允许跨线程的访问。 可以让系统不检测线程是否跨线程。
用户9857551
2022/06/28
2810
C#实例:datagridview单元格合并
这是替C#微信交流群群友做的一个小实例,目的就是在datagridview选择对应行以后,点击button后获取对应行的ip,并执行相应的操作,其实我觉得这样的话button没必要非放置到datagridview里面的!但是为了满足群友的需求,还是这么做了。
zls365
2020/08/19
5.3K0
C#实例:datagridview单元格合并
使用winform程序控制window服务的操作 c#之添加window服务(定时任务)
这篇文章主要讲述,使用winform程序来控制window服务的安装,启动,停止,卸载等操作
Vincent-yuan
2019/09/10
2.6K0
使用winform程序控制window服务的操作

            c#之添加window服务(定时任务)
C# WinForm实现自动更新程序之客户端的示例代码
/// The main entry point for the application.
用户7718188
2022/11/06
1K0
WPF 封装 dotnet remoting 调用其他进程
在 WPF 使用RPC调用其他进程 已经告诉大家调用的原理,但是大家可以看到,如果自己写一个框架是比较难的。
林德熙
2022/08/04
9550
监视的最低点(3)
与公开宣布的不同,数字考试监视器将有关所有网络适配器/接口的信息发送到其服务器。在撰写本文时,这尚未公开,并且很可能会让人认为负责任的开发人员正在监视的比他们所说的要多。这并不是您真正需要担心的关键数据,但动机未知。我们怀疑这被用来记录在考试期间使用虚拟专用网络的人。丹麦的考试情况是在学校 wifi 上进行的,这通常由负责的 IT 部门监控,因此使用虚拟专用网络会使这种监控无法工作。奇怪的是,在参加考试时使用虚拟专用网络是不被禁止的,这使得这个检查有点奇怪。
franket
2021/12/24
4.3K0
C#创建一个Window服务
Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这使服务非常适合在服务器上使用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。本文就向大家介绍如何运用Visual C#来一步一步创建一个文件监视的Windows服务程序,然后介绍如何安装、测试和调试该Windows服务程序。
用户1055830
2019/05/25
6930
C# 进程间通讯
进程间通讯的方式有很多,常用的有共享内存(内存映射文件、共享内存DLL、剪切板等)、命名管道和匿名管道、发送消息等几种方法来直接完成,另外还可以通过socket口、配置文件和注册表等来间接实现进程间数据通讯任务。以上这几种方法各有优缺点,具体到在进程间进行大数据量数据的快速交换问题上,则可以排除使用配置文件和注册表的方法;另外,由于管道和socket套接字的使用需要有网卡的支持,因此也可以不予考虑。这样,可供选择的通讯方式只剩下共享内存和发送消息两种。
zls365
2021/01/13
1.6K0
C# 进程间通讯
模拟键盘操作Windows应用程序
这是针对Windows系统录音软件的小程序 目的是把声音文件的频率转换的低一些 尝试过用WINDOWS API来做这个事,结果失败了 最后还是用程序操作EXE文件完成工作的 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.
liulun
2022/05/09
5820
WPF 封装 dotnet remoting 调用其他进程
在 WPF 使用RPC调用其他进程 已经告诉大家调用的原理,但是大家可以看到,如果自己写一个框架是比较难的。
林德熙
2018/09/19
8970
C#重定向 进程调用 WinForm多线程
需求: 一个以前的控制台程序,由于命令行方式对用户不够友好,所以加个界面调用控制台程序,但是以前的控制台输出信息就要重定向到新的界面上,要不用户不知道程序信息更不好。
井九
2024/10/12
1420
c# 动态生成控件
今天这个主题主要也是群里小伙伴提到的一个问题,就是如何动态的生成控件,他是想自动生成一级二级菜单这样,我这里主要是动态生成的picturebox,希望能给他起到借鉴的作用,然后举一反三完成自己的项目!
zls365
2020/08/19
1.6K0
c# 动态生成控件
C# 创建Windows服务demo
1.新建一个Windows Service,并将项目名称改为“MyWinsService”,程序保存路径自己选一个,如下图所示:
用户7053485
2020/03/19
9440
C# 创建Windows服务demo
C#/.NET基于Topshelf创建Windows服务的守护程序不显示UI界面的问题分析和解决方案
C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案
Rector
2019/05/25
1.4K0
自制安装程序~单文件~可安装windows服务~技巧!类似安装QQ!
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using System.Xml; using System.IO; using System.IO.Compression; u
liulun
2022/05/09
4640
自制安装程序~单文件~可安装windows服务~技巧!类似安装QQ!
20-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 加入数据通信
https://www.cnblogs.com/yangfengwu/p/11192594.html
杨奉武
2019/07/16
7620
20-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 加入数据通信
C# 软件开机启动
方法2:添加环境变量 , 计算行--属性--高级系统设置--环境变量--系统变量里面设置.
zls365
2020/08/19
6900
C# 软件开机启动
推荐阅读
相关推荐
C#-窗体之自制记事本
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档