SpringBoot2.x整合SMTP邮件服务(使用篇)

JAVA && Spring && SpringBoot2.x — 学习目录

SpringBoot中使用Freemarker构建邮箱模板
SpringBoot2.x整合SMTP邮件服务(配置篇)

当邮件内容比较简单的时候,我们可能一行字符串就能表达出意思,但是绝大多数情况下,我们的邮件内容都比较复杂需要使用HTML来组织邮件内容。并且HTML中的数据还要动态修改,这时,最好的解决方案莫过于Freemarker。

Freemarker不仅可以做HTML模板(大多数情况下它都扮演了这个角色)。还可以XML、邮件等的模板。那么我们便看一下Freemarker要怎么使用。

1. 引入依赖

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
</dependency>

2. 创建邮件地址

需要根据我们想要的HTML样式,常见一个邮件模板,这个模板是ftl文件。

<p>你好,${name}童鞋,欢迎加入XXX大家庭!您的入职信息如下:</p>
<table border="1" cellspacing="0">
 <tr><td><strong style="color: #F00">工号</strong></td><td>${workID}</td></tr>
    <tr><td><strong style="color: #F00">合同期限</strong></td><td>${contractTerm}年</td></tr>
    <tr><td><strong style="color: #F00">合同起始日期</strong></td><td>${beginContract?string("yyyy-MM-dd")}</td></tr>
    <tr><td><strong style="color: #F00">合同截至日期</strong></td><td>${endContract?string("yyyy-MM-dd")}</td></tr>
    <tr><td><strong style="color: #F00">所属部门</strong></td><td>${departmentName}</td></tr>
    <tr><td><strong style="color: #F00">职位</strong></td><td>${posName}</td></tr>
</table>
<p><strong style="color: #F00; font-size: 24px;">希望在未来的日子里,携手共进!</strong></p>

3. 显示效果

邮件显示效果

样式可以根据自己的需求进行灵活调整,但是需要注意的是:一般在前后端分离中,不需要webapp目录,模板一般放在resources目录下的ftl目录。

4. 模板解析

Configuration cfg = new Configuration(Configuration.VERSION_2_3_27);
cfg.setClassLoaderForTemplateLoading(ClassLoader.getSystemClassLoader(),"ftl");
Template emailTemplate = cfg.getTemplate("email.ftl");
StringWriter out = new StringWriter();
emailTemplate.process(employee,out);
  1. 根据所使用的freemarker版本号创建一个Configuration对象 。
  2. 设置模板路径,模板路径的设置方法有好几个,我这里因为放在了resources目录下,因此使用了setClassLoaderForTemplateLoading方法
  3. 创建模板,通过process方法进行渲染,渲染后的html将放到out这个变量中,然后我们在邮件中直接将之发送出去即可。

2. SpringBoot整合email

Spring中文文档—使用MimeMessageHelper发送邮件

SpringEmail抽象的核心是MailSender接口,MailSender的实现能够把Email发送给邮件服务器,由邮件服务器实现邮件发送的功能。

image.png

Spring自带一个MailSender的实现JavaMailSenderImpl,他会使用JavaMail API来发送Email。Spring或SpringBoot在发送Email之前。我们必须要JavaMailSenderImpl装配为Spring应用上下文的一个Bean。

2.1 引入Maven文件

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2.2 配置application.yml

server:
  port: 8080
spring:
  mail:
    host: smtp.qq.com
    username:  #发送方邮箱账号
    password: #授权码,并非登录密码
    default-encoding: utf-8
    protocol: smtp
    properties:
      mail:
        smtp:
          ssl.trust: smtp.qq.com
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory #SSL证书Socket工厂
            port: 465 #使用SMTPS协议465端口
          auth: true
          starttls:
            enable: true
            required: true
  thymeleaf:
    prefix: classpath:/templates/

在此处需要说明一下:邮件发送端口默认为smtp协议的25端口,但是项目需要部署到阿里云,因为阿里云默认屏蔽掉了25端口,所以此处需要更换smtps协议465端口。

2.3 配置javabBean模板

 public class MailVerifyCode {
        private String code;
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    }

2.4 配置邮件发送的ftl模板

