Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件

好久没发博客了,忙东忙西的,坚持!

本文介绍Java使用Mailgun搭建发送邮件的服务。

我把这个邮件服务放在了我的springCloudApplication(微服务Demo)项目的utilservice服务模块中。
源码地址:springCloudApplication

  • jdk1.8
  • SpringBoot版本:2.0.4.RELEASE
  • SpringCloud版本:Finchley.RELEASE
  • Intellij IDEA :2018-2

本文涉及到基础的SpringCloud 知识,对应到本项目中的服务名来说就是:服务注册中心(eurekaserver),配置中心(configserver),路由(routeservice),负载均衡服务调用(uaaservice)。

一、Mailgun

Mailgun是国外的一个邮件服务器。主页:https://app.mailgun.com/

其实代码没多少,就是配置Mailgun需要花费些时间。

先用邮箱注册好。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第1张图片

Settings,显示的就是你的账户信息。
Security,这里的 Private API Key 就是等会要用到的身份认证key。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第2张图片
Authorized Recipients
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第3张图片
Upgrade,升级账户,貌似是$1。绑定你的信用卡。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第4张图片
接下来跳转到:https://app.mailgun.com/app/domains
domains,域名。上面个是我自己的域名(这里本该解析个二级域名的,我直接用顶级域名搞了一次),下面个是当你注册账户时Mailgun为你自动生成的一个二级域名。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第5张图片
刚开始进这个页面是只有下面个域名,自己的域名要通过Add New Aomain添加。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第6张图片
添加完之后你的域名会显示:Unverified,点击自己的域名验证,往下拉,看Domain Verification & DNS部分
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第7张图片
要去自己的域名服务商控制台配置,我这里全都配置好了所以全绿。我的域名阿里云买的,解析记录如下:
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第8张图片
看着这个GIF跟着配置就好了:https://help.mailgun.com/hc/en-us/articles/202052074-How-do-I-verify-my-domain-
我还添加了个SMTP Credentials:
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第9张图片
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第10张图片
好,现在Mailgun配置算是完成了。接下来上代码。还有啥问题就翻它的文档吧。

二、代码

我这里写了两种方式的邮件内容,一种纯文本内容的,一种thymeleaf模板引擎渲染的html内容的。就放在一起写了。只上核心代码和配置。详细了解看源码,文章开头已给出地址。
项目结构:
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第11张图片

  • eurekaserver,服务注册中心
  • confiserver,配置中心,几乎所有功能模块的配置都放在这里的
  • routeserver,路由网关
  • utilservice,邮件服务所在模块
  • uaaservice,在这里调用邮件服务

调用服务时传入收件人邮箱List,邮件的主题,邮件的thymeleaf模板,模板的参数(Map)。然后在邮件服务中渲染模板,然后通过mailgun发送邮件。

mailgun配置属性:

mailgun:
  domain: mistra.wang
  apiKey: key-e9861fdc2c1a6f189528c9cf18c5dc1a
  from: 丶小王瑞
  fromAddress: [email protected]
  mailgunResource: https://api.mailgun.net/v3/mistra.wang/messages

注意:如果写代码的时候把这个配置,就是你的mailgun的敏感信息,如key等。push到了Github的公共仓库的话你的邮件服务用不了,你的账户会被禁用。并且你会收到邮件提示,如何解决。记得测试完了代码再push。还挺严谨安全的,我测试完,刚push,马上我的账户就用不了了。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第12张图片
配置属性安全映射实体类

@Data
@Configuration
@ConfigurationProperties(prefix = "mailgun")
public class MailgunConfigProperties {
    private String domain;
    private String apiKey;
    private String from;
    private String fromAddress;
    private String mailgunResource;
}

MailgunConfig配置

@Configuration
public class MailgunConfig {
    /**
     * mailgun配置参数
     */
    @Autowired
    private MailgunConfigProperties mailgunConfigProperties;

    @Bean
    public net.sargue.mailgun.Configuration mailgunConfiguration(){
        net.sargue.mailgun.Configuration configuration = new net.sargue.mailgun.Configuration()
                .from(mailgunConfigProperties.getFrom(), mailgunConfigProperties.getFromAddress())
                .apiKey(mailgunConfigProperties.getApiKey())
                .domain(mailgunConfigProperties.getDomain());
        return configuration;
    }
}

thymeleaf模板引擎配置

@Configuration
public class SpringTemplateEngineConfig {

    @Bean(name = "stringTemplateEngine")
    public SpringTemplateEngine springTemplateEngine() {
        //字符串模板引擎对象
        SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
        //内置方言
        IDialect springStandardDialect = new SpringStandardDialect();
        springTemplateEngine.setDialect(springStandardDialect);
        //字符串解析器
        StringTemplateResolver stringTemplateResolver = new StringTemplateResolver();
        //使用缓存
        stringTemplateResolver.setCacheable(true);
        stringTemplateResolver.setTemplateMode(TemplateMode.HTML);
        springTemplateEngine.setTemplateResolver(stringTemplateResolver);
        return springTemplateEngine;
    }
}

