本节介绍如何使用 Spring Framework 发送电子邮件。

库依赖项

以下 JAR 需要位于应用程序的类路径上,才能使用 Spring Framework 的电子邮件支持:

该库可在 Web 上免费获得,例如,在 Maven Central 中为 .请确保使用最新的 2.x 版本(使用 包命名空间)而不是 Jakarta Mail 1.6.x(使用包命名空间)。com.sun.mail:jakarta.mailjakarta.mailjavax.mail

Spring Framework 提供了一个有用的实用程序库,用于发送屏蔽的电子邮件 您从底层邮件系统的具体情况中负责 代表客户端进行低级资源处理。

该包是 Spring 的根级包 Framework 的电子邮件支持。发送电子邮件的中央界面是界面。一个简单的值对象,它封装了简单邮件的属性,例如 as 和 (加上许多其他) 是类。此软件包 还包含已检查异常的层次结构,这些异常提供更高级别的 对较低级别的邮件系统异常进行抽象,根例外为 。有关富邮件异常层次结构的更多信息,请参阅 javadocorg.springframework.mailMailSenderfromtoSimpleMailMessageMailException

界面增加了专门的 JavaMail 功能,例如对界面的 MIME 消息支持 (它从中继承)。 还提供了一个回调接口,用于准备 .org.springframework.mail.javamail.JavaMailSenderMailSenderJavaMailSenderorg.springframework.mail.javamail.MimeMessagePreparatorMimeMessage

用法

假设我们有一个名为 的业务接口,如以下示例所示:OrderManager

public interface OrderManager {

	void placeOrder(Order order);

}

进一步假设我们有一个要求,说明一封电子邮件带有 需要生成订单号并将其发送给下相关订单的客户。

基本和用法MailSenderSimpleMailMessage

以下示例演示如何使用和发送 当有人下订单时发送电子邮件:MailSenderSimpleMailMessage

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.example"/>
</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>

使用 和JavaMailSenderMimeMessagePreparator

本节介绍使用回调接口的另一种实现。在下面的示例中,该属性的类型,以便我们能够使用 JavaMail 类:OrderManagerMimeMessagePreparatormailSenderJavaMailSenderMimeMessage

import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;

import jakarta.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() + ", thanks for your 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 方面,然后可以 在目标上的适当连接点运行。OrderManager

Spring Framework 的邮件支持随标准 JavaMail 实现一起提供。 有关更多信息,请参阅相关的 javadoc。

使用 JavaMailMimeMessageHelper

在处理 JavaMail 消息时非常方便的类是 ,它可以保护您免受 必须使用冗长的 JavaMail API。使用 ,它是 创建 非常容易,如以下示例所示:org.springframework.mail.javamail.MimeMessageHelperMimeMessageHelperMimeMessage

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

发送附件和内联资源

多部分电子邮件允许附件和内联资源。示例 内联资源包括要在邮件中使用的图像或样式表,但 您不希望显示为附件。

附件

以下示例演示如何使用 to 发送电子邮件 使用单个 JPEG 图像附件: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]");

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

内联资源

以下示例演示如何使用 to 发送电子邮件 使用内联图像: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);
内联资源通过使用指定的(在上面的示例中)添加到 中。添加文本的顺序 资源非常重要。请务必先添加文本,然后 资源。如果你反过来做,它是行不通的。MimeMessageContent-IDidentifier1234

使用模板库创建电子邮件内容

前面部分中显示的示例中的代码显式创建了电子邮件的内容, 通过使用诸如 .这对于简单情况来说很好,而且它 在上述示例的上下文中是可以的,其目的是向您展示 API 的基础知识。message.setText(..)

但是,在典型的企业应用程序中,开发人员通常不会创建内容 由于以下原因,使用前面显示的方法的电子邮件:

  • 在 Java 代码中创建基于 HTML 的电子邮件内容既繁琐又容易出错。

  • 显示逻辑和业务逻辑之间没有明确的分离。

  • 更改电子邮件内容的显示结构需要编写 Java 代码, 重新编译、重新部署等。

通常,解决这些问题所采取的方法是使用模板库(例如 作为 FreeMarker)来定义电子邮件内容的显示结构。这会留下您的代码 仅负责创建要在电子邮件模板中呈现的数据,并且 发送电子邮件。当您的电子邮件内容时,这绝对是一种最佳实践 甚至变得中等复杂,并且,在 Spring 框架的支持类 FreeMarker,这变得非常容易做到。