如何用java发送包含表格形式的邮件

问题:
如何用java发送包含表格形式的邮件?
方法:
发用freemaker工具来替换html的表格变量,从而动态生成了html。然后再发送这个html格式(不能用纯文本)文本即可。
优化流程:
1、准备模板(这里是以Excel转html为模板)

2、处理模板及对模板填充内容的工具类

3、修改发送邮件的代码
所需依赖
pom.xml依赖

 
<!-- freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.4</version>
</dependency>

具体实现
1、准备模板
先用excel画一个模板,如下图
在这里插入图片描述
然后在网上找一个excel转换html的在线转换工具
我用的是:零代码 - Table在线布局工具(Excel转HTML)
2. 转换成功之后下载,之后会得到这样一个html文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>www.lingdaima.com(零代码excel转HTML)</title>
    <style>
table{border-top:1px solid #333;border-left:1px solid #333;border-spacing:0;background-color:#fff;width:100%}
table td{border-bottom:1px solid #333;border-right:1px solid #333;font-size:13px;padding:5px}
.font5{color:windowtext;}
.xl65{text-align:left ;}
</style>
</head>
<body>
    <table style="width:500pt"> <!--StartFragment--> 
 <colgroup>
  <col width="111" style="mso-width-source:userset;mso-width-alt:3552;width:83pt"> 
  <col width="131" style="mso-width-source:userset;mso-width-alt:4192;width:98pt"> 
  <col width="290" style="mso-width-source:userset;mso-width-alt:9280;width:218pt"> 
  <col width="135" style="mso-width-source:userset;mso-width-alt:4320;width:101pt"> 
 </colgroup>
 <tbody>
  <tr height="19"> 
   <td class="xl65">号码</td> 
   <td class="xl65">所属运营商</td> 
   <td class="xl65">所属号码组</td> 
   <td class="xl65">报警时间</td> 
  </tr> 
  <tr height="19"> 
   <td class="xl65">15528474394</td> 
   <td class="xl65">万事融通</td> 
   <td class="xl65">智慧外呼_万事融通_日产专用_品牌认证</td> 
   <td class="xl65">2024/10/24 9:35</td> 
  </tr> <!--EndFragment--> 
 </tbody>
</table>
</body>
</html>

3.把这个文件修改为 alert-email-template.ftl, 放到 java 项目的 resouce/ftl/目录下
该文件的内容为

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
table{border-top:1px solid #333;border-left:1px solid #333;border-spacing:0;background-color:#fff;width:100%}
table td{border-bottom:1px solid #333;border-right:1px solid #333;font-size:13px;padding:5px}
.font5{color:windowtext;}
.xl65{text-align:left ;}
</style>
</head>
<body>
<div style="font-size: 12px; margin: 10px;">
    您好:<br/>
    &nbsp &nbsp &nbsp 本次共有${totalAmounts}个未接通号码,详情请参见附件。
    <br/>
    下面列出的是前${topAmounts}个未接通号码详细信息。
    <br/>
</div>
    <table style="width:500pt"> <!--StartFragment-->
 <colgroup>
  <col width="111" style="mso-width-source:userset;mso-width-alt:3552;width:83pt">
  <col width="131" style="mso-width-source:userset;mso-width-alt:4192;width:98pt">
  <col width="290" style="mso-width-source:userset;mso-width-alt:9280;width:218pt">
  <col width="135" style="mso-width-source:userset;mso-width-alt:4320;width:101pt">
 </colgroup>
 <tbody>
  <tr height="19">
   <td class="xl65">号码</td>
   <td class="xl65">所属运营商</td>
   <td class="xl65">所属号码组</td>
   <td class="xl65">报警时间</td>
  </tr>
  <#if items?? && (items? size >0)>
  <#list items as item>
  <tr height="18">
   <td class="xl66">${(item.phone)!}</td>
   <td class="xl66">${(item.supplier)!}</td>
   <td class="xl66">${(item.group)!}</td>
   <td class="xl66">${(item.time)!}</td>
  </tr>
  </#list>
 </#if>
 </tbody>
</table>
</body>
</html>

这里带$的就是需要freemaker来替换的变量。
注:这里items是一个list变量。

  1. 处理模板及对模板填充内容的工具类
    直接上java代码
@Data
public class FailedCallInfo {
    private String phone;
    private String supplier;
    private String group;
    private String time;
}
List<FailedCallInfo> items = new ArrayList<>();
 FailedCallInfo record = new FailedCallInfo();
 record.setPhone("123456");
 record.setSupplier("abc");
 record.setGroup("group1");
 record.setTime("2024-10-10 12:12:00");
 items.add(record);
 Map<String, Object> callInfoMap = new HashMap<>(32);
 //注意变量名字要和ftl模板里面的一致!
 callInfoMap.put("items", items);
 callInfoMap.put("totalAmounts", 1);
 callInfoMap.put("topAmounts", 1);
  String generatedEmailBodyText = null;
        try {
            generatedEmailBodyText = FreemarkerUtil.generate("alert-email-template.ftl", callInfoMap);
        } catch (IOException e) {
            log.warn("email template generation failed, IOException exception:{}", e.getMessage());
            csvfile.delete();
            return;
        } catch (TemplateException e) {
            log.warn("email template generation failed, TemplateException exception:{}", e.getMessage());
            csvfile.delete();
            return;
        }
        boolean send_result = EmailHelper.send(receivers, null, null, "未接通号码告警邮件", generatedEmailBodyText, attachment, "xc-jsb-sjjg-unit@autohome.com.cn");
        if (send_result) {
            log.info("发送告警邮件成功!收件人:{}", JSON.toJSONString(receivers));
        } else {
            log.warn("发送告警邮件失败,收件人:{}", JSON.toJSONString(receivers));
        }

FreemarkerUtil.java

package com.xxx.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;

/**
 * freemarker 工具类
 */
public class FreemarkerUtil {

    private static Configuration config = null;

    /**
     * Static initialization.
     *
     * Initialize the configuration of Freemarker.
     */
    static {
        config = new Configuration();
        config.setClassForTemplateLoading(FreemarkerUtil.class, "/ftl/");
        config.setTemplateUpdateDelay(0);
    }

    public static Configuration getConfiguration() {
        return config;
    }

    /**
     * @param template
     * @return
     * @throws Exception
     */
    public static String generate(String template, Object obj) throws IOException, TemplateException {
        Configuration config = getConfiguration();
        config.setDefaultEncoding("UTF-8");
        Template tp = config.getTemplate(template, "utf-8");
        StringWriter stringWriter = new StringWriter();
        BufferedWriter writer = new BufferedWriter(stringWriter);
        tp.setEncoding("UTF-8");
        tp.process(obj, writer);
        String htmlStr = stringWriter.toString();
        writer.flush();
        writer.close();
        return htmlStr;
    }

}

EmailHelper.java

package com.xxx.util;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

@Slf4j
public class EmailHelper {
    private static final String DEFAULT_SMTP_HOST = "12.12.12.12";
    private static final Integer DEFAULT_SMTP_PORT = 25;
    private static final String DEFAULT_MAIL_SENDER = "test@aby.com.cn";

    /**
     * 邮件发送
     *
     * @param to      收件人邮件地址列表
     * @param subject 邮件标题
     * @param content 邮件内容
     * @return 发送结果
     */
    public static boolean send(List<String> to, String subject, String content) {
        return send(to, null, null, subject, content, null);
    }

    /**
     * 邮件发送
     *
     * @param to          收件人邮件地址列表
     * @param subject     邮件标题
     * @param content     邮件内容
     * @param attachments 附件
     * @return 发送结果
     */
    public static boolean send(List<String> to, String subject, String content, List<File> attachments) {
        return send(to, null, null, subject, content, attachments);
    }

    /**
     * 邮件发送
     *
     * @param to          收件人邮件地址列表
     * @param cc          抄送人邮件地址列表
     * @param subject     邮件标题
     * @param content     邮件内容
     * @param attachments 附件
     * @return 发送结果
     */
    public static boolean send(List<String> to, List<String> cc, String subject, String content, List<File> attachments) {
        return send(to, cc, null, subject, content, attachments);
    }

    /**
     * 邮件发送
     *
     * @param to          收件人邮件地址列表
     * @param cc          抄送人邮件地址列表
     * @param bcc         密送人邮件地址列表
     * @param subject     邮件标题
     * @param content     邮件内容
     * @param attachments 附件
     * @param sender 发件人
     * @return 发送结果
     */
    public static boolean send(List<String> to, List<String> cc, List<String> bcc,
                               String subject, String content, List<File> attachments,String sender) {
        return send(DEFAULT_SMTP_HOST, DEFAULT_SMTP_PORT, sender, null, to, cc, bcc, subject, content, attachments);
    }

    /**
     * 邮件发送
     *
     * @param to          收件人邮件地址列表
     * @param cc          抄送人邮件地址列表
     * @param bcc         密送人邮件地址列表
     * @param subject     邮件标题
     * @param content     邮件内容
     * @param attachments 附件
     * @return 发送结果
     */
    public static boolean send(List<String> to, List<String> cc, List<String> bcc,
                               String subject, String content, List<File> attachments) {
        return send(DEFAULT_SMTP_HOST, DEFAULT_SMTP_PORT, DEFAULT_MAIL_SENDER, null, to, cc, bcc, subject, content, attachments);
    }

    /**
     * 邮件发送
     *
     * @param smtpHost       smtp服务地址
     * @param smtpPort       smtp服务端口
     * @param sender         发送人邮箱地址
     * @param senderPassword 发送人邮箱密码
     * @param to             收件人邮件地址列表
     * @param cc             抄送人邮件地址列表
     * @param bcc            密送人邮件地址列表
     * @param subject        邮件标题
     * @param content        邮件内容
     * @param attachments    附件
     * @return 发送结果
     */
    public static boolean send(String smtpHost, Integer smtpPort, String sender, String senderPassword,
                               List<String> to, List<String> cc, List<String> bcc,
                               String subject, String content, List<File> attachments) {
        MimeMessage message = getMimeMessage(smtpHost, smtpPort, sender, senderPassword);
        try {
            // 收件人
            List<InternetAddress> toInternetAddressList = convertToInternetAddress(to);
            if (CollectionUtils.isEmpty(toInternetAddressList)) {
                log.error("邮件收件人不能为空");
                return false;
            }
            message.addRecipients(Message.RecipientType.TO, toInternetAddressList.toArray(new InternetAddress[0]));

            // 抄送人
            List<InternetAddress> ccInternetAddressList = convertToInternetAddress(cc);
            if (!CollectionUtils.isEmpty(ccInternetAddressList)) {
                message.addRecipients(Message.RecipientType.CC, ccInternetAddressList.toArray(new InternetAddress[0]));
            }

            // 密送人
            List<InternetAddress> bccInternetAddressList = convertToInternetAddress(bcc);
            if (!CollectionUtils.isEmpty(bccInternetAddressList)) {
                message.addRecipients(Message.RecipientType.BCC, bccInternetAddressList.toArray(new InternetAddress[0]));
            }

            // 内容
            Multipart multipart = new MimeMultipart();
            MimeBodyPart contentPart = new MimeBodyPart();
            contentPart.setContent(content, "text/html;charset=utf-8");
            multipart.addBodyPart(contentPart);

            // 附件
            if (!CollectionUtils.isEmpty(attachments)) {
                attachments.forEach(file -> {
                    try {
                        MimeBodyPart filePartBody = new MimeBodyPart();
                        DataSource fileDataSource = new FileDataSource(file);
                        DataHandler dataHandler = new DataHandler(fileDataSource);
                        filePartBody.setDataHandler(dataHandler);
                        filePartBody.setFileName(MimeUtility.encodeText(file.getName()));
                        multipart.addBodyPart(filePartBody);
                    } catch (Exception e) {
                        log.error("邮件中的附件失败,已经丢弃该附件:{}", file.getName());
                    }
                });
            }

            message.setContent(multipart);
            message.setFrom(new InternetAddress(sender));

            String mailSubject = StringUtils.isNotBlank(subject) ? subject : "无主题";
            String activeProfile = System.getProperty("spring.profiles.active");
            if (StringUtils.isNotBlank(activeProfile) && !activeProfile.contains("online")) {
                mailSubject += String.format(" 【环境: %s】", activeProfile);
            }
            message.setSubject(mailSubject, "UTF-8");
            message.saveChanges();
            Transport.send(message);
            return true;
        } catch (MessagingException ex) {
            log.error("error when send email.", ex);
            return false;
        }
    }

    private static MimeMessage getMimeMessage(String smtpHost, Integer smtpPort, String sender, String senderPassword) {
        Properties properties = new Properties();
        properties.put("mail.transport.protocol", "smtp");
        properties.put("mail.smtp.host", smtpHost);
        properties.put("mail.smtp.port", smtpPort);
        Authenticator authenticator = null;
        if (StringUtils.isNotBlank(sender) && StringUtils.isNotBlank(senderPassword)) {
            authenticator = new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(sender, senderPassword);
                }
            };
        }
        properties.put("mail.smtp.auth", authenticator != null ? "true" : "false");
        Session session = Session.getDefaultInstance(properties, authenticator);
        return new MimeMessage(session);
    }

    private static List<InternetAddress> convertToInternetAddress(List<String> mailAddressList) {
        if (CollectionUtils.isEmpty(mailAddressList)) {
            return new ArrayList<>();
        }

        List<InternetAddress> mailInternetAddress = new ArrayList<>();
        mailAddressList.forEach(item -> {
            try {
                mailInternetAddress.add(new InternetAddress(item));
            } catch (AddressException e) {
                log.error("邮件地址错误,此邮件地址不参与邮件的接收:{}", item);
            }
        });

        return mailInternetAddress;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值