Spring boot 集成邮件通知

1. 工作中很难避免会有一些需要邮件通知的情况,网络上也有很多邮件模板和工具类

     我们可以先从网上找一个邮件工具类试着体验一下邮件发送然后在进行改造(直接使用工具类也能发送邮件,不过我们每次程序执行时还要调用邮件发送势必会影响我们编写的程序执行效率,尤其对需进行压测的程序不建议直接使用)!

       在此提供一篇供参考 邮件通知工具类       

2. 邮件通知

首先我们建一张邮件模板表用于存储邮件模板,如下图

字段意思分别是 id,code,参数个数,模板内容,使用状态值.....后面是记录创建和修改人和时间

Spring boot 集成邮件通知

其次我们将邮件模板从数据库中读取出来并写入缓存中(简单的代码在此忽略不做展示和解释)

      logger.info("==========加载邮件模板信息===begin========");

      List<EmailTemplate> listEmailTemplate = emailTemplateMapper.selectAll();

     //本类只有一个属性List<EmailTemplate> emailTemplates 并于使用对象的方式存储数据

      EmailTemplateDTO emailTemplateDTO = new EmailTemplateDTO();

      emailTemplateDTO.setEmailTemplates(listEmailTemplate);

      redisUtil.setObjectToJson(SystemInitUtil.SYSTEM_EMAIL_TEMPLATE, -1, emailTemplateDTO);

注意需要在程序启动时或使用时自动加载实现CommandLineRunner类即可,这个实现简单不做解释;

下面我们就需要实际项目使用了,我们为了不影响正常程序执行采用另起线程的方式发送邮件(后面会给我封装好的工具类)

    Spring boot 集成邮件通知

    String assignerEmail ="";   //收件人邮箱,可多个以逗号分隔

    String content1 =systemInitUtil.getEmailTempCon("AD-002", new String[] {enterName});//根据code返回模板内容

    SendEmailThread sendEmailThread = new SendEmailThread(sendEmailUtil,assignerEmail,"入场反馈",content1,null);

   new Thread(sendEmailThread, "需求创建系统自动发送邮件").start();

Spring boot 集成邮件通知

Spring boot 集成邮件通知

Spring boot 集成邮件通知

工具类的属性值

Spring boot 集成邮件通知

修改后的邮件工具类

package com.leon.api.common.utils.email;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import com.leon.api.common.utils.StringUtil;

@Configuration
public class SendEmailUtil {
    private static Logger logger = LoggerFactory.getLogger(SendEmailUtil.class);    
    @Value("${emailTitle}")
    private String emailTitle;    
    
    @Value("${emailAccount}")
    private String emailAccount;
    
    @Value("${emailPassword}")
    private String emailPassword;
    
    @Value("${emailSMTPHost}")
    private String emailSMTPHost;
    
    @Value("${templatePath}")
    private String templatePath;
    
    public static void main(String[] args) {
        SendEmailUtil util = new SendEmailUtil();
        util.sendEmail("***@163.com,***@163.com", "***审批通过,详细可登录系统查看,谢谢!");
    }

    /**
     * 邮件发送
     *
     * @param receiveMailAccount
     *            发送邮件地址
     * @param title
     *            主题
     * @param content
     *            内容
     */
    public synchronized void sendEmail(String receiveMailAccount, String content) {
        sendEmail(receiveMailAccount,emailTitle,content,null);
    }

    /**
     * 邮件发送
     *
     * @param receiveMailAccount
     *            发送邮件地址
     * @param title
     *            主题
     * @param content
     *            内容
     */
    public synchronized void sendEmail(String receiveMailAccount, String title, String content) {
        sendEmail(receiveMailAccount,title,content,null);
    }
    
