6.Email
6.1 介绍
库依赖关系
以下JAR需要位于应用程序的类路径中,以便使用Spring Framework的电子邮件库。
这个库可以在网上免费使用 - 例如,在Maven Central中可以使用com.sun.mail:javax.mail。
Spring框架提供了一个有用的实用程序库,用于发送电子邮件,防止用户从底层邮件系统的特定情况出发,并代表客户端负责低级别的资源处理。
org.springframework.mail包是Spring Framework电子邮件支持的根级包。 发送邮件的中心界面是MailSender界面; SimpleMailMessage类是一个封装简单邮件属性的简单值对象,如From和To(以及其他很多)。 该软件包还包含一个检查异常的层次结构,它对较低级别的邮件系统异常提供了更高的抽象级别,而根异常是MailException。 有关富邮件异常层次结构的更多信息,请参阅javadocs。
org.springframework.mail.javamail.JavaMailSender接口将特殊的JavaMail功能(如MIME消息支持)添加到MailSender接口(从中继承)。 JavaMailSender还提供了一个用于准备JavaMail MIME消息的回调接口,称为org.springframework.mail.javamail.MimeMessagePreparator
6.2. 使用
假设有一个名为OrderManager的业务接口:
public interface OrderManager {
void placeOrder(Order order);
}
让我们还假设有一个要求,说明一个带有订单号码的电子邮件信息需要生成并发送给一个发出相关订单的客户。
6.2.1 基本的MailSender和SimpleMailMessage用法
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
public class SimpleOrderManager implements OrderManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
public void placeOrder(Order order) {
// Do the business calculations...
// Call the collaborators to persist the order...
// Create a thread safe "copy" of the template message and customize it
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear " + order.getCustomer().getFirstName()
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
try{
this.mailSender.send(msg);
}
catch (MailException ex) {
// simply log it and go on...
System.err.println(ex.getMessage());
}
}
}
查找下面的代码的bean定义:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.mycompany.com"/>
</bean>
<!-- this is a template message that we can pre-load with default state -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="[email protected]"/>
<property name="subject" value="Your order"/>
</bean>
<bean id="orderManager" class="com.mycompany.businessapp.support.SimpleOrderManager">
<property name="mailSender" ref="mailSender"/>
<property name="templateMessage" ref="templateMessage"/>
</bean>
6.2.2. 使用JavaMailSender和MimeMessagePreparator
这是使用MimeMessagePreparator回调接口的OrderManager的另一个实现。 请注意在这种情况下,mailSender属性是JavaMailSender类型,以便我们能够使用JavaMail MimeMessage类:
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class SimpleOrderManager implements OrderManager {
private JavaMailSender mailSender;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void placeOrder(final Order order) {
// Do the business calculations...
// Call the collaborators to persist the order...
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
mimeMessage.setRecipient(Message.RecipientType.TO,
new InternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(new InternetAddress("[email protected]"));
mimeMessage.setText(
"Dear " + order.getCustomer().getFirstName() + " "
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
}
};
try {
this.mailSender.send(preparator);
}
catch (MailException ex) {
// simply log it and go on...
System.err.println(ex.getMessage());
}
}
}
邮件代码是一个横切的问题,很可能是重构成自定义的Spring AOP Aspect的候选,然后可以在OrderManager目标上的适当连接点执行该方面。
Spring框架的邮件支持附带了标准的JavaMail实现。 请参阅相关的javadocs了解更多信息。
6.3. 使用JavaMail MimeMessageHelper
处理JavaMail消息时非常方便的类是org.springframework.mail.javamail.MimeMessageHelper类,它避免了使用详细的JavaMail API。 使用MimeMessageHelper创建一个MimeMessage非常简单:
// of course you would use DI in any real-world cases
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setTo("[email protected]");
helper.setText("Thank you for ordering!");
sender.send(message);
6.3.1.发送附件和内联资源
Multipart 类型的电子邮件允许附件和内联资源。 内联资源的例子是图像或样式表,您希望在消息中使用,但不希望显示为附件。
附件
以下示例显示如何使用MimeMessageHelper发送电子邮件以及单个JPEG图像附件。
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
// use the true flag to indicate you need a multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("[email protected]");
helper.setText("Check out this image!");
// let's attach the infamous windows Sample file (this time copied to c:/)
FileSystemResource file = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg", file);
sender.send(message);
内联资源
下示例显示如何使用MimeMessageHelper发送电子邮件以及内嵌图像。
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
// use the true flag to indicate you need a multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("[email protected]");
// use the true flag to indicate the text included is HTML
helper.setText("<html><body><img src='cid:identifier1234'></body></html>", true);
// let's include the infamous windows Sample file (this time copied to c:/)
FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addInline("identifier1234", res);
sender.send(message);
使用指定的Content-ID(上例中的identifier1234)将内联资源添加到mime消息中。 您添加文本和资源的顺序非常重要。 请务必先添加文本,然后再添加资源。 如果你以相反的方式做,它将无法工作!
6.3.2. 使用模板库创建电子邮件内容
前面示例中的代码使用诸如message.setText(..)之类的方法调用明确地创建了电子邮件消息的内容。 这对于简单的情况来说很好,在前面提到的示例中,这样做的目的是向您展示API的基础知识。
但是,在您的典型企业应用程序中,由于多种原因,您不会使用上述方法创建电子邮件的内容。
- 在Java代码中创建基于HTML的电子邮件内容是单调乏味且容易出错的
- 显示逻辑和业务逻辑之间没有明确的分离
- 更改电子邮件内容的显示结构需要编写Java代码,重新编译,重新部署...
通常,解决这些问题的方法是使用诸如FreeMarker之类的模板库来定义电子邮件内容的显示结构。 这使得你的代码只负责创建要在电子邮件模板中呈现的数据并发送电子邮件。 当你的电子邮件的内容变得相当复杂时,绝对是一个最好的实践,而Spring框架的FreeMarker支持类变得相当容易。