美文网首页
SpringBoot发送邮件

SpringBoot发送邮件

作者: coder小明 | 来源:发表于2019-10-08 12:04 被阅读0次

    在小明经历的多个项目开发中,总会遇到消息通知的场景,比如某个广告主提交一个表单,我们要通知提醒运营人员及时查看。

    消息通知的形式也有很多,比如:短信、邮件、app推送等,本文主要给大家描述一下邮件通知的形式,因为邮件相比较其他通知渠道更方便实用(免费),除了简单文本邮件(已经满足大多数情形),本文还会重点说一下集成Thymeleaf模版引擎,使用HTML的形式发送邮件,尽管HTML内容不是标准化的消息格式,但是许多邮件客户端至少支持标记语言的子集,这种方式相比较纯文本展现形式更加友好。

    准备

    一个普通再也普通不了的SpringBoot项目

    简单文本发送

    还是那句老话,在SpringBoot看来一切都是这么便捷。它已经集成邮件发送所必需的库模块,我们只需将以下依赖添加到pom.xml即可。

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    

    邮箱服务结构

    Spring框架中用于Java邮件支持的接口和类组织如下:

    1. MailSender interface:发送简单基础电子邮件的顶级接口;

    2. JavaMailSender interface:是MailSender的子接口。它支持MIME消息,并且主要与MimeMessageHelper类一起用于创建MimeMessage。建议在此接口实现类JavaMailSenderImpl中使用MimeMessagePreparator机制;

    3. JavaMailSenderImpl class:实现了JavaMailSender 的接口,它支持MimeMessageSimpleMailMessage

    4. SimpleMailMessage class:用于创建简单的邮件消息,包括from,to,cc,subject和text字段;

    5. MimeMessagePreparator interface:提供一个回调接口,用于编写MIME消息;

    6. MimeMessageHelper class:用于创建MIME消息的帮助类。它为HTML布局中的图像,典型邮件附件和文本内容提供支持。

    在以下部分中,我将向大家展示如何使用这些接口和类:

    配置文件

    下面举例163邮箱(最常用的):

    spring:
      mail:
        host: smtp.163.com # 发件服务器
        username: coderxm@163.com # 账号
        password: xxxx # 密码(163需要授权第三方登录密码,请查看设置-客户端授权码密码开通)
        port: 465
        protocol: smtp
        default-encoding: utf-8
        # 下面这些配置大家不用深究,主要用于配置ssl
        properties:
          mail:
            imap:
              ssl:
                socketFactory:
                  fallback: false
            smtp:
              auth: true
              ssl:
                enable: true
                socketFactory:
                  class: com.fintech.modules.base.util.mail.MailSSLSocketFactory
              starttls:
                enable: true
                required: true
          test-connection: false
    

    代码

    service层

    按照常见的代码结构,我们先定义一个发送邮件的接口,负责创建和发送新的邮件消息。

    public interface EmailService {
        /**
         * 发送简单文本内容
         * @param to 发件人
         * @param subject 主题
         * @param text 内容
         */
        void sendSimpleMessage(String to,
                               String subject,
                               String text);
    }
    

    我们可以将一些常用的配置添加到yml配置文件当中

    # 邮件配置
    xiaoming:
      email:
        subject: "程序员小明"
        from: "coderxm@163.com"
        to: "xiaohong@163.com"
        # 抄送人:类型定义为数组,可以配置多个
        cc:
          - "xiaogang@163.com"
    

    然后再通过注解注入到一个实体类中,这样很优雅,随用随取:

    @Configuration
    @ConfigurationProperties(prefix = "xiaoming.email")
    @Data
    public class EmailConfig {
        private String subject;
        private String from;
        private String to;
        private String[] cc;
    }
    

    我们再定义一个类去实现这个接口:

    @Slf4j
    @Service
    public class EmailServiceImpl implements EmailService {
        @Autowired
        public JavaMailSender emailSender;
        @Autowired
        private EmailConfig emailConfig;
    
        @Override
        public void sendSimpleMessage(String to, String subject, String text) {
            try {
                SimpleMailMessage message = new SimpleMailMessage();
                message.setTo(to);
                message.setFrom("coderxm@163.com");
                message.setSubject(subject);
                message.setText(text);
                emailSender.send(message);
            } catch (MailException exception) {
                log.error(ExceptionUtil.stacktraceToString(exception));
            }
        }
    }
    

    测试

    我们做一个简单的测试:简单的邮件是否能够发送成功。

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class EmailTest {
        @Autowired
        private EmailService emailService;
        @Test
        public void testSimple(){
            emailService.sendSimpleMessage("ligang@163.com","XX篮球","你好,我想让周琦代言!");
        }
    }
    

    使用html作为模版发送邮件

    正在洋洋得意(准备划水)的时候,我们的产品突然对我说,“用简单的文本发送邮件也太简陋了吧,显示不出来我们的产品档次”,然后给我了一个样式,让我以这种形式发送,好啊,什么都难不倒小明。我连忙找到我们的前端,(假装低三下四地)让她帮忙排一个页面给我(这个工作我实在不想做,一是懒,二是人家前端肯定比我专业啊),为了保密,我简化一下,大概是这样的:

    <!DOCTYPE html>
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head></head>
    <body>
        姓 名:<span th:text="${userName}"></span>
        性 别:<span th:text="${gender}"></span>
    </body>
    </html>
    

    其实样式很好看的,但是这都不是重点,我们就以此作为模版举个例子,语法使用的都是thymeleaf,在此处就不再赘述,如果有想了解的可以去官网找。

    增加Thymeleaf dependency

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

    service层

    创建另一个服务类,它主要通过读取html模版封装数据准备邮件内容,在我们之前的示例中,这是一个简单的文本消息。

    @Service
    public class MailContentBuilder {
        @Autowired
        private TemplateEngine templateEngine;
    
        @Autowired
        public MailContentBuilder(TemplateEngine templateEngine) {
            this.templateEngine = templateEngine;
        }
    
        public String build(Map<String, Object> message) {
            Context context = new Context();
            context.setVariables(message);
            return templateEngine.process("email", context);
        }
    }
    

    EmailService增加接口:

    public interface EmailService {
        /**
         * 发送简单文本内容
         * @param to 发件人
         * @param subject 主题
         * @param text 内容
         */
        void sendSimpleMessage(String to,
                               String subject,
                               String text);
    
        /**
         * 传递多个变量,用于动态更换页面模版内容
         * @param emailInfoMap
         */
        void prepareAndSend(Map<String,Object> emailInfoMap);
    }
    

    EmailServiceImpl增加发送html形式邮件的实现方法:

    @Override
    public void prepareAndSend(Map<String,Object> emailInfoMap) {
        MimeMessagePreparator messagePreparator = mimeMessage -> {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(emailConfig.getFrom());
            messageHelper.setTo(emailConfig.getTo());
            messageHelper.setCc(emailConfig.getCc());
            messageHelper.setSubject(emailConfig.getSubject());
    //            messageHelper.setText(message);
            String content = mailContentBuilder.build(info);
            messageHelper.setText(content,true);
        };
        try {
            emailSender.send(messagePreparator);
        } catch (MailException e) {
            // runtime exception; compiler will not force you to handle it
        }
    }
    

    测试

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class EmailTest {
        @Autowired
        private EmailService emailService;
      
        @Test
        public void testHtml(){
            HashMap<String, Object> map = new HashMap<>();
            map.put("userName","程序员小明");
            map.put("gender","男");
            emailService.prepareAndSend(map);
        }
    }
    

    整个Springboot发送邮件的场景已经复盘结束,大家如果有用到的速速体验吧!
    欢迎关注微信公众号”程序员小明”,获取更多资源。

    相关文章

      网友评论

          本文标题:SpringBoot发送邮件

          本文链接:https://www.haomeiwen.com/subject/kmkbpctx.html