本节介绍如何使用 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。

邮件代码是一个跨领域问题,很可能是 重构为自定义的 Spring AOP 方面,然后可以 在目标上的适当连接点运行。OrderManager

使用 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,这变得非常容易做到。

内联资源通过使用指定的(在上面的示例中)添加到 中。添加文本的顺序 资源非常重要。请务必先添加文本,然后 资源。如果你反过来做,它是行不通的。MimeMessageContent-IDidentifier1234