基于JavaMailSenderImpl和velocity模板的邮件发送

Java邮箱集成发送, 本文介绍了基于JavaMailSenderImpl和velocity模板引擎,发送自定义的邮件内容。

一、依赖引入

java 复制代码
<dependency>
    <groupId>com.crygier</groupId>
    <artifactId>SpringUtils</artifactId>
    <version>1.0.1</version>
    <scope>compile</scope>
</dependency>
java 复制代码
<!--邮件服务-->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>com.crygier</groupId>
    <artifactId>SpringUtils</artifactId>
    <version>1.0.1</version>
    <scope>compile</scope>
</dependency>

二、邮箱发送工具类(javaMailSenderImpl)

SysEmailServiceProvider.java

java 复制代码
@Component
@Scope(value = "singleton")
public class SysEmailServiceProvider {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IFactoryEmailManageService factoryEmailManageService;
    /**
     * 系统邮箱发送服务实例,单例模式下使用到时再去加载
     */
    private volatile JavaMailSenderImpl javaMailSender;

    /**
     * 双重检测机制懒汉式单例模式,防止多线程下多次实例化对象
     *
     * @return
     */
    public JavaMailSenderImpl getJavaMailSender() {
        if (javaMailSender == null) {
            // 在代码块上加锁,比直接在方法上加锁效率高,因为锁的范围小了
            synchronized (SysEmailServiceProvider.class) {
                if (javaMailSender == null) {
                    // 从数据库查询邮件发送服务器配置
                    FactoryEmailManage sysEmail = factoryEmailManageService.selectFactoryEmailManageById(1L);
                    // 实例化对象
                    javaMailSender = buildJavaMailSenderBySysEmail(sysEmail);
                }
            }
        }
        return javaMailSender;
    }

    /**
     * 清除当前的邮件发送对象(一般用于修改系统邮箱发送服务时)
     */
    public void clearJavaMailSender() {
        // 直接赋值为null,用的时候再实例化
        javaMailSender = null;
    }

    /**
     * 根据邮件服务配置对象生成邮件发送实例对象
     *
     * @param email
     * @return
     */
    public JavaMailSenderImpl buildJavaMailSenderBySysEmail(FactoryEmailManage email) {
        if (email == null) {
            logger.warn("邮件发送服务配置为null,无法实例化对象");
            return null;
        }
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        try {
            javaMailSender.setHost(email.getEmailHost());
            javaMailSender.setUsername(email.getEmailName());
            javaMailSender.setPassword(RsaUtils.decryptByPrivateKey(email.getEmailPassword()));
            javaMailSender.setPort(email.getEmailPort());
            javaMailSender.setProtocol(email.getEmailProtocol());
            javaMailSender.setDefaultEncoding("utf-8");
        } catch (Exception e) {
            logger.error("实例化邮件发送对象失败,失败原因:{}", e.getMessage());
        }
        return javaMailSender;
    }

    /**
     * 邮件接收服务实例对象(不涉及多线程调用)
     */
    private Store store;

    /**
     * 简单懒汉式单例模式,因为这个对象不涉及到多线程调用
     *
     * @return
     */
    public Store getStore() throws Exception {
        if (store == null) {
            // 从数据库查询邮件发送服务器配置
            FactoryEmailManage sysEmail = factoryEmailManageService.selectFactoryEmailManageById((long) 1);
            store = buildStoreBySysEmail(sysEmail);
        }
        return store;
    }

    /**
     * 清除当前的邮件接收对象(一般用于修改系统邮箱接收服务时)
     */
    public void clearStore() {
        // 直接赋值为null,用的时候再实例化
        store = null;
    }


    /**
     * 根据邮件服务配置对象生成邮件接收实例对象
     *
     * @param email
     * @return
     */
    public Store buildStoreBySysEmail(FactoryEmailManage email) throws Exception {
        if (email == null) {
            logger.warn("邮件接收服务配置为null,无法实例化对象");
            return null;
        }
        Properties props = System.getProperties();
        if ("pop3s".equals(email.getEmailProtocol())) {
            props.setProperty("mail.pop3s.host", email.getEmailHost());
            props.setProperty("mail.pop3s.port", email.getEmailPort().toString());
            props.setProperty("mail.pop3s.auth", "true");
            props.setProperty("mail.pop3s.socketFactory.class",
                    "javax.net.ssl.SSLSocketFactory");
            props.setProperty("mail.pop3s.ssl.trust", "*");
        } else if ("pop3".equals(email.getEmailProtocol())) {
            props.setProperty("mail.pop3.host", email.getEmailHost());
            props.setProperty("mail.pop3.port", email.getEmailPort().toString());
        } else {
            throw new Exception("邮件接收服务器暂不支持pop3以及pop3s之外的协议");
        }
        Session session = Session.getDefaultInstance(props, null);
        Store store = null;
        try {
            store = session.getStore(email.getEmailProtocol());
        } catch (NoSuchProviderException e) {
            logger.error(e.getMessage(), e);
            throw new Exception(e.getMessage());
        } finally {
            return store;
        }
    }


}

