Spring provides org.springframework.mail.javamail.MimeMessageHelper
class which act as a Helper class for populating a javax.mail.internet.MimeMessage
. It offers support for HTML text content, inline elements such as images, and typical mail attachments. In other words, it helps preparing a Multi-part MimeMessage’s. Let’s get going.
As we saw in previous tutorial, Spring’s org.springframework.mail.javamail.MimeMessagePreparator
Callback interface comes handy for the preparation of JavaMail MIME messages. We can use both MimeMessagePreparator & MimeMessageHelper to finally create a MimeMessage with attachment or inline content.
Below method returns a MimeMessagePreparator consisting an MimeMessage which in addition to text, contains an image as an attachment.
private MimeMessagePreparator getContentWtihAttachementMessagePreparator(final ProductOrder order) { MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setSubject("Your order on Demoapp with attachement"); helper.setFrom("customerserivces@yourshop.com"); helper.setTo(order.getCustomerInfo().getEmail()); String content = "Dear " + order.getCustomerInfo().getName() + ", thank you for placing order. Your order id is " + order.getOrderId() + "."; helper.setText(content); // Add a resource as an attachment helper.addAttachment("cutie.png", new ClassPathResource("linux-icon.png")); } }; return preparator; }
Below method returns a MimeMessagePreparator consisting an MimeMessage which includes inline resources. Inline resources can be images or a stylesheet included in your message, not as an attachment.
private MimeMessagePreparator getContentAsInlineResourceMessagePreparator(final ProductOrder order) { MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); helper.setSubject("Your order on Demoapp with Inline resource"); helper.setFrom("customerserivces@yourshop.com"); helper.setTo(order.getCustomerInfo().getEmail()); String content = "Dear " + order.getCustomerInfo().getName() + ", thank you for placing order. Your order id is " + order.getOrderId() + "."; // Add an inline resource. // use the true flag to indicate you need a multipart message helper.setText("<html><body><p>" + content + "</p><img src='cid:company-logo'></body></html>", true); helper.addInline("company-logo", new ClassPathResource("linux-icon.png")); } }; return preparator; }
Take special note that inline resources are specified using Content-ID [cid:].
Once you got the MimeMessagePreparator, message can be send using JavaMailSender.
@Autowired JavaMailSender mailSender; mailSender.send(preparator);
Shown below is complete example:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.websystique.spring</groupId> <artifactId>SpringEmailWithAttachmentsExample</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>SpringEmailWithAttachmentsExample</name> <properties> <springframework.version>4.3.0.RELEASE</springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>javax.mail-api</artifactId> <version>1.5.5</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build> </project>
package com.websystique.spring.configuration; import java.util.Properties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; @Configuration @ComponentScan(basePackages = "com.websystique.spring") public class AppConfig { //Put Other Application configuration here. @Bean public JavaMailSender getMailSender(){ JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); //Using gmail mailSender.setHost("smtp.gmail.com"); mailSender.setPort(587); mailSender.setUsername("Your-gmail-id"); mailSender.setPassword("Your-gmail-password"); Properties javaMailProperties = new Properties(); javaMailProperties.put("mail.smtp.starttls.enable", "true"); javaMailProperties.put("mail.smtp.auth", "true"); javaMailProperties.put("mail.transport.protocol", "smtp"); javaMailProperties.put("mail.debug", "true"); mailSender.setJavaMailProperties(javaMailProperties); return mailSender; } }
Please do not forget to update above configuration with your [email] credentials in order to run this example.
package com.websystique.spring.service; import javax.mail.internet.MimeMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessagePreparator; import org.springframework.stereotype.Service; import com.websystique.spring.model.ProductOrder; @Service("mailService") public class MailServiceImpl implements MailService { @Autowired JavaMailSender mailSender; @Override public void sendEmail(Object object) { ProductOrder order = (ProductOrder) object; MimeMessagePreparator preparator = getContentWtihAttachementMessagePreparator(order); try { mailSender.send(preparator); System.out.println("Message With Attachement has been sent............................."); preparator = getContentAsInlineResourceMessagePreparator(order); mailSender.send(preparator); System.out.println("Message With Inline Resource has been sent........................."); } catch (MailException ex) { System.err.println(ex.getMessage()); } } private MimeMessagePreparator getContentWtihAttachementMessagePreparator(final ProductOrder order) { MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setSubject("Your order on Demoapp with attachement"); helper.setFrom("customerserivces@yourshop.com"); helper.setTo(order.getCustomerInfo().getEmail()); String content = "Dear " + order.getCustomerInfo().getName() + ", thank you for placing order. Your order id is " + order.getOrderId() + "."; helper.setText(content); // Add a resource as an attachment helper.addAttachment("cutie.png", new ClassPathResource("linux-icon.png")); } }; return preparator; } private MimeMessagePreparator getContentAsInlineResourceMessagePreparator(final ProductOrder order) { MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); helper.setSubject("Your order on Demoapp with Inline resource"); helper.setFrom("customerserivces@yourshop.com"); helper.setTo(order.getCustomerInfo().getEmail()); String content = "Dear " + order.getCustomerInfo().getName() + ", thank you for placing order. Your order id is " + order.getOrderId() + "."; // Add an inline resource. // use the true flag to indicate you need a multipart message helper.setText("<html><body><p>" + content + "</p><img src='cid:company-logo'></body></html>", true); helper.addInline("company-logo", new ClassPathResource("linux-icon.png")); } }; return preparator; } }
package com.websystique.spring.configuration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import com.websystique.spring.model.CustomerInfo; import com.websystique.spring.model.ProductOrder; import com.websystique.spring.service.OrderService; public class SampleEmailApplication { public static void main(String[] args) { AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); OrderService orderService = (OrderService) context.getBean("orderService"); orderService.sendOrderConfirmation(getDummyOrder()); ((AbstractApplicationContext) context).close(); } public static ProductOrder getDummyOrder(){ ProductOrder order = new ProductOrder(); order.setOrderId("1111"); order.setProductName("Thinkpad T510"); order.setStatus("confirmed"); CustomerInfo customerInfo = new CustomerInfo(); customerInfo.setName("Websystique Admin"); customerInfo.setAddress("WallStreet"); customerInfo.setEmail("websystique@gmail.com"); order.setCustomerInfo(customerInfo); return order; } }
package com.websystique.spring.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.websystique.spring.model.ProductOrder; @Service("orderService") public class OrderServiceImpl implements OrderService{ @Autowired MailService mailService; @Override public void sendOrderConfirmation(ProductOrder productOrder) { mailService.sendEmail(productOrder); } }
package com.websystique.spring.service; import com.websystique.spring.model.ProductOrder; public interface OrderService { public void sendOrderConfirmation(ProductOrder productOrder); }
package com.websystique.spring.service; public interface MailService { public void sendEmail(final Object object); }
package com.websystique.spring.model; public class ProductOrder { private String orderId; private String productName; private String status; private CustomerInfo customerInfo; public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public CustomerInfo getCustomerInfo() { return customerInfo; } public void setCustomerInfo(CustomerInfo customerInfo) { this.customerInfo = customerInfo; } @Override public String toString() { return "ProductOrder [orderId=" + orderId + ", productName=" + productName + ", status=" + status + ", customerInfo=" + customerInfo + "]"; } }
package com.websystique.spring.model; public class CustomerInfo { private String name; private String address; private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "CustomerInfo [name=" + name + ", address=" + address + ", email=" + email + "]"; } }
Run the mail program, and check your [customer] mailbox. You should see two new messages.
One with Attachment.
Other with Inline content.
And finally, the logs.
Jul 06, 2016 12:44:17 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@64964f8e: startup date [Wed Jul 06 00:44:17 CEST 2016]; root of context hierarchy DEBUG: JavaMail version 1.5.5 DEBUG: successfully loaded resource: /META-INF/javamail.default.providers DEBUG: Tables of loaded providers DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]} DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]} DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false 220 smtp.gmail.com ESMTP p126sm453929wmp.13 - gsmtp DEBUG SMTP: connected to host "smtp.gmail.com", port: 587 EHLO 192.168.1.2 250-smtp.gmail.com at your service, [81.243.87.175] 250-SIZE 35882577 250-8BITMIME 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-PIPELINING 250 SMTPUTF8 DEBUG SMTP: Found extension "SIZE", arg "35882577" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SMTPUTF8", arg "" STARTTLS 220 2.0.0 Ready to start TLS EHLO 192.168.1.2 250-smtp.gmail.com at your service, [81.243.87.175] 250-SIZE 35882577 250-8BITMIME 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH 250-ENHANCEDSTATUSCODES 250-PIPELINING 250 SMTPUTF8 DEBUG SMTP: Found extension "SIZE", arg "35882577" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SMTPUTF8", arg "" DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM DEBUG SMTP: AUTH LOGIN command trace suppressed DEBUG SMTP: AUTH LOGIN succeeded DEBUG SMTP: use8bit false MAIL FROM:<customerserivces@yourshop.com> 250 2.1.0 OK p126sm453929wmp.13 - gsmtp RCPT TO:<websystique@gmail.com> 250 2.1.5 OK p126sm453929wmp.13 - gsmtp DEBUG SMTP: Verified Addresses DEBUG SMTP: websystique@gmail.com DATA 354 Go ahead p126sm453929wmp.13 - gsmtp Date: Wed, 6 Jul 2016 00:44:22 +0200 (CEST) From: customerserivces@yourshop.com To: websystique@gmail.com Message-ID: <1541786836.2.1467758662936@dragon> Subject: Your order on Demoapp with attachement MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_0_592641362.1467758658216" ------=_Part_0_592641362.1467758658216 Content-Type: multipart/related; boundary="----=_Part_1_736374497.1467758658232" ------=_Part_1_736374497.1467758658232 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Dear Websystique Admin, thank you for placing order. Your order id is 1111. ------=_Part_1_736374497.1467758658232-- ------=_Part_0_592641362.1467758658216 Content-Type: image/x-png; name=cutie.png Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=cutie.png WXMAAABIAAAASABGyWs+AAAACXZwQWcAAAB4AAAAcADdnEtTAAAp60lEQVR42u19eXiV1bnv75v2 ............... iVBORw0KGgoAAAANSUhEUgAAAH ------=_Part_0_592641362.1467758658216-- . 250 2.0.0 OK 1467758663 p126sm453929wmp.13 - gsmtp QUIT 221 2.0.0 closing connection p126sm453929wmp.13 - gsmtp Message With Attachement has been sent............................. DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false 220 smtp.gmail.com ESMTP jt1sm1022321wjc.8 - gsmtp DEBUG SMTP: connected to host "smtp.gmail.com", port: 587 EHLO 192.168.1.2 250-smtp.gmail.com at your service, [81.243.87.175] 250-SIZE 35882577 250-8BITMIME 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-PIPELINING 250 SMTPUTF8 DEBUG SMTP: Found extension "SIZE", arg "35882577" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SMTPUTF8", arg "" STARTTLS 220 2.0.0 Ready to start TLS EHLO 192.168.1.2 250-smtp.gmail.com at your service, [81.243.87.175] 250-SIZE 35882577 250-8BITMIME 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH 250-ENHANCEDSTATUSCODES 250-PIPELINING 250 SMTPUTF8 DEBUG SMTP: Found extension "SIZE", arg "35882577" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SMTPUTF8", arg "" DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM DEBUG SMTP: AUTH LOGIN command trace suppressed DEBUG SMTP: AUTH LOGIN succeeded DEBUG SMTP: use8bit false MAIL FROM:<customerserivces@yourshop.com> 250 2.1.0 OK jt1sm1022321wjc.8 - gsmtp RCPT TO:<websystique@gmail.com> 250 2.1.5 OK jt1sm1022321wjc.8 - gsmtp DEBUG SMTP: Verified Addresses DEBUG SMTP: websystique@gmail.com DATA 354 Go ahead jt1sm1022321wjc.8 - gsmtp Date: Wed, 6 Jul 2016 00:44:24 +0200 (CEST) From: customerserivces@yourshop.com To: websystique@gmail.com Message-ID: <7787114.5.1467758664694@dragon> Subject: Your order on Demoapp with Inline resource MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_3_424169858.1467758664139" ------=_Part_3_424169858.1467758664139 Content-Type: multipart/related; boundary="----=_Part_4_1524579013.1467758664139" ------=_Part_4_1524579013.1467758664139 Content-Type: text/html;charset=UTF-8 Content-Transfer-Encoding: 7bit <html><body><p>Dear Websystique Admin, thank you for placing order. Your order id is 1111.</p><img src='cid:company-logo'></body></html> ------=_Part_4_1524579013.1467758664139 Content-Type: image/x-png Content-Transfer-Encoding: base64 Content-Disposition: inline Content-ID: <company-logo> iVBORw0KGgoAAAANSUhEUgAAAHgAAABwCAYAAADVN7S/AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBI ....................... mv+KjHUbAAAAAElFTkSuQmCC ------=_Part_4_1524579013.1467758664139-- ------=_Part_3_424169858.1467758664139-- . 250 2.0.0 OK 1467758665 jt1sm1022321wjc.8 - gsmtp QUIT 221 2.0.0 closing connection jt1sm1022321wjc.8 - gsmtp Message With Inline Resource has been sent......................... Jul 06, 2016 12:44:25 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@64964f8e: startup date [Wed Jul 06 00:44:17 CEST 2016]; root of context hierarchy
That’s it. As we saw, it’s rather easy to use Spring’s email support in your own application. Feel free to comment, and suggest improvements.
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
Hi i think that i saw you visited my web site thus i came to Return the favore I am attempting to find things to improve my web siteI suppose its ok to use some of your ideas.
My brother recommended I might like this web site. He was totally right. This post actually made my day. You cann't imagine just how much time I had spent for this information! Thanks!
As a trusted supplier in the plastic industry, Elitepipe Plastic Factory has established long-term partnerships with clients who value their high-quality products and reliable performance. Elitepipe Plastic Factory
Elitepipe Plastic Factory's HDPE fittings are renowned for their versatility, allowing for secure and efficient connections in diverse applications such as water supply, gas distribution, and industrial pipelines. Elitepipe Plastic Factory
Good, how to send email with attachment generate pdf itext or apache poi xls