线程池Bean

@Component
public class ThreadPoolConfig extends ThreadPoolTaskExecutor {

}

邮件实体

@Data
public class MailDTO {
    /**
     * 发送对象
     */
    @NotEmpty
    private List sendToAddress;
    /**
     * 主题
     */
    @NotNull
    private String subject;
    /**
     * 模板
     */
    @NotNull
    private String template;
    /**
     * 模板参数
     */
    @NotNull
    private Map paramsMap;
}

service

package com.mistra.utilservice.service.impl;

import com.mistra.base.result.Result;
import com.mistra.utilservice.config.MailgunConfigProperties;
import com.mistra.utilservice.dto.MailDTO;
import com.mistra.utilservice.service.MailService;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import net.sargue.mailgun.*;
import net.sargue.mailgun.content.Body;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

import javax.ws.rs.core.MediaType;
import java.util.regex.Pattern;

/**
 * @Author: WangRui
 * @Date: 2018/10/14
 * Time: 下午10:35
 * Description:
 */
@Service
public class MailServiceImpl implements MailService {

    private Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);

    /**
     * 邮箱验证正则
     */
    public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";

    /**
     * 字符串模板解析引擎
     */
    @Qualifier("stringTemplateEngine")
    @Autowired
    private SpringTemplateEngine springTemplateEngine;

    @Autowired
    private Configuration mailgunConfiguration;

    @Autowired
    private MailgunConfigProperties mailgunConfigProperties;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public Result sendMail(MailDTO mailDTO) {
        return sendTwo(mailDTO);
    }

    public Result sendOne(MailDTO mailDTO) {
        Result result = new Result();
        if (mailDTO.getSendToAddress().size() == 0 || mailDTO.getParamsMap().size() == 0 || StringUtils.isEmpty(mailDTO.getSubject()) || StringUtils.isEmpty(mailDTO.getTemplate())) {
            result.setSuccess(false);
            result.setMessage("MailDTO参数不正确!");
            return result;
        }
        for (String to : mailDTO.getSendToAddress()) {
            if (!Pattern.matches(REGEX_EMAIL, to)) {
                result.setSuccess(false);
                result.setMessage("邮箱格式错误!");
                return result;
            }
        }
        //编译thymeleaf模板 渲染数据
        Context context = new Context();
        context.setVariables(mailDTO.getParamsMap());
        String mailContent = springTemplateEngine.process(mailDTO.getTemplate(), context);
        Body mailBody = new Body(mailContent, "");

        MailBuilder mailBuilder = Mail.using(mailgunConfiguration);
        mailBuilder.subject(mailDTO.getSubject());
        mailBuilder.content(mailBody);
        for (String sendTo : mailDTO.getSendToAddress()) {
            mailBuilder.to(sendTo);
        }
        result.setSuccess(false);
        result.setMessage("邮件发送成功!");
        threadPoolTaskExecutor.submit(() -> {
            Response response = mailBuilder.build().send();
            logger.info("Send mail complete. Code: {}, Response Type: {}. Message: {}", response.responseCode(), response.responseType(), response.responseMessage());
            if (response.responseCode() != 200) {
                result.setSuccess(false);
                result.setMessage("邮件发送失败!" + response.responseMessage());
            }
        });
        return result;
    }

    /**
     * 第二种 发送纯文本邮件
     *
     * @param mailDTO
     * @return
     */
    public Result sendTwo(MailDTO mailDTO) {
        Result result = new Result();
        Client client = Client.create();
        client.addFilter(new HTTPBasicAuthFilter("api", mailgunConfigProperties.getApiKey()));
        WebResource webResource = client.resource(mailgunConfigProperties.getMailgunResource());
        MultivaluedMapImpl formData = new MultivaluedMapImpl();
        formData.add("from", mailgunConfigProperties.getFrom() + "" + mailgunConfigProperties.getFromAddress());
        mailDTO.getSendToAddress().stream().forEach(temp -> formData.add("to", temp));
        formData.add("subject", mailDTO.getSubject());
        formData.add("text", "纯文本邮件测试!");
        webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData);
        return result;
    }
}

三、查看Mailgun日志

你可以看到每一次发送邮件的日志,报错原因。
Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第13张图片
这个错误就是我的账户被禁用了,暴露了账户凭证,就是我把我的账户信息push到了Github公共仓库引起的。覆盖提交Commit是不管用的了,它提示你删库0-0,麻蛋。

"reject": {
        "reason": "exposed account credentials",
        "description": ""
    },

Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第14张图片

全文完。另外我是马自达粉。嘿嘿。

我的:

  • >>>>>>>CSDN<<<<<<<
  • >>>>>>>GitHub<<<<<<<
  • >>>>>>>个人博客<<<<<<<

Java(SpringCloud) 使用Thymeleaf渲染模板,通过Mailgun发送邮件_第15张图片

你可能感兴趣的:(Web,SpringBoot,SpringCloud)