三、邮箱发送工具类(自定义内容)

样式调整、发件人、收件人、内容、主题等自定义设置,本文加上了图片和模板内容。

java 复制代码
@Component
public class EmailSendUtils {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IFactoryEmailManageService factoryEmailManageService;
    @Autowired
    private SysEmailServiceProvider sysEmailServiceProvider;


    public void sendEmailAssignManage(Map<String, Object> addresseeMap, String content) throws Exception {

        try {
            JavaMailSenderImpl javaMailSender = sysEmailServiceProvider.getJavaMailSender();
            
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
            mimeMessageHelper.setFrom(javaMailSender.getUsername());
            if(addresseeMap.get("toReceiverGroup")!=null){ //收件人设置
                mimeMessageHelper.setTo((String[]) addresseeMap.get("toReceiverGroup"));
            }else if(addresseeMap.get("toReceiver")!=null){
                mimeMessageHelper.setTo(new String[]{addresseeMap.get("toReceiver").toString()});
            }
            //邮件主题
            mimeMessageHelper.setSubject(addresseeMap.get("emailSubject").toString());
            //邮件内容
            mimeMessageHelper.setText(content, true);
             //邮件内容-图片
            if(addresseeMap.get("logopng")!=null){
                mimeMessageHelper.addInline("logo", (ClassPathResource)addresseeMap.get("logopng"));
            }
            if(addresseeMap.get("topbackground")!=null){
                mimeMessageHelper.addInline("topbackground", (ClassPathResource)addresseeMap.get("topbackground"));
            }
            javaMailSender.send(mimeMessage);
        } catch (MailAuthenticationException e) {
            logger.error(e.getMessage(), e);
            logger.error("邮箱用户名或密码不正确");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            logger.error("发送邮件失败,请检查邮箱配置");

        }
    }

}

四、邮箱发送

1、velocity模板内容设置

java 复制代码
        SimpleDateFormat formatterDay = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        StringWriter sw = new StringWriter();
        VelocityContext context = new VelocityContext();
/内容设置
       

        context.put("warningType", "一次直通率预警");
        context.put("caId", "S01");
        context.put("content", factoryWarning.getContent());
        context.put("responsibility", "责任人name");
        context.put("happenTime", formatterDay.format(factoryWarning.getHappenTime()));
        context.put("currentTime", formatterDay.format(new Date()));

        Template template = Velocity.getTemplate("vm/warningSingleEmail.vm");
        template.merge(context, sw);
        String mailText = sw.toString();

2、velocity模板

warningSingleEmail.vm

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body style="font-size: 14px ;width: 100%;height: 100%;">

<div style="background: #EEE;width: 90%; height: 100%;margin:0px auto;">
    <div style="max-width: 680px;width: 680px;margin:0px auto;">
        <table align="center" border="0" cellpadding="0" cellspacing="0"
               style='background: rgb(255, 255, 255); width: 680px; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, Arial, sans-serif; border: none; border-collapse: collapse; max-width: 680px; margin: 0; auto; empty-cells: show;'>
            <tbody>
            <tr style="user-select: none;">
                <td align="center"
                    style="width: 680px; padding: 0px; text-align: center; min-width: 5px;  user-select: text;">
                    <img
                            alt="top-background" width="680"
                            src="cid:topbackground"
                            style="width: 680px; max-width: 100%;height: 150px; cursor: pointer;"
                            >
