メール
このセクションでは、Spring Framework を使用してメールを送信する方法について説明します。
Spring Framework は、メールを送信するための有用なユーティリティライブラリを提供します。このライブラリは、基礎となるメールシステムの詳細からユーザーを保護し、クライアントに代わって低レベルのリソース処理を行います。
org.springframework.mail
パッケージは、Spring Framework のメールサポートのルートレベルパッケージです。メールを送信するための中心的なインターフェースは、MailSender
インターフェースです。from
や to
(その他多数)などの単純なメールのプロパティをカプセル化する単純な値オブジェクトは、SimpleMailMessage
クラスです。このパッケージには、チェック例外の階層も含まれており、下位レベルのメールシステム例外よりも高いレベルの抽象化を提供します。ルート例外は MailException
です。リッチメールの例外階層の詳細については、javadoc を参照してください。
org.springframework.mail.javamail.JavaMailSender
インターフェースは、MIME メッセージのサポートなどの特殊な JavaMail 機能を(継承元の) MailSender
インターフェースに追加します。JavaMailSender
は、MimeMessage
を準備するための org.springframework.mail.javamail.MimeMessagePreparator
と呼ばれるコールバックインターフェースも提供します。
使用方法
次の例に示すように、OrderManager
というビジネスインターフェースがあると仮定します。
Java
Kotlin
public interface OrderManager {
void placeOrder(Order order);
}
interface OrderManager {
fun placeOrder(order: Order)
}
さらに、オーダー番号付きのメールメッセージを生成し、関連するオーダーを行った顧客に送信する必要があるという要件があると仮定します。
MailSender
および SimpleMailMessage
の基本的な使用箇所
次の例は、MailSender
および SimpleMailMessage
を使用して、誰かがオーダーしたときにメールを送信する方法を示しています。
Java
Kotlin
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;
}
@Override
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());
}
}
}
class SimpleOrderManager : OrderManager {
lateinit var mailSender: MailSender
lateinit var templateMessage: SimpleMailMessage
override fun 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
val msg = SimpleMailMessage(this.templateMessage)
msg.setTo(order.customer.emailAddress)
msg.text = ("Dear " + order.customer.firstName
+ order.customer.lastName
+ ", thank you for placing order. Your order number is "
+ order.orderNumber)
try {
mailSender.send(msg)
} catch (ex: MailException) {
// simply log it and go on...
System.err.println(ex.message)
}
}
}
次の例は、前述のコードの Bean 定義を示しています。
Java
Kotlin
XML
@Bean
JavaMailSender mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("mail.mycompany.example");
return mailSender;
}
@Bean // this is a template message that we can pre-load with default state
SimpleMailMessage templateMessage() {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("[email protected] (英語) ");
message.setSubject("Your order");
return message;
}
@Bean
SimpleOrderManager orderManager(JavaMailSender mailSender, SimpleMailMessage templateMessage) {
SimpleOrderManager orderManager = new SimpleOrderManager();
orderManager.setMailSender(mailSender);
orderManager.setTemplateMessage(templateMessage);
return orderManager;
}
@Bean
fun mailSender(): JavaMailSender {
return JavaMailSenderImpl().apply {
host = "mail.mycompany.example"
}
}
@Bean // this is a template message that we can pre-load with default state
fun templateMessage() = SimpleMailMessage().apply {
from = "[email protected] (英語) "
subject = "Your order"
}
@Bean
fun orderManager(javaMailSender: JavaMailSender, simpleTemplateMessage: SimpleMailMessage) = SimpleOrderManager().apply {
mailSender = javaMailSender
templateMessage = simpleTemplateMessage
}
<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>
JavaMailSender
および MimeMessagePreparator
の使用
このセクションでは、MimeMessagePreparator
コールバックインターフェースを使用する OrderManager
の別の実装について説明します。次の例では、mailSender
プロパティの型は JavaMailSender
であるため、JavaMail MimeMessage
クラスを使用できます。
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 を参照してください。
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);
添付ファイルとインラインリソースの送信
マルチパートメールメッセージでは、添付ファイルとインラインリソースの両方を使用できます。インラインリソースの例には、メッセージで使用したいが添付ファイルとして表示したくないイメージまたはスタイルシートが含まれます。
添付
次の例は、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 )を使用して MimeMessage に追加されます。テキストとリソースを追加する順序は非常に重要です。最初にテキストを追加してから、リソースを追加してください。逆にそれをやっていると、うまくいきません。 |
テンプレートライブラリを使用してメールコンテンツを作成する
前のセクションで示した例のコードは、message.setText(..)
などのメソッド呼び出しを使用して、メールメッセージのコンテンツを明示的に作成しました。これは単純なケースでは問題ありませんが、前述の例のコンテキストでは問題ありません。この例では、API の基本を説明することを目的としています。
ただし、一般的なエンタープライズアプリケーションでは、多くの場合、開発者は前述のアプローチを使用してメールメッセージのコンテンツを作成しません。
Java コードで HTML ベースのメールコンテンツを作成するのは面倒でエラーが発生しやすくなります。
表示ロジックとビジネスロジックの間には明確な分離はありません。
メールコンテンツの表示構造を変更するには、Java コードの記述、再コンパイル、再デプロイなどが必要です。
通常、これらの課題に対処するために取られるアプローチは、テンプレートライブラリ(FreeMarker など)を使用してメールコンテンツの表示構造を定義することです。これにより、コードは、メールテンプレートでレンダリングされるデータの作成とメールの送信のみに任されます。メールメッセージの内容がやや複雑になる場合は間違いなくベストプラクティスであり、Spring Framework の FreeMarker のサポートクラスを使用すると、非常に簡単になります。