如何使用 JavaMail API 从文件中读取 HTML 模板来发送邮件?
How can I read an HTML template from a file to send a mail with it using the JavaMail API?
我有一个任务要使用 JavaMail API 发送 HTML 邮件。
这是我的代码的一小部分:
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
try {
helper.setTo(recipients);
helper.setSubject("Simple mail template");
helper.setText("<html><body>Hi There</body><html>",html:true);
} catch (MessagingException e) {
e.printStackTrace();
}
现在我有一个任务要将 HTML 移到一个单独的文件中,并创建一个 class 来读取 HTML 模板并用它发送邮件。
关于如何做到这一点有什么建议吗?
我喜欢 jhipster 方法,只需使用 jhipster 生成应用程序。你得到了很好的例子。他们代码的一小部分
模板消息保存为您项目中的资源:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{email.activation.title}">Activation</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}" />
</head>
<body>
<p th:text="#{email.activation.greeting(${user.login})}">
Dear
</p>
<p th:text="#{email.activation.text1}">
Your account has been created, please click on the URL below to activate it:
</p>
<p>
<a th:href="@{|${baseUrl}/#/activate?key=${user.activationKey}|}"
th:text="@{|${baseUrl}/#/activate?key=${user.activationKey}|}">Activation Link</a>
</p>
<p>
<span th:text="#{email.activation.text2}">Regards, </span>
<br/>
<em th:text="#{email.signature}">Innovation Development HUB.</em>
</p>
</body>
</html>
在 yaml 文件中配置凭据和发送电子邮件首选项之前的电子邮件发件人
@Service
public class MailService {
private final Logger log = LoggerFactory.getLogger(MailService.class);
private static final String USER = "user";
private static final String BASE_URL = "baseUrl";
private final JHipsterProperties jHipsterProperties;
private final JavaMailSender javaMailSender;
private final MessageSource messageSource;
private final SpringTemplateEngine templateEngine;
public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender,
MessageSource messageSource, SpringTemplateEngine templateEngine) {
this.jHipsterProperties = jHipsterProperties;
this.javaMailSender = javaMailSender;
this.messageSource = messageSource;
this.templateEngine = templateEngine;
}
@Async
public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
isMultipart, isHtml, to, subject, content);
// Prepare message using a Spring helper
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
message.setTo(to);
message.setFrom(jHipsterProperties.getMail().getFrom());
message.setSubject(subject);
message.setText(content, isHtml);
javaMailSender.send(mimeMessage);
log.debug("Sent email to User '{}'", to);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn("Email could not be sent to user '{}'", to, e);
} else {
log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
}
}
}
@Async
public void sendEmailFromTemplate(User user, String templateName, String titleKey) {
Locale locale = Locale.forLanguageTag(user.getLangKey());
Context context = new Context(locale);
context.setVariable(USER, user);
context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
String content = templateEngine.process(templateName, context);
String subject = messageSource.getMessage(titleKey, null, locale);
sendEmail(user.getEmail(), subject, content, false, true);
}
@Async
public void sendActivationEmail(User user) {
log.debug("Sending activation email to '{}'", user.getEmail());
sendEmailFromTemplate(user, "activationEmail", "email.activation.title");
}
@Async
public void sendCreationEmail(User user) {
log.debug("Sending creation email to '{}'", user.getEmail());
sendEmailFromTemplate(user, "creationEmail", "email.activation.title");
}
@Async
public void sendPasswordResetMail(User user) {
log.debug("Sending password reset email to '{}'", user.getEmail());
sendEmailFromTemplate(user, "passwordResetEmail", "email.reset.title");
}
}
并且你需要SpringTemplateEngine
public class SpringTemplateEngine extends TemplateEngine implements MessageSourceAware, InitializingBean {
private static final SpringStandardDialect SPRINGSTANDARD_DIALECT = new SpringStandardDialect();
private MessageSource messageSource = null;
private MessageSource templateEngineMessageSource = null;
public SpringTemplateEngine() {
super.clearDialects();
super.addDialect(SPRINGSTANDARD_DIALECT);
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void setTemplateEngineMessageSource(MessageSource templateEngineMessageSource) {
this.templateEngineMessageSource = templateEngineMessageSource;
}
public void afterPropertiesSet() throws Exception {
SpringMessageResolver springMessageResolver = new SpringMessageResolver();
springMessageResolver.setMessageSource(this.templateEngineMessageSource == null ? this.messageSource : this.templateEngineMessageSource);
super.setDefaultMessageResolvers(Collections.singleton(springMessageResolver));
}
protected final void initializeSpecific() {
Configuration configuration = this.getConfiguration();
Map<String, IDialect> dialects = configuration.getDialects();
Iterator var3 = dialects.values().iterator();
IDialect dialect;
do {
if (!var3.hasNext()) {
throw new ConfigurationException("When using " + SpringTemplateEngine.class.getSimpleName() + ", at least one of the configured dialects must be or extend " + SpringStandardDialect.class.getName() + ".");
}
dialect = (IDialect)var3.next();
} while(!(dialect instanceof SpringStandardDialect));
this.initializeSpringSpecific();
}
protected void initializeSpringSpecific() {
}
}
使用模板引擎
我用 Thymeleaf as a template engine. You first wrote that you are using Spring Boot in your project, so I assume you can use it. I also assume you are using either Maven or Gradle 作为构建工具创建了一个最小示例。
添加 Thymeleaf 依赖项
将 spring-boot-starter-thymeleaf
依赖项添加到您的项目。您使用的是 Maven 还是 Gradle?
专家
您的 pom.xml
依赖项应包括:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Gradle
您的 build.gradle
依赖项应包括:
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
在 Spring 引导中配置 Thymeleaf
添加所需的 @Bean
。它们是:
@Bean
public ITemplateResolver templateResolver()
{
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
@Bean
public TemplateEngine templateEngine()
{
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(this.templateResolver());
return templateEngine;
}
他们可以进入任何用 @Configuration
(或 @SpringBootApplication
)注释的 class。
示例
现在,您可以从任何 class 访问您的 TemplateEngine
,其字段由 Spring 注入。
@Component
public class SomeClass
{
@Autowired
private TemplateEngine templateEngine;
public String generateMailHtml(String text)
{
Map<String, Object> variables = new HashMap<>();
variables.put("mailtext", text);
final String templateFileName = "mail"; //Name of the template file without extension
String output = this.templateEngine.process(templateFileName, new Context(Locale.getDefault(), variables));
return output;
}
}
mail.html
应位于 templates/
下的 class 路径 (resources/
)。
它应该是这样的:
<html>
<body data-th-text="${mailtext}"></body>
</html>
您发布的代码片段现在看起来像这样(@Autowired
SomeClass
as someClass
in the class outside the method):
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
try {
helper.setTo(recipients);
helper.setSubject("Simple mail template");
helper.setText(someClass.generateMailHtml("Hi There"), true);
} catch (MessagingException e) {
e.printStackTrace();
}
当然,根据自己的需要更改示例!
编辑
您提到您需要填写模板 "with a list of some names"。这将是这样实现的:
public String generateMailHtml(List<String> names)
{
Map<String, Object> variables = new HashMap<>();
variables.put("names", names);
final String templateFileName = "mail"; //Name of the template file without extension
String output = this.templateEngine.process(templateFileName, new Context(Locale.getDefault(), variables));
return output;
}
mail.html
<html>
<body>
<ul>
<li data-th-each="name : ${names}" data-th-text="${name}"></li>
</ul>
</body>
</html>
详细了解 data-th-each
/ th:each
here。注意:您可以交替使用 data-th-
和 th:
,尽管 data-th-
更 HTML5 友好。
我有一个任务要使用 JavaMail API 发送 HTML 邮件。 这是我的代码的一小部分:
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
try {
helper.setTo(recipients);
helper.setSubject("Simple mail template");
helper.setText("<html><body>Hi There</body><html>",html:true);
} catch (MessagingException e) {
e.printStackTrace();
}
现在我有一个任务要将 HTML 移到一个单独的文件中,并创建一个 class 来读取 HTML 模板并用它发送邮件。 关于如何做到这一点有什么建议吗?
我喜欢 jhipster 方法,只需使用 jhipster 生成应用程序。你得到了很好的例子。他们代码的一小部分
模板消息保存为您项目中的资源:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{email.activation.title}">Activation</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}" />
</head>
<body>
<p th:text="#{email.activation.greeting(${user.login})}">
Dear
</p>
<p th:text="#{email.activation.text1}">
Your account has been created, please click on the URL below to activate it:
</p>
<p>
<a th:href="@{|${baseUrl}/#/activate?key=${user.activationKey}|}"
th:text="@{|${baseUrl}/#/activate?key=${user.activationKey}|}">Activation Link</a>
</p>
<p>
<span th:text="#{email.activation.text2}">Regards, </span>
<br/>
<em th:text="#{email.signature}">Innovation Development HUB.</em>
</p>
</body>
</html>
在 yaml 文件中配置凭据和发送电子邮件首选项之前的电子邮件发件人
@Service
public class MailService {
private final Logger log = LoggerFactory.getLogger(MailService.class);
private static final String USER = "user";
private static final String BASE_URL = "baseUrl";
private final JHipsterProperties jHipsterProperties;
private final JavaMailSender javaMailSender;
private final MessageSource messageSource;
private final SpringTemplateEngine templateEngine;
public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender,
MessageSource messageSource, SpringTemplateEngine templateEngine) {
this.jHipsterProperties = jHipsterProperties;
this.javaMailSender = javaMailSender;
this.messageSource = messageSource;
this.templateEngine = templateEngine;
}
@Async
public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
isMultipart, isHtml, to, subject, content);
// Prepare message using a Spring helper
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
message.setTo(to);
message.setFrom(jHipsterProperties.getMail().getFrom());
message.setSubject(subject);
message.setText(content, isHtml);
javaMailSender.send(mimeMessage);
log.debug("Sent email to User '{}'", to);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn("Email could not be sent to user '{}'", to, e);
} else {
log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
}
}
}
@Async
public void sendEmailFromTemplate(User user, String templateName, String titleKey) {
Locale locale = Locale.forLanguageTag(user.getLangKey());
Context context = new Context(locale);
context.setVariable(USER, user);
context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
String content = templateEngine.process(templateName, context);
String subject = messageSource.getMessage(titleKey, null, locale);
sendEmail(user.getEmail(), subject, content, false, true);
}
@Async
public void sendActivationEmail(User user) {
log.debug("Sending activation email to '{}'", user.getEmail());
sendEmailFromTemplate(user, "activationEmail", "email.activation.title");
}
@Async
public void sendCreationEmail(User user) {
log.debug("Sending creation email to '{}'", user.getEmail());
sendEmailFromTemplate(user, "creationEmail", "email.activation.title");
}
@Async
public void sendPasswordResetMail(User user) {
log.debug("Sending password reset email to '{}'", user.getEmail());
sendEmailFromTemplate(user, "passwordResetEmail", "email.reset.title");
}
}
并且你需要SpringTemplateEngine
public class SpringTemplateEngine extends TemplateEngine implements MessageSourceAware, InitializingBean {
private static final SpringStandardDialect SPRINGSTANDARD_DIALECT = new SpringStandardDialect();
private MessageSource messageSource = null;
private MessageSource templateEngineMessageSource = null;
public SpringTemplateEngine() {
super.clearDialects();
super.addDialect(SPRINGSTANDARD_DIALECT);
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void setTemplateEngineMessageSource(MessageSource templateEngineMessageSource) {
this.templateEngineMessageSource = templateEngineMessageSource;
}
public void afterPropertiesSet() throws Exception {
SpringMessageResolver springMessageResolver = new SpringMessageResolver();
springMessageResolver.setMessageSource(this.templateEngineMessageSource == null ? this.messageSource : this.templateEngineMessageSource);
super.setDefaultMessageResolvers(Collections.singleton(springMessageResolver));
}
protected final void initializeSpecific() {
Configuration configuration = this.getConfiguration();
Map<String, IDialect> dialects = configuration.getDialects();
Iterator var3 = dialects.values().iterator();
IDialect dialect;
do {
if (!var3.hasNext()) {
throw new ConfigurationException("When using " + SpringTemplateEngine.class.getSimpleName() + ", at least one of the configured dialects must be or extend " + SpringStandardDialect.class.getName() + ".");
}
dialect = (IDialect)var3.next();
} while(!(dialect instanceof SpringStandardDialect));
this.initializeSpringSpecific();
}
protected void initializeSpringSpecific() {
}
}
使用模板引擎
我用 Thymeleaf as a template engine. You first wrote that you are using Spring Boot in your project, so I assume you can use it. I also assume you are using either Maven or Gradle 作为构建工具创建了一个最小示例。
添加 Thymeleaf 依赖项
将 spring-boot-starter-thymeleaf
依赖项添加到您的项目。您使用的是 Maven 还是 Gradle?
专家
您的 pom.xml
依赖项应包括:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Gradle
您的 build.gradle
依赖项应包括:
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
在 Spring 引导中配置 Thymeleaf
添加所需的 @Bean
。它们是:
@Bean
public ITemplateResolver templateResolver()
{
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
@Bean
public TemplateEngine templateEngine()
{
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(this.templateResolver());
return templateEngine;
}
他们可以进入任何用 @Configuration
(或 @SpringBootApplication
)注释的 class。
示例
现在,您可以从任何 class 访问您的 TemplateEngine
,其字段由 Spring 注入。
@Component
public class SomeClass
{
@Autowired
private TemplateEngine templateEngine;
public String generateMailHtml(String text)
{
Map<String, Object> variables = new HashMap<>();
variables.put("mailtext", text);
final String templateFileName = "mail"; //Name of the template file without extension
String output = this.templateEngine.process(templateFileName, new Context(Locale.getDefault(), variables));
return output;
}
}
mail.html
应位于 templates/
下的 class 路径 (resources/
)。
它应该是这样的:
<html>
<body data-th-text="${mailtext}"></body>
</html>
您发布的代码片段现在看起来像这样(@Autowired
SomeClass
as someClass
in the class outside the method):
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
try {
helper.setTo(recipients);
helper.setSubject("Simple mail template");
helper.setText(someClass.generateMailHtml("Hi There"), true);
} catch (MessagingException e) {
e.printStackTrace();
}
当然,根据自己的需要更改示例!
编辑
您提到您需要填写模板 "with a list of some names"。这将是这样实现的:
public String generateMailHtml(List<String> names)
{
Map<String, Object> variables = new HashMap<>();
variables.put("names", names);
final String templateFileName = "mail"; //Name of the template file without extension
String output = this.templateEngine.process(templateFileName, new Context(Locale.getDefault(), variables));
return output;
}
mail.html
<html>
<body>
<ul>
<li data-th-each="name : ${names}" data-th-text="${name}"></li>
</ul>
</body>
</html>
详细了解 data-th-each
/ th:each
here。注意:您可以交替使用 data-th-
和 th:
,尽管 data-th-
更 HTML5 友好。