    /**
     * 邮件发送
     *
     * @param receiveMailAccount
     *            发送邮件地址    
     * @param title
     *            主题
     * @param content
     *            内容
     * @param ccMailAccount
     *            抄送邮件地址
     */
    public synchronized void sendEmail(String receiveMailAccount, String title, String content,String ccMailAccount) {
        logger.info("==========邮件发送开始=========== ");
        logger.info("邮件发送地址:" + receiveMailAccount);
        logger.info("邮件内容:" + content);
        try {
            String  emailT = getEmailTempalte();
            
            content =  emailT.replace("/**content**/",content);
            
//            receiveMailAccount = "[email protected]";
//            ccMailAccount = "[email protected]";
            
            Properties props = new Properties(); // 参数配置
            props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议(JavaMail规范要求)
            props.setProperty("mail.smtp.host", emailSMTPHost); // 发件人的邮箱的 SMTP 服务器地址
            props.setProperty("mail.smtp.auth", "true");

            Session session = Session.getInstance(props);
            session.setDebug(true);                
            MimeMessage message = sendMimeMessage(session, receiveMailAccount,ccMailAccount,title,content);

            Transport transport = session.getTransport();
            transport.connect(emailAccount, emailPassword);
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();        
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info("==========邮件发送完成=========== ");
    }

    /**
     * 创建一封只包含文本的简单邮件
     *
     * @param session
     *            和服务器交互的会话
     * @param replyToMail
     *            抄送邮箱
     * @param receiveMail
     *            收件人邮箱
     * @return
     * @throws Exception
     */    
    private static MimeMessage sendMimeMessage(Session session, String receiveMail,String replyToMail, String title, String content)
            throws Exception {
        // 1. 创建一封邮件
        MimeMessage message = new MimeMessage(session);
        Multipart multipart = new MimeMultipart();
        
        // 2. From: 发件人(昵称有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改昵称)
        message.setFrom(new InternetAddress("******@163.com", "系统公共邮箱", "UTF-8"));

        // 3. To: 收件人(可以增加多个收件人、抄送、密送)
        if (receiveMail.indexOf(",") < 0) {
            message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress(receiveMail, receiveMail.split("@")[0], "UTF-8"));
        } else {
            String[] receiveMails = receiveMail.split(",");
            Address[] addresses = new Address[receiveMails.length];
            String mail = "";
            for (int i = 0; i < receiveMails.length; i++) {
                mail = receiveMails[i];
                addresses[i] = new InternetAddress(mail, mail.split("@")[0], "UTF-8");
            }
            message.setRecipients(MimeMessage.RecipientType.TO, addresses);                
        }
        
        //抄送
        if(StringUtil.isNotNull(replyToMail) && replyToMail.indexOf(",") < 0) {
            message.setRecipient(MimeMessage.RecipientType.CC,new InternetAddress(replyToMail, replyToMail.split("@")[0], "UTF-8"));
        } else if(StringUtil.isNotNull(replyToMail) && replyToMail.indexOf(",") > 0) {
            String[] replyToMails = replyToMail.split(",");
            Address[] addresses = new Address[replyToMails.length];
            String ccAddresses = "";
            for(int i = 0; i < replyToMails.length; i++) {
                ccAddresses = replyToMails[i];
                addresses[i] = new InternetAddress(ccAddresses, ccAddresses.split("@")[0], "UTF-8");
            }
            message.setRecipients(MimeMessage.RecipientType.CC, addresses);
        }        

        // 4. Subject: 邮件主题(标题有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改标题)
        message.setSubject(MimeUtility.encodeText(title, "UTF-8", "B"));

        BodyPart bodyPart = new MimeBodyPart();  
        bodyPart.setContent(content, "text/html;charset=utf-8");
        multipart.addBodyPart(bodyPart);
        
        // 5. Content: 邮件正文(可以使用html标签)(内容有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改发送内容)
        message.setContent(multipart);        

        // 6. 设置发件时间
        message.setSentDate(new Date());

        // 7. 保存设置
        message.saveChanges();
        
        return message;
    }
    
