阅读 39

Java整合Spring发送邮件

个人博客项目地址

希望各位帮忙点个star,给我加个小星星✨


又懒了,要多看书和总结,然后早点写博客😝

有时候代码执行完之后,需要邮件进行通知,所以通过工作中的项目和网上的资料,特地去学习了如何使用Java发送邮件。Demo使用的是QQ邮箱进行邮件发送,可以先了解一下基础文档协议RFC882、MIME、SMTP等


文档协议说明

看了孤傲苍狼的文章,关于邮件协议,他解释的很好,这边进行记录了一下

RFC882文档(发送简单文字邮件)

RFC882文档规定了如何编写一封简单的邮件(纯文本邮件),一封简单的邮件包含邮件头和邮件体两个部分,邮件头和邮件体之间使用空行分隔。

邮件头包含的内容有:

  • from字段   --用于指明发件人
  • to字段    --用于指明收件人
  • subject字段 --用于说明邮件主题
  • cc字段    -- 抄送,将邮件发送给收件人的同时抄送给另一个收件人,收件人可以看到邮件抄送给了谁
  • bcc字段    -- 密送,将邮件发送给收件人的同时将邮件秘密发送给另一个收件人,收件人无法看到邮件密送给了谁

MIME文档(可以发送HTML邮件)

在我们的实际开发当中,一封邮件既可能包含图片,又可能包含有附件,在这样的情况下,RFC882文档规定的邮件格式就无法满足要求了。

MIME协议是对RFC822文档的升级和补充,它描述了如何生产一封复杂的邮件。通常我们把MIME协议描述的邮件称之为MIME邮件。MIME协议描述的数据称之为MIME消息。    对于一封复杂邮件,如果包含了多个不同的数据,MIME协议规定了要使用分隔线对多段数据进行分隔,并使用Content-Type头字段对数据的类型、以及多个数据之间的关系进行描述。   

SMTP协议

要使用QQ邮箱发送邮件,就要遵守SMTP协议。SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。

需要在QQ邮箱中打开SMTP服务和生成授权码

QQ邮箱


Demo的时序图


代码实现

demo使用的是Velocity模板引擎进行html渲染,其它渲染方式类似,最后都是生成context内容。

基础依赖

java mail/spring-context-support/velocity

compile group: 'com.sun.mail', name: 'javax.mail', version: '1.6.1'
compile group: 'org.springframework', name: 'spring-context-support', version: '5.0.8.RELEASE'
compile group: 'org.apache.velocity', name: 'velocity', version: '1.7'
复制代码

邮件基础Bean

public class MailBean {
    /** 邮件发送人地址,非空 */
    private String from;
    /** 邮件发送人姓名,非空 */
    private String fromName;
    /** 邮件接收人地址列表,非空 */
    private String[] toList;
    /** 邮件抄送人地址列表 */
    private String[] ccList;
    /** 邮件主题,非空 */
    private String subject;
    /** 邮件内容velocity上下文参数 */
    private Map<String, Object> mailContext;
    /** 邮件内容velocity模板,非空 */
    private String mailVmName;
    ···
}
复制代码

模板引擎渲染工具

public class VelocityUtils {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(VelocityUtils.class);
    private static final VelocityEngine VE = new VelocityEngine();
    static {
        initVelocity();
    }
    private static void initVelocity() {
        try {
            VE.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
            VE.setProperty(
                    "classpath.resource.loader.class",
                    ClasspathResourceLoader.class.getName());
            VE.setProperty(RuntimeConstants.RUNTIME_LOG, "logs/velocity.log");
            VE.setProperty(
                    RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
                    "org.apache.velocity.runtime.log.NullLogChute");
            VE.init();
        } catch (Exception e) {
            LOGGER.warn("初始化velocity模板引擎失败", e);
        }
    }
    /** 实际渲染的代码,map里面的字段与编写的模板相对应 **/
    public static String render(String vmName, Map<String, Object> context) {
        String renderStr = "";
        try {
            Template template = VE.getTemplate(vmName, "UTF-8");
            VelocityContext velocityContext = new VelocityContext();
            for (Map.Entry<String, Object> entry : context.entrySet()) {
                velocityContext.put(entry.getKey(), entry.getValue());
            }
            StringWriter sw = new StringWriter();
            template.merge(velocityContext, sw);
            renderStr = sw.toString();
        } catch (Exception e) {
            LOGGER.warn("渲染vm模板失败", e);
        }
        return renderStr;
    }
}
复制代码

发送邮件的服务

我们使用spring进行依赖注入,帮我们托管mailSender

<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <!--         <property name="host" value="smtp.qq.com"/> -->
        <property name="host" value="smtp.qq.com"/>
        <property name="port" value="587"/>
        <!--         <property name="username" value="xxxxx@qq.com"/> -->
        <property name="username" value="xxxxxx@qq.com"/>
        <!-- qq邮箱的授权码,如果是企业邮箱,则使用登录密码 -->
        <property name="password" value="xxxxxxxxxxx"/>
        <property name="javaMailProperties">
            <props >
                <prop key="mail.smtp.auth">true</prop>
            </props>
        </property>
    </bean>
复制代码

面向接口编程

public interface MailService {

    /**
     * 发送邮件
     *
     * @param mailBean      邮件bean
     */
    void sendMail(MailBean mailBean);

}


@Service
public class MailServiceImpl implements MailService {

    @Autowired
    @Qualifier("javaMailSender")
    private JavaMailSender mailSender;


    @Override
    public void sendMail(MailBean mailBean) {
        // 省略了校验
        try {
            // 工具类进行内容渲染,传入的是模板名称和具体内容MAP
            String mailContent = VelocityUtils.render(
                    mailBean.getMailVmName(),
                    mailBean.getMailContext());
            MimeMessage msg = mailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(msg, true, "UTF-8");
            mimeMessageHelper.setFrom(mailBean.getFrom(), mailBean.getFromName());
            mimeMessageHelper.setSubject(mailBean.getSubject());
            mimeMessageHelper.setTo(mailBean.getToList());
            mimeMessageHelper.setText(mailContent, true);

            mailSender.send(msg);

        } catch (Exception e) {
            log.warn("邮件发送失败,mailBean={}", mailBean, e);
        }
    }
}
复制代码

demo.vm(模板文件)

<html xmlns="http://www.w3.org/1999/xhtml ">
<body class="word-style">
<div class="title" align="center">DEMO</div>
<br/>
<div class="indent">$!{msg}</div>
</body>
</html>
复制代码

发送邮件

最后通过调用MailService进行邮件发送

MailBean mailBean = new MailBean();
mailBean.setFrom("xxxxxx@qq.com");
mailBean.setFromName("DEMO");
mailBean.setSubject("Are you ok");
//模板
mailBean.setMailVmName("demo.vm");
//收件人地址
String[] toList = {"xxxxx@xxxx.com"};
mailBean.setToList(toList);
Map<String, Object> context = new HashMap<>();
context.put("msg", "I'm fine, thank you~");
mailBean.setMailContext(context);
mailService.sendMail(mailBean);
复制代码

当然,你可以制作更加好看的html邮件~


参考资料

  1. JavaWeb学习总结(五十二)——使用JavaMail创建邮件和发送邮件
  2. Java 发送邮件
  3. 通过spring实现javamail发送邮件功能
  4. 腾讯的IMAP服务说明
关注下面的标签,发现更多相似文章
评论