需要注意的是:要存放在resource目录下的templates文件夹下。当中的${params.username}是EL表达式,需要代码中进行配置。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>修改密码</title></head>
<body>
<table cellspacing="0" cellpadding="0" width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0;">
    <tbody>
    <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
        <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;"> </td>
        <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; max-width: 600px !important; clear: both !important; margin: 0 auto;">
            <table cellspacing="0" cellpadding="0" width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
                <tbody>
                <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
                    <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; text-align: center; margin: 0; padding: 20px;">
                        <table cellspacing="0" cellpadding="0" width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;background-color: #fff">
                            <tbody>
                            <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
                                <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"> <h1 style="font-family: 'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif; box-sizing: border-box; font-size: 32px; color: #000; line-height: 1.2em; font-weight: 500; text-align: center; margin: 40px 0 0;">
                                        <img style="height:32px;" alt="" /></h1> </td>
                            </tr>
                            <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
                                <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"> <h1 style="font-family: 'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif; box-sizing: border-box; font-size: 24px; color: #000; line-height: 1.2em; font-weight: 500; text-align: center; margin: 40px 0 0;"> 需要您的注意</h1> </td>
                            </tr>
                            <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
                                <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;">
                                    <h1 style="padding-bottom:60px;font-family: 'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif; box-sizing: border-box; font-size: 20px; color: #000; line-height: 1.2em; font-weight: 500; text-align: center; margin: 40px 0 0;">
                                        <p>${(params.username)!""}</p>
                                        <p>您现在正在做修改密码操作,</p>
                                        <p>验证码为 <span style="color:#3dabff;font-weight: bolder;">${(params.code)!""}</span>,
                                        </p> <p>请不要把验证码告诉别人哦!</p>
                                    </h1></td>
                            </tr>
                            </tbody>
                        </table> </td>
                </tr>
                </tbody>
            </table> </td>
        <td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;"> </td>
    </tr>
    </tbody>
</table>
</body>
</html>

2.5 配置最大超时时间的邮件发送

@Component
public class FreeMarker {

    @Value("${spring.mail.username}")
    private String sender;

    @Resource
    private JavaMailSender javaMailSender;


    @Resource
    private FreeMarkerConfigurer configurer;


    public String sendMailCode(String toMail) throws Exception{
        final String title = "标题";
        final ExecutorService exec = Executors.newSingleThreadExecutor();
        Callable<String> call = () -> {
            try {
                String code = getMailCode();
                MailVerifyCode verifyCode = new MailVerifyCode();
                verifyCode.setCode(code);
                sendMail(verifyCode,title,"updatePsw.ftl",toMail);
                return code;
            }catch (Exception e){
                throw new Exception("发送失败",e);
            }
        };
        try {
            Future<String> future = exec.submit(call);
            String code = future.get(1000*10*1000, TimeUnit.MILLISECONDS);//设置超时响应时间为10s
            return code;
        }catch (Exception e){
            throw new Exception("发送失败",e);
        }finally {
            exec.shutdown();
        }
    }

    public String getMailCode(){
        String code = String.valueOf((int)((Math.random()*9 +1)*100000));
        return code;
    }

    /**
     *
     * @param params 模板参数
     * @param title 标题
     * @param templateName 模板名称
     * @param to 收件方
     * @throws Exception
     */
    public void sendMail(Object params,String title,String templateName,String to) throws Exception{
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        //防止成为垃圾邮件,披上outlook的马甲
        mimeMessage.addHeader("X-Mailer","Microsoft Outlook Express 6.00.2900.2869");
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
        //设置发送方
        helper.setFrom(sender);
        //设置收件方
        helper.setTo(InternetAddress.parse(to));
        //设置发送邮件数据,填入到模板中
        Map<String,Object> model = new HashMap<>();
        model.put("params",params);
        //读取邮件模板
        Template template = configurer.getConfiguration().getTemplate(templateName);
        String text = FreeMarkerTemplateUtils.processTemplateIntoString(template,model);
        helper.setText(text,true);
        //设置标题
        helper.setSubject(title);
        //发送邮件
        javaMailSender.send(mimeMessage);
    }

}

2.6 单元测试

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class TestEmail {

    @Autowired
    private FreeMarker freeMarker;

    @Test
    public void emailTest(){
        try {
            freeMarker.sendMailCode("接受方的邮件地址");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

文章参考

SpringBoot中使用Freemarker构建邮件模板

使用springboot发送邮件(前后端分离:使用freemark模板技术)

freemark邮件模板

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,501评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,673评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,610评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,939评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,668评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,004评论 1 329
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,001评论 3 449
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,173评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,705评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,426评论 3 359
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,656评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,139评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,833评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,247评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,580评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,371评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,621评论 2 380

推荐阅读更多精彩内容