##                    <p style="position: absolute;left: 35%; top: 1%;color: white; font-size: 3rem; font-weight:bolder; font-family: fantasy">预警系统提醒</p>
            </tr>
            </tbody>
        </table>
        <table align="center" border="0" cellpadding="0" cellspacing="0"
               style='background: rgb(239, 249, 254); width: 680px; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, Arial, sans-serif; border: none; border-collapse: collapse; max-width: 680px; margin: 0px; empty-cells: show;'>
            <tbody>
            <tr style="background: rgb(239, 249, 254); user-select: none;">
                <td style="background: rgb(239, 249, 254); width: 40px; color: rgb(160, 160, 160); line-height: 1.6; padding: 10px 0px; font-size: 14px; min-width: 5px;  user-select: text;">
                    &nbsp;
                </td>
                <td style="background: rgb(239, 249, 254); max-width: 600px;height: 500px; width: 600px; color: rgb(160, 160, 160); line-height: 1.6; padding: 10px 0px; font-size: 14px; min-width: 5px; user-select: text; text-align: left;">
                    <p style="text-align: left;"><span style="color: rgb(71, 85, 119);">尊敬的用户:</span></p>
                    <p><span style="color: rgb(71, 85, 119);">&nbsp; &nbsp; &nbsp; &nbsp;您有新的${warningType}产生,请及时处理!</span>
                    </p>
                    <p><span style="color: rgb(71, 85, 119);"><br></span></p>
                    <p><span style="color: rgb(71, 85, 119);">以下为本次预警的主要信息:</span></p>
                    <p><span style="color: rgb(71, 85, 119);"><b>预警类别:</b>${warningType}</span></p>
                    #if(${caId})
                        <p><span style="color: rgb(71, 85, 119);"><b>线别:</b>${caId}</span></p>
                    #end
                    <p><span style="color: rgb(71, 85, 119);"><b>描述:</b>${content}</span></p>
                    <p><span style="color: rgb(71, 85, 119);"><b>责任人:</b>${responsibility}</span></p>
                    <p><span style="color: rgb(71, 85, 119);"><b>发生时间:</b>${happenTime}</span></p>
                    <div style="float: right;font-size: 16px;font-weight: bold;margin-top: 20px">${currentTime}</div>
                </td>
                <td style="background: rgb(239, 249, 254); width: 40px; color: rgb(160, 160, 160); line-height: 1.6; padding: 10px 0px; font-size: 14px; min-width: 5px;  user-select: text;">
                    <br></td>
            </tr>
            </tbody>
        </table>
        <table align="center" border="0" cellpadding="0" cellspacing="0"
               style='background: rgb(255, 255, 255); width: 680px; height: 150px;font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, Arial, sans-serif; border: none; border-collapse: collapse; max-width: 680px; margin: 0px auto; empty-cells: show;'>
            <tbody>
            <tr style="user-select: none;">
                <td align="center"
                    style="width: 680px; padding: 0px; text-align: center; min-width: 5px; height: 150px; user-select: text;">
                    <img
                            alt="lbs-foot" width="680"
                            src="cid:logo"
                            style="width: 680px; max-width: 40%; min-height: 50%;cursor: pointer;"
                            />
            </tr>
            </tbody>
        </table>

    </div>
</div>
</body>
</html>

3、收发件人和主题等设置

java 复制代码
            Map<String, Object> content = new HashMap<>();
            //设置收件人邮箱
//            content.put("toReceiver", "**@163.com");
            //设置收件人邮箱-多人群组
                String receiversEmail[] = ["**@163.com","**@126.com"];
                content.put("toReceiverGroup", receiversEmail);
            //设置邮件主题
            content.put("emailSubject", "预警系统:您有新的预警产生!");
            ClassPathResource logoPng = new ClassPathResource("vm/warning-logo.png");//从本地文件夹中获取所需图片
            content.put("logopng",logoPng);
            ClassPathResource topbackground = new ClassPathResource("vm/warning-top.png");//从本地文件夹中获取所需图片
            content.put("topbackground",topbackground);

4、发送邮件调用

java 复制代码
//发送邮件
emailSendUtils.sendEmailAssignManage(content, mailText);

五、效果

相关推荐
只因在人海中多看了你一眼1 分钟前
python语言基础
开发语言·python
2401_858286113 分钟前
101.【C语言】数据结构之二叉树的堆实现(顺序结构) 下
c语言·开发语言·数据结构·算法·
y25084 分钟前
《Object类》
java·开发语言
小技与小术8 分钟前
数据结构之树与二叉树
开发语言·数据结构·python
旭日猎鹰26 分钟前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
hccee30 分钟前
C# IO文件操作
开发语言·c#
hummhumm34 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
J老熊44 分钟前
JavaFX:简介、使用场景、常见问题及对比其他框架分析
java·开发语言·后端·面试·系统架构·软件工程
zmd-zk1 小时前
flink学习(2)——wordcount案例
大数据·开发语言·学习·flink
好奇的菜鸟1 小时前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang