第四章:使用Springboot2整合JavaMail发送邮件

2019-03-05  本文已影响0人  菜出意料

本章目标

整合JavaMail发送邮件,结果展示在文档末尾。

搭建项目

build.gradle依赖

    implementation 'org.springframework.boot:spring-boot-starter-mail'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

application.yml配置

spring:
  mail:
    properties:
      mail:
        smtp:
          connectiontimeout: 5000
          timeout: 3000
          writetimeout: 5000
    host: smtp.126.com
    protocol: smtp
    port: 25
    username: 邮箱登录账号,如XXX@126.com
    password: 邮箱授权码
  1. host: 不同的邮箱对应的host不同,126邮箱为smtp.126.com
  2. username: 发件箱邮箱登录账号
  3. password: 邮箱授权码,如何获取不同邮箱的授权码可自行百度

Tips:Springboot项目启动时,会根据application.yml中的mail配置实例化JavaMailSenderImpl实例mailSender,在使用mailSender时可以通过@Autowired直接注入。

编写SpringTool工具类

@Component
public class SpringTool implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return applicationContext.getBean(beanName, clazz);
    }

    public static Object getBean(String beanName) {
        return getBean(beanName, null);
    }
}

SpringTool工具类主要根据beanName获取对应的对象

编写MailUtil类

public class MailUtil {
    private static JavaMailSenderImpl mailSender = SpringTool.getBean("mailSender", JavaMailSenderImpl.class);

    @RequiredArgsConstructor
    static class MimeMessageHelperBuilder {
        private final MimeMessage message;

        /**
         * 是否带附件 发送带附件和html格式的右键时必须为true
         */
        private final boolean multipart;

        /**
         * 收件人
         */
        private String to;

        /**
         * 右键主题
         */
        private String subject;

        /**
         * 右键内容
         */
        private String text;

        /**
         * 是否html格式的邮件
         */
        private boolean html;

        MimeMessageHelperBuilder to(String to) {
            this.to = to;
            return this;
        }

        MimeMessageHelperBuilder subject(String subject) {
            this.subject = subject;
            return this;
        }

        MimeMessageHelperBuilder text(String text) {
            this.text = text;
            return this;
        }

        MimeMessageHelperBuilder html(boolean html) {
            this.html = html;
            return this;
        }

        MimeMessageHelper build() throws MessagingException {
            MimeMessageHelper helper = new MimeMessageHelper(message, multipart);
            helper.setFrom(mailSender.getUsername());

            helper.setTo(to);
            helper.setText(text, html);
            helper.setSubject(subject);

            return helper;
        }
    }

    /**
     * 发送普通文本邮件
     * @param to       收件人
     * @param subject  邮件标题
     * @param text     邮件正文
     * @throws MessagingException
     */
    public static void setTextMail(String to, String subject, String text) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelperBuilder builder = new MimeMessageHelperBuilder(message, false);
        MimeMessageHelper helper = builder.to(to).subject(subject).text(text).build();

        sendMail(message);
    }

    /**
     * 发送带附件的邮件
     * @param to                    收件人
     * @param subject               邮件标题
     * @param text                  邮件正文
     * @param attachmentNamePathMap 附件名和附件路径组成的map
     * @throws MessagingException
     */
    public static void sendAttachmentMail(String to, String subject, String text, Map<String, String> attachmentNamePathMap) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelperBuilder builder = new MimeMessageHelperBuilder(message, true);
        MimeMessageHelper helper = builder.to(to).subject(subject).text(text).build();

        /**
         * 组装附件信息
         */
        attachmentNamePathMap.forEach((n, p) -> {
            FileSystemResource file = new FileSystemResource(new File(p));
            try {
                helper.addAttachment(n, file);
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        });

        sendMail(message);
    }

    /**
     * 发送html格式的邮件
     * @param to                收件人
     * @param subject           邮件标题
     * @param htmlText          html文档
     * @param inlineNamePathMap src名及路径对应的map
     * @throws MessagingException
     */
    public static void senHtmlMail(String to, String subject, String htmlText, Map<String, String> inlineNamePathMap) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelperBuilder builder = new MimeMessageHelperBuilder(message, true);
        MimeMessageHelper helper = builder.to(to).subject(subject).text(htmlText).html(true).build();

        /**
         * 组装html里img标签的src
         */
        inlineNamePathMap.forEach((n, p) -> {
            FileSystemResource file = new FileSystemResource(new File(p));
            try {
                helper.addInline(n, file);
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        });

        sendMail(message);
    }

    private static void sendMail(MimeMessage message) {
        mailSender.send(message);
    }

}

编写单元测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter04ApplicationTests {
    @Test
    public void testSendTextMail() throws MessagingException {
        MailUtil.setTextMail("***收件人邮箱***", "Text Mail", "测试JavaMail的Text mail");
    }

    @Test
    public void testSendAttachmentMail() throws MessagingException {
        Map<String, String> attachmentNamePathMap = new HashMap<>();
        attachmentNamePathMap.put("mysql-apt-config_0.8.12-1_all.deb", "/home/bobyco/Downloads/mysql-apt-config_0.8.12-1_all.deb");
        attachmentNamePathMap.put("desktop.jpg", "/home/bobyco/Pictures/desktop.jpg");
        attachmentNamePathMap.put("Paper_Architecture_by_Dmitri_Popov.jpg", "/home/bobyco/Pictures/Paper_Architecture_by_Dmitri_Popov.jpg");
        MailUtil.sendAttachmentMail("***收件人邮箱***", "Text Mail", "测试JavaMail发送带附件的邮件", attachmentNamePathMap);
    }

    @Test
    public void testSendHtmlMail() throws IOException, TemplateException, MessagingException {
        Map<String, String> inlineNamePathMap = new HashMap<>();
        inlineNamePathMap.put("desktop", "/home/bobyco/Pictures/desktop.jpg");

        StringBuffer s = new StringBuffer();
        s.append("<html>")
            .append("<head>")
            .append("<title>Welcome!</title>")
            .append("</head>")
            .append("<body>")
            .append("<h1>Welcome JavaMail!</h1>")
            .append("<p>Our latest product:<a href=\"http://baidu.com\"><img src=\"cid:desktop\" alt=\"\"></a></p>")
            .append("</body>")
            .append("</html>");

        MailUtil.senHtmlMail("***收件人邮箱***", "测试发送html格式的右键", s.toString(), inlineNamePathMap);
    }

    @Test
    public void contextLoads() {
    }

}

整合FreeMarker,使用FreeMarker模板创建邮件内容

添加FreeMarker依赖

implementation 'org.springframework.boot:spring-boot-starter-freemarker'

在application.yml添加FreeMarker配置

  freemarker:
    template-loader-path: classpath:/templates/mail/

Tips: Springboot项目启动时,会自动初始化id为freeMarkerConfiguration的freemarker.template.Configuration对象,在使用freeMarkerConfiguration时通过SpringTool获取或使用@Autowired注入都可!

在MailUtil中添加sendTemplateMail方法

     private static Configuration cfg = SpringTool.getBean("freeMarkerConfiguration", Configuration.class);
    /**
     * 使用FreeMarker模板创建邮件内容
     * @param to                 收件人邮箱
     * @param subject            邮件标题
     * @param templatePath       模板路径
     * @param dataModel          模板对应的数据
     * @param inlineNamePathMap  src名及路径对应的map
     * @throws IOException
     * @throws TemplateException
     * @throws MessagingException
     */
    public static void sendTemplateMail(String to, String subject, String templatePath, Map dataModel, Map<String, String> inlineNamePathMap) throws IOException, TemplateException, MessagingException {
        Template temp = cfg.getTemplate(templatePath);
        String emailContent = FreeMarkerTemplateUtils.processTemplateIntoString(temp, dataModel);
        senHtmlMail(to, subject, emailContent, inlineNamePathMap);
    }

在resources/templates/mail路径下编写MailHtmlTemplate.ftl文件

<html>
<head>
    <title>Welcome!</title>
</head>
<body>
<h1>${title}!</h1>
<p>Our latest product:<a href="http://baidu.com"><img src="cid:desktop" alt=""></a></p>
</body>
</html>

编写单元测试

    @Test
    public void testSendTemplateMail() throws TemplateException, IOException, MessagingException {
        Map<String, String> inlineNamePathMap = new HashMap<>();
        inlineNamePathMap.put("desktop", "/home/bobyco/Pictures/desktop.jpg");

        Map dataModel = new HashMap();
        dataModel.put("title", "Welcome JavaMail Creating Email Content by Using a Templating Library!");

        MailUtil.sendTemplateMail("***收件人邮箱***", "测试发送使用模板创建正文的邮件", "MailHtmlTemplate.ftl", dataModel, inlineNamePathMap);
    }

结果预览

Tips: 如果在邮件里查看不到图片,请在电脑网页版邮箱中设置图片可见,即可浏览到图片!

模板邮件.png
html格式邮件.png
带附件的邮件.png
普通文本邮件.png

源码路径

本文源码地址:https://gitee.com/bobyco/sprintboot2_note_source/tree/master/chapter04
end

上一篇下一篇

猜你喜欢

热点阅读