Micronaut Email

Integration with Transaction Email Providers

Version:

1 Introduction

The Micronaut Email module provides integration with Transactional email providers such as Amazon Simple Email Service, Postmark, Mailjet or SendGrid.

2 Release History

For this project, you can find a list of releases (with release notes) here:

3 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.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")));
    }
}
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"))
        )
    }
}

4 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()
    }
}

5 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.

🔗
Table 1. Configuration Properties for FromConfigurationProperties
Property Type Description

micronaut.email.from.email

java.lang.String

Default from email address.

micronaut.email.from.name

java.lang.String

From name

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.

6 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

7 Integrations

7.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:

7.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:

🔗
Table 1. Configuration Properties for PostmarkConfigurationProperties
Property Type Description

postmark.enabled

boolean

If Postmark integration is enabled. Default value: true

postmark.api-token

java.lang.String

Postmark API token.

postmark.track-opens

boolean

Whether to track if the email is opened. Default value: false

postmark.track-links

TrackLinks

Whether to track the email’s links. Default value DO_NOT_TRACK.

7.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:

🔗
Table 1. Configuration Properties for SendGridConfigurationProperties
Property Type Description

sendgrid.api-key

java.lang.String

The API (Application Programming Interface) keys to authenticate access to SendGrid service.

sendgrid.enabled

boolean

If SendGrid integration is enabled. Default value true

7.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:

🔗
Table 1. Configuration Properties for MailjetConfigurationProperties
Property Type Description

mailjet.enabled

boolean

If Mailjet integration is enabled. Default value: true

mailjet.version

java.lang.String

Mailjet API Version. Default value: "v3.1"

mailjet.api-key

java.lang.String

Mailjet API Key.

mailjet.api-secret

java.lang.String

Mailjet API Secret.

7.5 JavaMail

To use JavaMail, 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>

You need to provide beans of type MailPropertiesProvider and SessionProvider to match your configuration.

8 Repository

You can find the source code of this project in this repository: