最近,在开发工作中有这么的需求,使用模板技术加javax mail发送模板邮件,经历的一系列的蛋疼时刻终于搞定,在这里做下总结,以备以后在遇到类似问题,方便查找。
使用VelocityEngine + Spring完成模板解析,VelocityTemplateMailProcessor.java:
/** * 处理velocity邮件模板,将template中参数替换为真实值 * * @author Arthur * */ public class VelocityTemplateMailProcessor implements TemplateMailProcessor { private final static Logger LOGGER = Logger .getLogger(VelocityTemplateMailProcessor.class); /** * 使用velocity模板引擎处理邮件模板,支持在velocity等模板文件中对时间和数字进行格式化支持 * * @param templateLocation * 邮件模板路径:例如在src/main/resoures下有一个example.tpl文件, * 则起对应的tamplateLocation为example.tpl * @param charsetEncoding * 读取邮件模板使用的charset * @param attributeMap * 模板中对应占位符的值map * @return */ public String process(String templateLocation, String charsetEncoding, Map<String, Object> attributeMap) { // First, volidate attributeMap, make sure "dateTool" & "numberTool" not // used by application this.validate(attributeMap); try { Properties prop = new Properties(); prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); // 增加date和number格式化支持 try { VelocityTemplateMailProcessor.class.getClassLoader().loadClass( "org.apache.velocity.tools.generic.DateTool"); LOGGER.info("DateTool 'org.apache.velocity.tools.generic.DateTool' found in classpath and support date format"); DateTool dateTool = new DateTool(); attributeMap.put("dateTool", dateTool); } catch (ClassNotFoundException e) { // not exist, just skip } try { VelocityTemplateMailProcessor.class.getClassLoader().loadClass( "org.apache.velocity.tools.generic.NumberTool"); LOGGER.info("NumberTool 'org.apache.velocity.tools.generic.NumberTool' found in classpath and support numberic format"); NumberTool numberTool = new NumberTool(); attributeMap.put("numberTool", numberTool); } catch (ClassNotFoundException e) { // not exist, just skip } VelocityEngineFactoryBean factoryBean = new VelocityEngineFactoryBean(); factoryBean.setVelocityProperties(prop); VelocityEngine velocityEngine = factoryBean.createVelocityEngine(); LOGGER.debug("VelocityEngine initialization is ok"); return VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templateLocation, charsetEncoding, attributeMap); } catch (Exception e) { LOGGER.error("use VelocityEngine to process mail template[" + "templateLocation" + "] error", e); throw new ParseTemplateException(e); } } private void validate(Map<String, Object> attributeMap) { if (attributeMap.get("dateTool") != null) { throw new IllegalArgumentException( "dateTool is reserved field not for application, Please make sure it's not used"); } if (attributeMap.get("numberTool") != null) { throw new IllegalArgumentException( "numberTool is reserved field not for application, Please make sure it's not used"); } } }
ok,使用该类完成邮件模板的解析工作,接着发送邮件,邮件发送类这里就不贴出来了;
使用javax mail发送邮件时最容易遇到的问题就是邮件内容和标题的乱码,对于内容乱码,相信很多人都遇到过,也都知道怎么解决。
至于标题乱码有点棘手,需要对邮件title进行Base64编码,防止邮件标题中文乱码,但是这里就需要对使用哪个Base64实现类进行选择,
不幸的是开始楼主选择了Sun的sun.misc.BASE64Encoder进行encode,结果发现有的邮件乱码,有的邮件正常;好蛋疼!!
经过楼主的排查,翻阅javax mail源码(MimeMessage、MimeUtility.java、PropUtil.java)发现在MimeMessage.java中:
public void setSubject(String subject, String charset) throws MessagingException { if (subject == null) { removeHeader("Subject"); } else { try { setHeader("Subject", MimeUtility.fold(9, MimeUtility.encodeText(subject, charset, null))); } catch (UnsupportedEncodingException uex) { throw new MessagingException("Encoding error", uex); } } }
该方法调用到了MimeUtility.fold()方法
public static String fold(int used, String s) { if (!foldText) return s; int end; char c; // 请注意这里 // Strip trailing spaces and newlines for (end = s.length() - 1; end >= 0; end--) { c = s.charAt(end); if (c != ' ' && c != '\t' && c != '\r' && c != '\n') break; } if (end != s.length() - 1) s = s.substring(0, end + 1); // 一下省略啦 ...... }
该方法遇到""、\t、\r、\n就会将邮件标题截取,剩余部分默认将其作为邮件内容;
回过头来,再看下sun.misc.BASE64Encoder.encode(),sun的base64实现完全遵循了Base64(RFC2045~RFC2049)规范,将加密后的字符串每76个字符后插入回车换行符,这就导致了邮件标题base64之后不完整,而且邮件内容多了一部分,导致邮件无法被解析展示。
最后楼主经过测试使用了apache的Base64实现org.apache.commons.codec.binary.Base64,该实现对加密后的Base64字符串不进行任何回车换行的操作。
OK,这里把解决邮件标题乱码的部分代码贴出来:
String subject = new String(Base64.encodeBase64("subject".getBytes("UTF-8"))); mailMessage.setSubject("=?UTF-8?B?" + subject + "?=");
第一次写博客,写的不好还请轻拍:)
相关推荐
Java 实现模板邮件发送是一项常见的任务,特别是在企业级应用中,用于批量发送通知、报告或者验证码等。在本文中,我们将深入探讨如何使用Java来创建和发送带有模板的电子邮件。 首先,我们需要理解Java中用于邮件...
本篇文章将详细讲解如何利用Java实现邮件发送,并结合Apache的相关库来创建邮件发送模板,以提升效率和用户体验。 首先,JavaMail API是Java中用于处理电子邮件的主要库。它提供了丰富的API,可以用来创建、发送和...
在Java编程领域,发送邮件是一项常见的任务,尤其在企业级应用中,如自动...通过JavaMail API与模板引擎的结合,实现了高效、灵活的邮件发送功能。开发者只需提供必要的配置和数据,即可轻松完成复杂的邮件发送任务。
在Java编程环境中,发送HTML模板邮件是一项常见的任务,特别是在企业级应用中,用于发送美观、格式化的通知或营销信息。本项目提供了一个完整的Eclipse工程...希望这个概述能帮助你理解并实现自己的Java邮件发送功能。
此外,如果发送大量邮件,记得考虑邮件发送频率和并发控制,避免被邮件服务器视为垃圾邮件。 通过学习和理解这些知识点,你将能够利用Java实现在各种场景下发送带模板的邮件功能,为你的应用程序添加更丰富的通信...
4. **编写Java代码发送邮件**: 下面的代码展示了如何使用JavaMail API和FreeMarker来发送模板邮件。 ```java import javax.mail.*; import javax.mail.internet.*; import freemarker.template.Configuration; ...
3. **mail.jar**:在某些情况下,javax.mail.jar可能会包含在名为mail.jar的文件中,它是JavaMail API的完整实现,包含了发送邮件所需的所有组件。 4. **commons-email-1.2.jar**:这是Apache Commons Email库,...
`javax.mail`库提供了强大的功能,使得在程序中集成邮件发送变得简单而灵活。只需注意,实际使用时需要根据你的SMTP服务器配置调整`SMTP_HOST`、`SMTP_PORT`、`FROM_ADDRESS`和`FROM_PASSWORD`。同时,确保邮件服务...
"java email邮件发送所需mail相关jar包"就是这样一个集合,它包含了执行邮件发送所需的类和方法。 邮件发送主要依赖于JavaMail API,这是一个开源的Java库,它提供了与邮件服务器交互的标准API。JavaMail API包括多...
总的来说,`EmailUtils`是一个实用的工具,它简化了使用`JavaMail`发送邮件的过程,通过配置和模板系统,使得邮件发送更加灵活和高效。在实际开发中,这样的工具类大大提高了代码的可读性和可维护性。
Java邮件发送是通过Java编程语言实现发送电子邮件的功能。在Java中,这通常涉及到JavaMail API,一个用于处理邮件的开放源代码库。本篇将详细解释如何使用Java发送邮件,重点在于提供的三个类:MailSenderInfo.java...
Java Mail邮件发送是一个在Java应用程序中发送电子邮件的关键技术。它基于JavaMail API,这是一个开源库,提供了丰富的功能来处理SMTP(简单邮件传输协议)、POP3(邮局协议)和IMAP(因特网消息访问协议)等邮件...
在Java项目中,我们需要引入几个关键的库来实现邮件发送功能: - `java.util.Properties`: 用于配置邮件会话属性。 - `javax.mail.*`: 包含了用于发送邮件的主要类和接口。 - `javax.activation.*`: 提供了处理数据...
2. `javax.mail.Transport`:负责将邮件发送到邮件服务器。通过调用`Transport.send()`方法,开发者可以将创建好的邮件对象发送出去。 3. `javax.mail.Message`:表示一个邮件消息,包含了邮件的全部内容,如收件人...
JavaMail API 包含了多个关键组件,如`javax.mail`和`javax.mail.internet`包,它们提供了创建、配置、发送和接收邮件的接口和类。例如,`Session`对象是邮件会话的入口点,用于设置SMTP服务器信息、认证凭据和其他...
JavaMail 是一个强大的开源库,用于在Java应用程序中发送和接收电子邮件。...在这个过程中,理解MimeMessage、Multipart和BodyPart的概念,以及如何配置SMTP服务器参数,是成功实现邮件发送的关键。
在Spring Boot应用中,利用JavaMailSender发送邮件是一种常见的需求,Spring ...Spring Boot的`spring-boot-starter-mail`模块简化了邮件发送的配置和使用,使得开发者能够更加专注于业务逻辑,而不是底层通信细节。
在Spring Boot框架中,实现邮件发送功能是一项常见的需求,它能够帮助我们自动化处理通知、确认信息等业务场景。本文将详细讲解如何利用Spring Boot的JavaMailSender接口和相关的配置来实现各种类型的邮件发送,包括...
下面将详细解释如何在Java中实现邮件发送,以及涉及到的关键知识点。 首先,JavaMail API是Java平台用于处理邮件的核心库,它提供了创建、发送、读取和管理电子邮件的功能。要发送邮件,你需要引入`javax.mail`和`...
首先,邮件发送系统的核心是SMTP(Simple Mail Transfer Protocol),这是一种用于在互联网上传输电子邮件的标准协议。通过SMTP,系统可以将用户编写或预设的邮件发送到目标邮箱服务器。了解SMTP的工作流程,包括...