Chapter 22. Spring邮件抽象层

Chapter 22. Spring邮件抽象层

22.1. 简介

Spring提供了一个发送电子邮件的高级抽象层,它向用户屏蔽了底层邮件系统的一些细节,同时代表客户端负责底层的资源处理。

22.2. Spring邮件抽象结构

Spring邮件抽象层的主要包为org.springframework.mail 。它包括了发送电子邮件的主要接口MailSender ,和值对象 SimpleMailMessage ,它封装了简单邮件的属性如from , to ,cc , subject ,text 。 包里还包含一棵以MailException 为根的checked Exception继承树,它们提供了对底层邮件系统异常的高级别抽象。 要获得关于邮件异常层次的更丰富的信息,请参考Javadocs。

为了使用JavaMail 中的一些特色, 比如MIME类型的信件, Spring提供了MailSender 的一个子接口, 即org.springframework.mail.javamail.JavaMailSender 。Spring还提供了一个回调接口org.springframework.mail.javamail.MimeMessagePreparator , 用于准备JavaMail的MIME信件。

public interface MailSender {

/**
* Send the given simple mail message.
* @param simpleMessage message to send
* @throws MailException in case of message, authentication, or send errors
*/
public void send(SimpleMailMessage simpleMessage) throws MailException;

/**
* Send the given array of simple mail messages in batch.
* @param simpleMessages messages to send
* @throws MailException in case of message, authentication, or send errors
*/
public void send(SimpleMailMessage[] simpleMessages) throws MailException;

}
public interface JavaMailSender extends MailSender {

/**
* Create a new JavaMail MimeMessage for the underlying JavaMail Session
* of this sender. Needs to be called to create MimeMessage instances
* that can be prepared by the client and passed to send(MimeMessage).
* @return the new MimeMessage instance
* @see #send(MimeMessage)
* @see #send(MimeMessage[])
*/
public MimeMessage createMimeMessage();

/**
* Send the given JavaMail MIME message.
* The message needs to have been created with createMimeMessage.
* @param mimeMessage message to send
* @throws MailException in case of message, authentication, or send errors
* @see #createMimeMessage
*/
public void send(MimeMessage mimeMessage) throws MailException;

/**
* Send the given array of JavaMail MIME messages in batch.
* The messages need to have been created with createMimeMessage.
* @param mimeMessages messages to send
* @throws MailException in case of message, authentication, or send errors
* @see #createMimeMessage
*/
public void send(MimeMessage[] mimeMessages) throws MailException;

/**
* Send the JavaMail MIME message prepared by the given MimeMessagePreparator.
* Alternative way to prepare MimeMessage instances, instead of createMimeMessage
* and send(MimeMessage) calls. Takes care of proper exception conversion.
* @param mimeMessagePreparator the preparator to use
* @throws MailException in case of message, authentication, or send errors
*/
public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException;

/**
* Send the JavaMail MIME messages prepared by the given MimeMessagePreparators.
* Alternative way to prepare MimeMessage instances, instead of createMimeMessage
* and send(MimeMessage[]) calls. Takes care of proper exception conversion.
* @param mimeMessagePreparators the preparator to use
* @throws MailException in case of message, authentication, or send errors
*/
public void send(MimeMessagePreparator[] mimeMessagePreparators) throws MailException;

}
public interface MimeMessagePreparator {

/**
* Prepare the given new MimeMessage instance.
* @param mimeMessage the message to prepare
* @throws MessagingException passing any exceptions thrown by MimeMessage
* methods through for automatic conversion to the MailException hierarchy
*/
void prepare(MimeMessage mimeMessage) throws MessagingException;

}

22.3. 使用Spring邮件抽象

假设某个业务接口名为 OrderManager :

public interface OrderManager {

void placeOrder(Order order);
}

同时有一个用例为:需要生成带有订单号的email信件, 并向客户发送该订单。 为此,我们会使用MailSender 接口和SimpleMailMessage 类。

请注意,通常情况下,我们在业务代码中使用接口而让Spring ioc容器负责组装我们需要的合作者。

以下是OrderManager 的实现:

import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;

public class OrderManagerImpl implements OrderManager {

private MailSender mailSender;
private SimpleMailMessage message;

public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}

public void setMessage(SimpleMailMessage message) {
this.message = message;
}

public void placeOrder(Order order) {

// Do the business calculations...
// Call the collaborators to persist the order...

//Create a thread safe "sandbox" of the message
SimpleMailMessage msg = new SimpleMailMessage(this.message);
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{
mailSender.send(msg);
}
catch(MailException ex) {
//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>

<bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="customerservice@mycompany.com"/>
<property name="subject" value="Your order"/>
</bean>

<bean id="orderManager" class="com.mycompany.businessapp.support.OrderManagerImpl">
<property name="mailSender" ref="mailSender"/>
<property name="message" ref="mailMessage"/>
</bean>

下面是OrderManager 接口的实现,使用了MimeMessagePreparator 回调接口。 请注意这里的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 OrderManagerImpl 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 MessagingException {

mimeMessage.setRecipient(Message.RecipientType.TO,
new InternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(new InternetAddress("mail@mycompany.com"));
mimeMessage.setText(
"Dear "
+ order.getCustomer().getFirstName()
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
}
};
try {
mailSender.send(preparator);
}
catch (MailException ex) {
//log it and go on
System.err.println(ex.getMessage());
}
}
}

如果你想获得JavaMail MimeMessage 的全部能力,你可以使用MimeMessagePreparator

[Note] Note

以上的邮件代码是一个横切关注点,是重构为定制SpringAOP advice的完美候选者,这样就可以在目标对象OrderManager 合适的joinpoint中运行。请参阅Chapter 6, 使用Spring进行面向切面编程(AOP) 章节。

22.3.1. 可插拔的MailSender实现

Spring直接提供两种MailSender 的实现:标准的JavaMail实现,和基于Jason Hunter 编写的MailMessage 类之上的实现,后者位于http://servlets.com/cos (com.oreilly.servlet)。进一步的资料请查阅相关Javadocs。

22.4. 使用 JavaMail MimeMessageHelper

org.springframework.mail.javamail.MimeMessageHelper 是处理JavaMail邮件常用的顺手组件之一。它可以让你摆脱繁复的javax.mail.internet API类。下面是一些通常的场景:

22.4.1. 创建一条简单的MimeMessage ,并且发送出去

使用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("test@host.com");
helper.setText("Thank you for ordering!");

sender.send(message);

22.4.2. 发送附件和嵌入式资源(inline resources)

Email允许添加附件,也允许在multipart信件中内嵌资源。内嵌资源可能是你在信件中希望使用的图像,或者样式表,但是又不想把它们作为附件。下面的例子演示如何使用MimeMessageHelper 来发送带有内嵌图像的email。

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("test@host.com");

// 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);

// if you would need to include the file as an attachment, use
// the various addAttachment() methods on the MimeMessageHelper


sender.send(message);
[Warning] Warning

如你所见,嵌入式资源使用Content-ID(上例中是identifier1234 )来插入到mime信件中去。你加入文本或者资源的顺序是非常重要的。首先,你加入文本,随后是资源。如果你弄反了顺序,它将无法正常运作!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值