有关Java发送邮件信息(支持附件、html文件模板发送)
最近在做扫码开票的需求,有个功能是需要开票成功之后通过邮件或者手机号的方式通知开票方,看了一下市面上的邮件发送费用,再结合客户的开票数量,果断放弃,于是只好自己开发免费不要钱的模板,怎么做呢,看下面:
1、引入依赖
<!--邮件发送--> <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
2、编写工具类
package com.ruoyi.common.utils; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.URLDataSource; import javax.mail.*; 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; /** * @author :yanjun.hou * @description : 邮件工具类(包含发送附件 和html模板) * @create :2022-09-16 09:09:00 */ public class SendMailUtil { /** * @param subject 主题 * @param content 内容 * @param htmlContent 邮件html内容 * @param email 收件人 * @param attachmentUrl 附件路径--需要是网络地址 * @param fileName 文件名称 * @throws Exception */ public static String sendMail(String subject, String content, String htmlContent, String email, String attachmentUrl, String fileName) { try { //设置不是草稿 int draft = 0; //普通邮件 优先级(1:紧急 3:普通 5:低) int priority = 3; //是否需要回执 默认是0,不需要回执 int receiptFlag = 0; Properties props = new Properties(); String host = "smtp.yeah.net"; props.setProperty("mail.transport.protocol", "smtp"); props.setProperty("mail.smtp.host", host); props.setProperty("mail.smtp.port", "465"); props.setProperty("mail.smtp.auth", "true"); props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.setProperty("mail.smtp.socketFactory.fallback", "false"); //设置了附件名过长问题,从而导致附件名显示带bin的错误,造成附件异常 System.setProperty("mail.mime.splitlongparameters", "false"); Session session = Session.getDefaultInstance(props); //发件人邮箱 String from = "xxx@yeah.net"; String passWord = "xxx"; Message message = new MimeMessage(session); message.setSentDate(new Date()); // 设置发件人地址 ((MimeMessage) message).setFrom("hyj<xxx@yeah.net>"); // 设置主题 message.setSubject(subject); // 设置收件人 message.addRecipients(Message.RecipientType.TO, InternetAddress.parse(MimeUtility.encodeText(email))); // 设置抄送人 message.addRecipients(Message.RecipientType.CC, InternetAddress.parse(MimeUtility.encodeText("")));//选填 // 设置密送人 message.addRecipients(Message.RecipientType.BCC, InternetAddress.parse(MimeUtility.encodeText("")));//选填 // 如果是草稿 if (draft == 1) { message.setFlag(Flags.Flag.DRAFT, true); } // 设置优先级(1:紧急 3:普通 5:低) if (priority == 1) { message.setHeader("X-Priority", "1"); } // 如果receiptFlag=1 代表需要回执 if (receiptFlag == 1) { message.setHeader("Disposition-Notification-To", from); } /** * 设置邮件内容 */ Multipart multipart = new MimeMultipart(); MimeBodyPart txtPart = new MimeBodyPart(); txtPart.setContent(content, "text/html;charset=utf-8"); multipart.addBodyPart(txtPart); MimeBodyPart part = new MimeBodyPart(); /** * 附件 */ if (StringUtils.isNotEmpty(attachmentUrl)) { URL url = new URL(attachmentUrl); DataSource dataSource = new URLDataSource(url); part.setDataHandler(new DataHandler(dataSource)); } part.setFileName(MimeUtility.encodeText(fileName)); /** * 支持html内容 */ MimeBodyPart html = new MimeBodyPart(); html.setContent(htmlContent, "text/html;charset=utf-8"); multipart.addBodyPart(html); multipart.addBodyPart(part); message.setContent(multipart); message.setFlag(Flags.Flag.RECENT, true); message.saveChanges(); /** * 不是草稿的情况下进行发送 */ if (draft == 0) { Transport transport = session.getTransport("smtp"); transport.connect(host, from, passWord); transport.sendMessage(message, message.getAllRecipients()); transport.close(); } return "success"; } catch (Exception e) { return null; } } public static void main(String[] args) { try { String s = sendMail("您有1张电子发票", "测试电子发票", "<h1>测试html</h1>", "xxx@qq.com", "https://xxx.pdf", "电子发票.pdf"); } catch (Exception e) { e.printStackTrace(); } } }
3、编写邮件html模板
//该模板构建完成之后 需要放到资源目录下,后续使用InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("模板文件名称");读取 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="description" content="xxxx"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <!--扫码开票成功邮件通知模板--> <body> <div style="background-color:#ECECEC; padding: 35px;"> <table cellpadding="0" align="center" style="width: 800px;height: 100%; margin: 0px auto; text-align: left; position: relative; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; font-size: 14px; font-family:微软雅黑, 黑体; line-height: 1.5; box-shadow: rgb(153, 153, 153) 0px 0px 5px; border-collapse: collapse; background-position: initial initial; background-repeat: initial initial;background:#fff;"> <tbody> <tr> <th valign="middle" style="height: 25px; line-height: 25px; padding: 15px 35px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #42a3d3; background-color: #49bcff; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px;"> <font face="微软雅黑" size="5" style="color: rgb(255, 255, 255); ">发票信息</font> </th> </tr> <tr> <td style="word-break:break-all"> <div> <p style="margin-left: 4%;margin-top: 5%;">尊敬的客户您好!</p> <p style="margin-left: 4%;">您于{3}消费并开具了电子发票,发票信息如下:</p> <p></p> </div> <div style="padding:25px 35px 40px; background-color:#fff;"> <h2 style="margin: 5px 0px; text-align:center;"> <font color="#333333" style="line-height: 20px; "> <font style="line-height: 22px; " size="4"> 电子发票信息</font> </font> </h2> <!-- 使用占位数字 对应动态渲染数据信息--> <p>购方名称:{0}</p> <p>发票代码:{1}</p> <p>发票号码:{2}</p> <p>开票日期:{3}</p> <p>合计金额:{4}</p> <p>发票链接:{5}</p><br> <div style="width:700px;margin:0 auto;"> <div style="padding:10px 10px 0;border-top:1px solid #ccc;color:#747474;margin-bottom:20px;line-height:1.3em;font-size:12px;"> <p style="font-weight: bold;font-size: 15px;">温馨提醒:</p> <p>灵税通电子发票为您提供便捷的发票服务,欢迎访问官网,选择您需要的发票解决方案https://xxx.com 此电子发票由灵税通发票助手交付。</p><br> <p>此为系统邮件,请勿回复<br> Please do not reply to this system email </p> </div> </div> </div> </td> </tr> </tbody> </table> </div> </body> </html>
4、构建邮件模板,动态传参
/** * 构建邮件模板信息 * * @param htmlPath email模板文件路径 * @param buyerName * @param invoiceCode * @param invoiceNo * @param invoiceDate * @param totalAmount * @param pdfUrl * @param failCause 失败原因 * @param orderNo 订单编号 * @return */ public String buildContent(String htmlPath, String buyerName, String invoiceCode, String invoiceNo, String invoiceDate, String totalAmount, String pdfUrl, String failCause, String orderNo) { //获取文件路径 InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(htmlPath); BufferedReader fileReader = null; StringBuffer buffer = new StringBuffer(); String line = ""; try { fileReader = new BufferedReader(new InputStreamReader(inputStream)); while ((line = fileReader.readLine()) != null) { buffer.append(line); } } catch (Exception e) { logger.error(String.format("发送邮件读取模板失败,错误堆栈信息:%s", e.getMessage())); } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } //使用动态参数替换html模板中的占位符参数 String htmlText = MessageFormat.format(buffer.toString(), buyerName, invoiceCode, invoiceNo, invoiceDate, totalAmount, pdfUrl, failCause, orderNo); return htmlText; }
5、测试
/** * 免费邮件模板成功通知 * * @param history * @param email * @param buyerName */ private void KLsendEmail_SuccessForFree(OutputBaseInvoiceHistory history, String email, String buyerName) { StringBuilder subBuilder = new StringBuilder(); subBuilder.append("您收到一张【").append(history.getSaleName()).append("】开具的发票【发票号码:").append(history.getInvoiceNo()).append("】"); String formatDate = sdf.format(new Date()); try { // MailUtil.send() 这个方式只能传入本地File,无法传入网络资源 所以转换pdf为本地地址 String localPdfUrl = outPutFileToLocalUtiils.downParsePdf(history.getPdfUrl()); //获取对应的邮件html模板信息 String htmlInfo = buildContent("scanCodeSuccessEmail.html", buyerName, history.getInvoiceCode(), history.getInvoiceNo(), formatDate, history.getOrderAmount(), localPdfUrl, "", ""); // String send = MailUtil.send(email, subBuilder.toString(), htmlInfo, true, FileUtil.file(localPdfUrl)); String send = SendMailUtil.sendMail(subBuilder.toString(), "", htmlInfo, email, history.getPdfUrl(), "电子发票.pdf"); if (StringUtils.isNotEmpty(send)) { logger.info(LogUtils.formatLog("outputSuMailRequest", "sendInfoFromKaiLingSystemForFree", "KLsendEmail_SuccessForFree", email, String.format("扫码开票发送邮件通知成功:接收者对应邮箱:%s", email))); } } catch (Exception e) { logger.info(String.format("扫码开票发送邮件信息出现异常!异常信息:%s,对应pdf地址:%s", e.getMessage(), history.getPdfUrl())); } }
6、效果