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

库依赖项

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

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

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

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

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

用法

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

public interface OrderManager {

	void placeOrder(Order order);

}

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

基本和用法MailSenderSimpleMailMessage

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

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 定义:Spring中文文档

<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 类:OrderManagerMimeMessagePreparatormailSenderJavaMailSenderMimeMessageSpring中文文档

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中文文档

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

使用 JavaMailMimeMessageHelper

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

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

发送附件和内联资源

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

附件

以下示例演示如何使用 to 发送电子邮件 使用单个 JPEG 图像附件:MimeMessageHelperSpring中文文档

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 发送电子邮件 使用内联图像:MimeMessageHelperSpring中文文档

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(..)Spring中文文档

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

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

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

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

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

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