package io.micronaut.email.docs;
import io.micronaut.email.BodyType;
import io.micronaut.email.EmailSender;
import io.micronaut.email.Email;
import io.micronaut.email.MultipartBody;
import jakarta.inject.Singleton;
@Singleton
public class WelcomeService {
private final EmailSender<?, ?> emailSender;
public WelcomeService(EmailSender<?, ?> emailSender) {
this.emailSender = emailSender;
}
public void sendWelcomeEmail() {
emailSender.send(Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(new MultipartBody("<html><body><strong>Hello</strong> dear Micronaut user.</body></html>", "Hello dear Micronaut user")));
}
}
Micronaut Email
Integration with Transaction Email Providers
Version: 2.7.1-SNAPSHOT
1 Introduction
The Micronaut Email module provides integration with Transactional email providers such as Amazon Simple Email Service, Postmark, Mailjet or SendGrid.
2 Breaking Changes
Micronaut Email 2
Micronaut Email 2 migrates to Jakarta Mail package namespaces, from javax.mail
to jakarta.mail
. Moreover, it uses transitive dependency jakarta.mail:jakarta.mail-api
instead of com.sun.mail:javax.mail
. Jakarta Mail also separates API and Implementation. Previous implementation sources are now part of the Eclipse Angus project, the direct successor to JavaMail/JakartaMail. In addition to jakarta-mail-api
an additional dependency on org.eclipse.angus:angus-mail
is required. Note that for Eclipse Angus, module and package prefixes changed from com.sun.mail
to org.eclipse.angus.mail
.
This release also updates the ActiveCampaign Postmark library from 1.8.x to 1.9.0. Although it’s a minor revision otherwise it refactors package names and the dependency groupId from com.wildbit.java
to com.postmarkapp
.
3 Release History
For this project, you can find a list of releases (with release notes) here:
4 Quick Start
First, you need to install the dependency and add configuration for your transactional email provider.
Then, you can send an email by injecting a bean of type EmailSender.
package io.micronaut.email.docs
import io.micronaut.email.Email
import io.micronaut.email.EmailSender
import jakarta.inject.Singleton
@Singleton
class WelcomeService {
private final EmailSender<?, ?> emailSender
WelcomeService(EmailSender<?, ?> emailSender) {
this.emailSender = emailSender
}
void sendWelcomeEmail() {
emailSender.send(Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body("<html><body><strong>Hello</strong> dear Micronaut user.</body></html>", "Hello dear Micronaut user"))
}
}
package io.micronaut.email.docs
import io.micronaut.email.EmailSender
import io.micronaut.email.Email
import io.micronaut.email.MultipartBody
import jakarta.inject.Singleton
@Singleton
class WelcomeService(private val emailSender: EmailSender<Any, Any>) {
fun sendWelcomeEmail() {
emailSender.send(
Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(MultipartBody("<html><body><strong>Hello</strong> dear Micronaut user.</body></html>", "Hello dear Micronaut user"))
)
}
}
5 Attachments
To send attachment use the Attachment builder.
package io.micronaut.email.docs;
import io.micronaut.email.Attachment;
import io.micronaut.email.BodyType;
import io.micronaut.email.Email;
import io.micronaut.email.EmailSender;
import io.micronaut.email.MultipartBody;
import io.micronaut.email.test.SpreadsheetUtils;
import io.micronaut.http.MediaType;
import jakarta.inject.Singleton;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@Singleton
public class SendAttachmentService {
private final EmailSender<?, ?> emailSender;
public SendAttachmentService(EmailSender<?, ?> emailSender) {
this.emailSender = emailSender;
}
public void sendReport() throws IOException {
emailSender.send(Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Monthly reports")
.body(new MultipartBody("<html><body><strong>Attached Monthly reports</strong>.</body></html>", "Attached Monthly reports"))
.attachment(Attachment.builder()
.filename("reports.xlsx")
.contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
.content(excel())
.build()));
}
private static byte[] excel() throws IOException {
XSSFWorkbook wb = new XSSFWorkbook();
wb.createSheet("Reports");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
wb.write(bos);
} finally {
bos.close();
}
return bos.toByteArray();
}
}
package io.micronaut.email.docs
import io.micronaut.email.Attachment
import io.micronaut.email.Email
import io.micronaut.email.EmailSender
import io.micronaut.email.MultipartBody
import jakarta.inject.Singleton
import org.apache.poi.xssf.usermodel.XSSFWorkbook
@Singleton
class SendAttachmentService {
private final EmailSender<?, ?> emailSender;
SendAttachmentService(EmailSender<?, ?> emailSender) {
this.emailSender = emailSender;
}
void sendReport() throws IOException {
emailSender.send(Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Monthly reports")
.body(new MultipartBody("<html><body><strong>Attached Monthly reports</strong>.</body></html>", "Attached Monthly reports"))
.attachment(Attachment.builder()
.filename("reports.xlsx")
.contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
.content(excel())
.build()))
}
private static byte[] excel() throws IOException {
XSSFWorkbook wb = new XSSFWorkbook()
wb.createSheet("Reports")
ByteArrayOutputStream bos = new ByteArrayOutputStream()
try {
wb.write(bos)
} finally {
bos.close()
}
bos.toByteArray()
}
}
package io.micronaut.email.docs
import io.micronaut.email.*
import jakarta.inject.Singleton
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.io.ByteArrayOutputStream
@Singleton
class SendAttachmentService(private val emailSender: EmailSender<Any, Any>) {
fun sendWelcomeEmail() {
emailSender.send(
Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Monthly reports")
.body(MultipartBody("<html><body><strong>Attached Monthly reports</strong>.</body></html>", "Attached Monthly reports"))
.attachment(
Attachment.builder()
.filename("reports.xlsx")
.contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
.content(excel())
.build()))
}
private fun excel(): ByteArray {
val wb = XSSFWorkbook()
wb.createSheet("Reports")
val bos = ByteArrayOutputStream()
bos.use { byteArrayOutputStream ->
wb.write(byteArrayOutputStream)
}
return bos.toByteArray()
}
}
6 Decorators
If you send emails always from the same email address you can specify it via configuration and skip populating the from
field when you build the Email.
Property | Type | Description |
---|---|---|
|
java.lang.String |
|
|
java.lang.String |
The name of the contact sending the email. |
By setting micronaut.email.from.email
, Micronaut Email registers a bean of type FromDecorator which populates the from
field if not specified in the construction of the Email.
Moreover, if you have a custom need (e.g. always bcc an email address, adding a prefix to the email subject in a particular environment), you can register a bean of type EmailDecorator.
7 Customizing Emails
If you have a requirement to customize the email being sent — for example adding headers to the email — then you can use the Consumer variant of EmailSender.
Here we show an example for JavaMail using the jakarta.mail.Message class, but this can be altered to the Mail platform request class you are using.
package io.micronaut.email.docs;
import io.micronaut.email.Email;
import io.micronaut.email.EmailSender;
import io.micronaut.email.MultipartBody;
import jakarta.inject.Singleton;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An example of customization for JavaMail messages
*/
@Singleton
public class CustomizedJavaMailService {
private static final Logger LOG = LoggerFactory.getLogger(CustomizedJavaMailService.class);
private final EmailSender<Message, ?> emailSender;
public CustomizedJavaMailService(EmailSender<Message, ?> emailSender) {
this.emailSender = emailSender;
}
public void sendCustomizedEmail() {
Email.Builder email = Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(
new MultipartBody(
"<html><body><strong>Hello</strong> dear Micronaut user.</body></html>",
"Hello dear Micronaut user"
)
);
// Customize the message with a header prior to sending
emailSender.send(email, message -> {
try {
message.addHeader("List-Unsubscribe", "<mailto:list@host.com?subject=unsubscribe>");
} catch (MessagingException e) {
LOG.error("Failed to add header", e);
}
});
}
}
package io.micronaut.email.docs
import io.micronaut.email.Email
import io.micronaut.email.EmailSender
import io.micronaut.email.MultipartBody
import jakarta.inject.Singleton
import jakarta.mail.Message
import jakarta.mail.MessagingException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* An example of customization for JavaMail messages
*/
@Singleton
class CustomizedJavaMailService {
private static final Logger LOG = LoggerFactory.getLogger(CustomizedJavaMailService.class);
private final EmailSender<Message, ?> emailSender
CustomizedJavaMailService(EmailSender<Message, ?> emailSender) {
this.emailSender = emailSender
}
void sendCustomizedEmail() {
def email = Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(
new MultipartBody(
"<html><body><strong>Hello</strong> dear Micronaut user.</body></html>",
"Hello dear Micronaut user"
)
)
// Customize the message with a header prior to sending
emailSender.send(email, message -> {
try {
message.addHeader("List-Unsubscribe", "<mailto:list@host.com?subject=unsubscribe>");
} catch (MessagingException e) {
LOG.error("Failed to add header", e);
}
})
}
}
package io.micronaut.email.docs
import io.micronaut.email.Email
import io.micronaut.email.EmailSender
import io.micronaut.email.MultipartBody
import jakarta.inject.Singleton
import jakarta.mail.Message
import jakarta.mail.MessagingException
import org.slf4j.LoggerFactory
/**
* An example of customization for JavaMail messages
*/
@Singleton
class CustomizedJavaMailService(private val emailSender: EmailSender<Message, *>) {
fun sendCustomizedEmail() {
val email = Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(
MultipartBody(
"<html><body><strong>Hello</strong> dear Micronaut user.</body></html>",
"Hello dear Micronaut user"
)
)
// Customize the message with a header prior to sending
emailSender.send(email) { message: Message ->
try {
message.addHeader("List-Unsubscribe", "<mailto:list@host.com?subject=unsubscribe>")
} catch (e: MessagingException) {
LOG.error("Failed to add header", e)
}
}
}
companion object {
private val LOG = LoggerFactory.getLogger(CustomizedJavaMailService::class.java)
}
}
8 Templates
If you want to send Emails using templates, add the following dependency to your application.
implementation("io.micronaut.email:micronaut-email-template")
<dependency>
<groupId>io.micronaut.email</groupId>
<artifactId>micronaut-email-template</artifactId>
</dependency>
You can use any Template Engines supported by Micronaut Views.
For example, you can use velocity templates for your emails if you include the following dependency:
implementation("io.micronaut.views:micronaut-views-velocity")
<dependency>
<groupId>io.micronaut.views</groupId>
<artifactId>micronaut-views-velocity</artifactId>
</dependency>
Specify the email text or HTML as a TemplateBody to send a template.
A bean of type TemplateBodyDecorator renders those templates.
package io.micronaut.email.docs;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.email.BodyType;
import io.micronaut.email.Email;
import io.micronaut.email.EmailSender;
import io.micronaut.email.MultipartBody;
import io.micronaut.email.template.TemplateBody;
import io.micronaut.views.ModelAndView;
import jakarta.inject.Singleton;
import java.util.Map;
@Singleton
public class WelcomeWithTemplateService {
private final EmailSender<?, ?> emailSender;
public WelcomeWithTemplateService(EmailSender<?, ?> emailSender) {
this.emailSender = emailSender;
}
public void sendWelcomeEmail() {
Map<String, String> model = CollectionUtils.mapOf("message", "Hello dear Micronaut user",
"copyright", "© 2021 MICRONAUT FOUNDATION. ALL RIGHTS RESERVED",
"address", "12140 Woodcrest Executive Dr., Ste 300 St. Louis, MO 63141");
emailSender.send(Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(new MultipartBody(
new TemplateBody<>(BodyType.HTML, new ModelAndView<>("htmltemplate", model)),
new TemplateBody<>(BodyType.TEXT, new ModelAndView<>("texttemplate", model)))));
}
}
package io.micronaut.email.docs
import io.micronaut.email.BodyType
import io.micronaut.email.Email
import io.micronaut.email.EmailSender
import io.micronaut.email.MultipartBody
import io.micronaut.email.template.TemplateBody
import io.micronaut.views.ModelAndView
import jakarta.inject.Singleton
@Singleton
class WelcomeWithTemplateService {
private final EmailSender<?, ?> emailSender
WelcomeWithTemplateService(EmailSender<?, ?> emailSender) {
this.emailSender = emailSender
}
void sendWelcomeEmail() {
Map<String, String> model = [message: "Hello dear Micronaut user",
copyright: "© 2021 MICRONAUT FOUNDATION. ALL RIGHTS RESERVED",
address: "12140 Woodcrest Executive Dr., Ste 300 St. Louis, MO 63141"]
emailSender.send(Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(new MultipartBody(
new TemplateBody(BodyType.HTML, new ModelAndView<>("htmltemplate", model)),
new TemplateBody(BodyType.TEXT, new ModelAndView<>("texttemplate", model)))))
}
}
package io.micronaut.email.docs
import io.micronaut.email.BodyType
import io.micronaut.email.Email
import io.micronaut.email.EmailSender
import io.micronaut.email.MultipartBody
import io.micronaut.email.template.TemplateBody
import io.micronaut.views.ModelAndView
import jakarta.inject.Singleton
@Singleton
class WelcomeWithTemplateService(private val emailSender: EmailSender<Any, Any>) {
fun sendWelcomeEmail() {
val model = mapOf(
"message" to "Hello dear Micronaut user",
"copyright" to "© 2021 MICRONAUT FOUNDATION. ALL RIGHTS RESERVED",
"address" to "12140 Woodcrest Executive Dr., Ste 300 St. Louis, MO 63141"
)
emailSender.send(
Email.builder()
.from("sender@example.com")
.to("john@example.com")
.subject("Micronaut test")
.body(MultipartBody(
TemplateBody(BodyType.HTML, ModelAndView("htmltemplate", model)),
TemplateBody(BodyType.TEXT, ModelAndView("texttemplate", model))))
)
}
}
In the previous example, you could have a Velocity template such as:
src/main/resources/views/texttemplate.vm
Hello
$message
thanks,
Micronaut Framework
$address
$copyright
9 Integrations
9.1 SES
To integrate with Amazon Simple Email Service, add the following dependency to your application.
implementation("io.micronaut.email:micronaut-email-amazon-ses")
<dependency>
<groupId>io.micronaut.email</groupId>
<artifactId>micronaut-email-amazon-ses</artifactId>
</dependency>
This integration uses Micronaut AWS SDK v2 integration.
Read about:
See the guide for Send Emails with Amazon SES from the Micronaut Framework to learn more. |
9.2 Postmark
To integrate with Postmark, add the following dependency to your application.
implementation("io.micronaut.email:micronaut-email-postmark")
<dependency>
<groupId>io.micronaut.email</groupId>
<artifactId>micronaut-email-postmark</artifactId>
</dependency>
You need to supply your Postmark’s API token via configuration:
Property | Type | Description |
---|---|---|
|
boolean |
If Postmark integration is enabled. Default value: |
|
java.lang.String |
|
|
boolean |
Whether to track if the email is opened. Default value: |
|
Whether to track the email’s links. Default value DO_NOT_TRACK. |
9.3 SendGrid
To integrate with SendGrid, add the following dependency to your application.
implementation("io.micronaut.email:micronaut-email-sendgrid")
<dependency>
<groupId>io.micronaut.email</groupId>
<artifactId>micronaut-email-sendgrid</artifactId>
</dependency>
You need to supply your SendGrid’s API key and secret via configuration:
Property | Type | Description |
---|---|---|
|
boolean |
If SendGrid integration is enabled. Default value true |
|
java.lang.String |
See the guide for Send Emails with SendGrid from the Micronaut Framework to learn more. |
9.4 Mailjet
To integrate with Mailjet, add the following dependency to your application.
implementation("io.micronaut.email:micronaut-email-mailjet")
<dependency>
<groupId>io.micronaut.email</groupId>
<artifactId>micronaut-email-mailjet</artifactId>
</dependency>
You need to supply your Mailjet’s API key and secret via configuration:
Property | Type | Description |
---|---|---|
|
boolean |
If Mailjet integration is enabled. Default value: |
|
java.lang.String |
Mailjet API Version. Default value: |
|
java.lang.String |
Mailjet API Key. |
|
java.lang.String |
Mailjet API Secret. |
9.5 Jakarta Mail
To use Jakarta Mail, add the following dependency to your application.
implementation("io.micronaut.email:micronaut-email-javamail")
<dependency>
<groupId>io.micronaut.email</groupId>
<artifactId>micronaut-email-javamail</artifactId>
</dependency>
In addition, you will need to provide a runtime dependency on an implementation of the Jakarta Mail api. Eclipse Angus is the direct successor to prior versions of JavaMail/JakartaMail.
runtimeOnly("org.eclipse.angus:angus-mail")
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-mail</artifactId>
<scope>runtime</scope>
</dependency>
You need to provide beans of type MailPropertiesProvider and SessionProvider to match your configuration.
Authentication via configuration
As an alternative to providing your own SessionProvider for authentication, you can configure password based authentication via configuration:
javamail.authentication.username=my.username
javamail.authentication.password=my.password
javamail:
authentication:
username: 'my.username'
password: 'my.password'
[javamail]
[javamail.authentication]
username="my.username"
password="my.password"
javamail {
authentication {
username = "my.username"
password = "my.password"
}
}
{
javamail {
authentication {
username = "my.username"
password = "my.password"
}
}
}
{
"javamail": {
"authentication": {
"username": "my.username",
"password": "my.password"
}
}
}
10 Guides
See the following list of guides to learn more about working with email in the Micronaut Framework:
11 Repository
You can find the source code of this project in this repository: