238 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| [[mail]]
 | |
| = Email
 | |
| 
 | |
| This section describes how to send email with the Spring Framework.
 | |
| 
 | |
| .Library dependencies
 | |
| ****
 | |
| The following JAR needs to be on the classpath of your application in order to use the
 | |
| Spring Framework's email support:
 | |
| 
 | |
| * The https://jakartaee.github.io/mail-api/[Jakarta Mail] library
 | |
| 
 | |
| This library is freely available on the web -- for example, in Maven Central as
 | |
| `com.sun.mail:jakarta.mail`. Please make sure to use the latest 2.x version (which uses
 | |
| the `jakarta.mail` package namespace) rather than Jakarta Mail 1.6.x (which uses the
 | |
| `javax.mail` package namespace).
 | |
| ****
 | |
| 
 | |
| The Spring Framework provides a helpful utility library for sending email that shields
 | |
| you from the specifics of the underlying mailing system and is responsible for
 | |
| low-level resource handling on behalf of the client.
 | |
| 
 | |
| The `org.springframework.mail` package is the root level package for the Spring
 | |
| Framework's email support. The central interface for sending emails is the `MailSender`
 | |
| interface. A simple value object that encapsulates the properties of a simple mail such
 | |
| as `from` and `to` (plus many others) is the `SimpleMailMessage` class. This package
 | |
| also contains a hierarchy of checked exceptions that provide a higher level of
 | |
| abstraction over the lower level mail system exceptions, with the root exception being
 | |
| `MailException`. See the {spring-framework-api}/mail/MailException.html[javadoc]
 | |
| for more information on the rich mail exception hierarchy.
 | |
| 
 | |
| The `org.springframework.mail.javamail.JavaMailSender` interface adds specialized
 | |
| JavaMail features, such as MIME message support to the `MailSender` interface
 | |
| (from which it inherits). `JavaMailSender` also provides a callback interface called
 | |
| `org.springframework.mail.javamail.MimeMessagePreparator` for preparing a `MimeMessage`.
 | |
| 
 | |
| 
 | |
| 
 | |
| [[mail-usage]]
 | |
| == Usage
 | |
| 
 | |
| Assume that we have a business interface called `OrderManager`, as the following example shows:
 | |
| 
 | |
| include-code::./OrderManager[tag=snippet,indent=0]
 | |
| 
 | |
| Further assume that we have a requirement stating that an email message with an
 | |
| order number needs to be generated and sent to a customer who placed the relevant order.
 | |
| 
 | |
| 
 | |
| [[mail-usage-simple]]
 | |
| === Basic `MailSender` and `SimpleMailMessage` Usage
 | |
| 
 | |
| The following example shows how to use `MailSender` and `SimpleMailMessage` to send an
 | |
| email when someone places an order:
 | |
| 
 | |
| include-code::./SimpleOrderManager[tag=snippet,indent=0]
 | |
| 
 | |
| The following example shows the bean definitions for the preceding code:
 | |
| 
 | |
| include-code::./MailConfiguration[tag=snippet,indent=0]
 | |
| 
 | |
| 
 | |
| [[mail-usage-mime]]
 | |
| === Using `JavaMailSender` and `MimeMessagePreparator`
 | |
| 
 | |
| This section describes another implementation of `OrderManager` that uses the `MimeMessagePreparator`
 | |
| callback interface. In the following example, the `mailSender` property is of type
 | |
| `JavaMailSender` so that we are able to use the JavaMail `MimeMessage` class:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	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("mail@mycompany.example"));
 | |
| 					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());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| ----
 | |
| 
 | |
| NOTE: The mail code is a crosscutting concern and could well be a candidate for
 | |
| refactoring into a xref:core/aop.adoc[custom Spring AOP aspect], which could then
 | |
| be run at appropriate joinpoints on the `OrderManager` target.
 | |
| 
 | |
| The Spring Framework's mail support ships with the standard JavaMail implementation.
 | |
| See the relevant javadoc for more information.
 | |
| 
 | |
| 
 | |
| 
 | |
| [[mail-javamail-mime]]
 | |
| == Using the JavaMail `MimeMessageHelper`
 | |
| 
 | |
| A class that comes in pretty handy when dealing with JavaMail messages is
 | |
| `org.springframework.mail.javamail.MimeMessageHelper`, which shields you from
 | |
| having to use the verbose JavaMail API. Using the `MimeMessageHelper`, it is
 | |
| pretty easy to create a `MimeMessage`, as the following example shows:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	// 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);
 | |
| ----
 | |
| 
 | |
| 
 | |
| [[mail-javamail-mime-attachments]]
 | |
| === Sending Attachments and Inline Resources
 | |
| 
 | |
| Multipart email messages allow for both attachments and inline resources. Examples of
 | |
| inline resources include an image or a stylesheet that you want to use in your message but
 | |
| that you do not want displayed as an attachment.
 | |
| 
 | |
| [[mail-javamail-mime-attachments-attachment]]
 | |
| ==== Attachments
 | |
| 
 | |
| The following example shows you how to use the `MimeMessageHelper` to send an email
 | |
| with a single JPEG image attachment:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	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");
 | |
| 
 | |
| 	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);
 | |
| ----
 | |
| 
 | |
| [[mail-javamail-mime-attachments-inline]]
 | |
| ==== Inline Resources
 | |
| 
 | |
| The following example shows you how to use the `MimeMessageHelper` to send an email
 | |
| with an inline image:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	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);
 | |
| 
 | |
| 	sender.send(message);
 | |
| ----
 | |
| 
 | |
| WARNING: Inline resources are added to the `MimeMessage` by using the specified `Content-ID`
 | |
| (`identifier1234` in the above example). The order in which you add the text
 | |
| and the resource are very important. Be sure to first add the text and then
 | |
| the resources. If you are doing it the other way around, it does not work.
 | |
| 
 | |
| 
 | |
| [[mail-templates]]
 | |
| === Creating Email Content by Using a Templating Library
 | |
| 
 | |
| The code in the examples shown in the previous sections explicitly created the content of the email message,
 | |
| by using methods calls such as `message.setText(..)`. This is fine for simple cases, and it
 | |
| is okay in the context of the aforementioned examples, where the intent was to show you
 | |
| the very basics of the API.
 | |
| 
 | |
| In your typical enterprise application, though, developers often do not create the content
 | |
| of email messages by using the previously shown approach for a number of reasons:
 | |
| 
 | |
| * Creating HTML-based email content in Java code is tedious and error prone.
 | |
| * There is no clear separation between display logic and business logic.
 | |
| * Changing the display structure of the email content requires writing Java code,
 | |
|   recompiling, redeploying, and so on.
 | |
| 
 | |
| Typically, the approach taken to address these issues is to use a template library (such
 | |
| as FreeMarker) to define the display structure of email content. This leaves your code
 | |
| tasked only with creating the data that is to be rendered in the email template and
 | |
| sending the email. It is definitely a best practice when the content of your email messages
 | |
| becomes even moderately complex, and, with the Spring Framework's support classes for
 | |
| FreeMarker, it becomes quite easy to do.
 | |
| 
 |