    @SuppressWarnings("resource")
    private String getEmailTempalte() {
        String filePath = this.getClass().getResource("/").getPath();        
        filePath = filePath+"emailTemplate.html";
        if(filePath.indexOf("%20") >= 0){
            filePath = filePath.replaceAll("%20", " ");
        }
        logger.info("当前操作系统:"+System.getProperties().get("os.name").toString().toUpperCase());
        if (System.getProperties().get("os.name").toString().toUpperCase().indexOf("WINDOWS") >= 0) {
            filePath = filePath.substring(1,filePath.length());
        }else {
            filePath = this.templatePath;
        }
        logger.info("=======filePath====="+filePath);
        InputStreamReader isr = null;
        try {
            isr = new InputStreamReader(new FileInputStream(new File(filePath)), "UTF-8");
            BufferedReader input = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            String text;
            while ((text = input.readLine()) != null) {
                buffer.append(text + "\n");
            }
            logger.info("=======buffer====="+buffer.length());
            return buffer.toString();
        } catch (FileNotFoundException e) {            
            logger.error("文件获取错误:",e);
        } catch (IOException e) {            
            logger.error("文件输出错误:",e);
        }
        return "";
    }
    

}

线程处理 邮件发送

package com.leon.api.common.utils.email;

import java.text.MessageFormat;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SendEmailThread implements Runnable{
    
    private Logger logger = LoggerFactory.getLogger(SendEmailThread.class);
    
    private String receiveMailAccount;//收件邮箱
    
    private String title;//标题
    
    private String content;//内容
    
    private String ccMailAccount;//抄送
    
    private SendEmailUtil sendEmailUtil;// 发送邮件
    
    public SendEmailThread(SendEmailUtil sendEmailUtil,String receiveMailAccount, String title, String content,String ccMailAccount) {
        this.receiveMailAccount = receiveMailAccount;
        this.title = title;
        this.content = content;
        this.ccMailAccount = ccMailAccount;
        this.sendEmailUtil = sendEmailUtil;
    }
    
    @Override
    public void run() {
        try {
            sendEmailUtil.sendEmail(this.receiveMailAccount,this.title,this.content);
        } catch (Exception e) {
            logger.info(MessageFormat.format("邮件发送失败,收件人:{0}抄送:{1},标题:{2}内容:{3}", this.receiveMailAccount,this.ccMailAccount,this.title, this.content));
            e.printStackTrace();
        }
    }
    //get/set忽略
}

emailTemplate.html 模板

<html>
<head>
<meta charset="UTF-8">
<style>
    .out-container h3{font-size:18px;font-weight:&nbsp;normal;line-height:&nbsp;26px;color:&nbsp;#3a3a3a;}
    .out-table{border-left: 1px solid #5e6973;border-top: 1px solid #5e6973;}
    .out-table td{border-right: 1px solid #5e6973;border-bottom: 1px solid #5e6973;text-align: center;font-size: 14px;font-weight: normal;padding: 8px 15px;}
    .out-table th{border-right: 1px solid #5e6973;border-bottom: 1px solid #5e6973;text-align: center;font-size: 14px;padding: 8px 15px;background: #e7f1fa;}
    .out-font{font-size: 14px;margin-bottom: 15px;font-family:"微软雅黑";color: #333; margin-top:15px;}
    .out-font span{color:#fc9153;font-size: 18px;}
    .main-box{
        padding-left:20px;        
    }    
    .hello{
        font-weight:bold;
    }
    .box-item{
        width:auto;
        margin-left:32px;
    }
    .box-item span{
        display:block;
        height:28px;
        line-height:28px;
        color:#b0b0b0;
    }
    .box-item span a{
        color:#999;
    }
    .box-item span a:hover{
        color:#666;
    }    
</style>
</head>
<body>
<div class="main-box">
    <div>您好,</div>
    <div class="box-item">
        /**content**/        
        <br/>系统链接:<a href="http://ip:8080/login">*******系统</a>    
        <br/>如有任何问题,可咨询:***@163.com        
    </div>
    <div class="hello">
        ------------------------------------------------------------------
        <br/>本邮件为系统自动发出,不必回复。
        <br/>This email is automatically sent out, no need to reply.
    </div>
</div>
</body>
</html>