Choosing the right email delivery service provider is very crucial for any business. With a good provider, you will always have the confidence that the emails reach the recipient. In spite of that, this does not apply to many providers. As a result, the delivery of the email is not guaranteed or might take very long. In this tutorial, you will learn how to send emails in Spring Boot using Postmark.

Postmark is an email delivery service that ensures your emails get to your inbox. As a matter of time, it takes 5 to 10 seconds for the emails to reach your inbox. This means that the recipient does not have to wait for the email as the delivery is immediate. Let’s get started with the implementation of Postmark.

Prerequisites

Create a new project

To create a new project, Go to Spring initializr to provide the project details. Select the respective sections as shown below.

  • Project – Maven
  • Language – Java
  • Spring Boot – 3.x.x, The version of Spring Boot will vary depending on the time you are reading this article. As a result, the value of x will be the latest version of Spring Boot.

In the Project Metadata section, enter the respective sections as shown below.

  • Group – com.javawhizz
  • Artifact – sendEmail
  • Name – sendEmail
  • Description – Send emails in Spring Boot using Postmark
  • Package name – com.javawhizz.sendEmail
  • Packaging – Jar
  • Java – 17

Next, click the ADD DEPENDENCIES button and add the following dependencies.

  • Spring Web – Supports the development of web applications.
  • Lombok – Assist in the generation of helper methods.
  • Validation – Adds constraints to fields to ensure the data entered by the user is correct.
  • Thymeleaf – Templating engine for the Java programming language.

If you have entered all the details as provided in the previous sections. The project structure and dependencies should be as shown below.

how to send emails in spring boot using  Postmark project structure


Click on the GENERATE button to download a zipped file of your project. Now unzip and import the project in IntelliJ. Before continuing, you should give the application some time to download the dependencies.

Add Postmark dependency

Copy and paste the following code into the pom.xml file. Use the command CTRL+SHIFT+O to reload the Maven changes. As a result, this will download the Postmark dependency and add it to the project’s classpath.

<!-- https://mvnrepository.com/artifact/com.postmarkapp/postmark -->
<dependency>
     <groupId>com.postmarkapp</groupId>
     <artifactId>postmark</artifactId>
     <version>1.10.21</version>
</dependency>

Create the project sub-packages

You should organize the classes in your project based on their responsibilities. As a result, the code will be easy to navigate and make changes in the future. After importing the project into IntelliJ. Create the following sub-packages under the folder src/main/java/com/javawhizz/sendEmail.

  • config
  • controller
  • model
  • service

Add Postmark API key

Open the file named application.properties under the folder src/main/resources. Copy and paste the following property into the file.

postmark.api.secretKey=YOUR_API_KEY

Configure the API key

Create a file named ApiClientConfig.java under the config folder. Copy and paste the following code into the file.

package com.javawhizz.sendEmail.config;

import com.postmarkapp.postmark.Postmark;
import com.postmarkapp.postmark.client.ApiClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApiClientConfig {

    @Value("${postmark.api.secretKey}")
    private String secretKey;

    @Bean
    public ApiClient apiClient(){
        return Postmark.getApiClient(secretKey);
    }
}

Postmark uses ApiClient to send an email. To create an instance of this class, create a @Bean definition that returns ApiClient.

Inside the bean method definition, call Postmark.getApiClient() to return an ApiClient. Note that the getApiClient() method expects the API key as the argument.

Next, inject the API key using @Value annotation, then pass the key as the argument of the method. As a result, you only need to inject ApiClient when sending an email.

Create a message DTO

Create a file named CustomMessage.java under the model package. Next, Copy and paste the following code into the file.

package com.javawhizz.sendEmail.model;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class CustomMessage {
    @Email
    @NotBlank
    private String to;

    @NotBlank
    @Size(min = 10, max = 200)
    private String subject;

    @NotBlank
    @Size(min = 10, max = 200)
    private String message;
}

Add the @Getter and @Setter annotations to the class to generate getter and setter methods. You should also add the @NoArgsContructor to assist in creating empty objects.

This class represents the details of the message to send to the recipient. With regard to the fields, they represent the recipient’s data. The first field is for the recipient’s email, the second is for the context of the email, and the last is for the email body.

To add constraints to the fields, you should also add the field annotations. As a result, this will verify every user input to ensure the fields adhere to the constraints. The following description explains the constraints added by each annotation.

  • @Email – Checks for the correct format of the email.
  • @NotBlank – The field should not be null and should not have whitespace.
  • @Size – The length of the field must be between the least and highest values inclusive.

Create an email service interface

Create a file named EmailService.java under the service package. Next, copy and paste the following code into the file.

package com.javawhizz.sendEmail.service;

import com.javawhizz.sendEmail.model.CustomMessage;
import com.postmarkapp.postmark.client.ApiClient;

public interface EmailService {
    Boolean sendEmail(ApiClient client, CustomMessage customMessage);
}

The method sendEmail() will assist you in isolating the controller from the logic to send an email. In general, when sending an email, you only need to inject the EmailService into the controller. Let’s put in place the implementation of the interface.

Implement the email service interface

Create a file named EmailServiceImpl.java under the service package. Next, copy and paste the following code into the file.

package com.javawhizz.sendEmail.service;

import com.javawhizz.sendEmail.model.CustomMessage;
import com.postmarkapp.postmark.client.ApiClient;
import com.postmarkapp.postmark.client.data.model.message.Message;
import com.postmarkapp.postmark.client.exception.PostmarkException;
import org.springframework.stereotype.Service;

import java.io.IOException;
@Service
public class EmailServiceImpl implements EmailService{
    private static final String FROM = "info@javawhizz.com";

    @Override
    public Boolean sendEmail(ApiClient client, CustomMessage customMessage) {
        boolean isMessageSent = false;
        Message message = new Message(
                FROM,
                customMessage.getTo(),
                customMessage.getSubject(),
                """
                        <!doctype html>
                        <html lang="en">
                          <head>                  
                            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" 
                            rel="stylesheet" 
                            integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9"
                             crossorigin="anonymous">
                          </head>
                          <body>
                          <p>%s</P                
                          <div class="card">
                            <div class="card-body">
                              <h5 class="card-title">JavaWhizz</h5>
                              <p class="card-text">
                              In this tutorial you will learn how to send emails in Spring Boot using Postmark 
                              </p>
                              <p class="card-text">
                              <small class="text-body-secondary">Last updated 3 mins ago
                              </small>
                              </p>
                            </div>
                            <img 
                              src="https://res.cloudinary.com/javawhizz/image/upload/v1690791222/Send_emails_in_Spring_Boot_using_Postmark_cytdkl.png"  
                            class="card-img-bottom" alt="...">
                          </div>
                            
                            <script 
                            src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" 
                            integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" 
                            crossorigin="anonymous"></script>
                          </body>
                        </html>
                                                    
                        """.formatted(customMessage.getMessage())
        );

        message.setMessageStream("announcements");

        try {
            if (client.deliverMessage(message)
                    .getMessageId() != null)
                isMessageSent = true;
        } catch (PostmarkException | IOException e) {
            throw new RuntimeException(e);
        }

        return isMessageSent;
    }
}

Start by defining your sender signature as a class variable. By default, this is the email account that you used to create a Postmark account.

When sending the email the sender’s signature represents the email FROM the sender. Next, create a new instance of Message then pass the expected arguments. The expected arguments are the values CustomMessage passed to the sendEmail() method.

To send a custom template of your email, add the HTML body as the third parameter. You should also include the email body in the template. To achieve this, add a paragraph in the template with the text %s to format the string.

Next, call the method formatted() on the String then pass the method getMessage() as the argument. As a result, the string returned by the method will be the text of the paragraph.

Postmark uses streams to group different types of emails. To set a stream for this email, call the setMessageStream() method from the message object. Next, pass the String announcements as the argument of the method.

The method variable named isMessageSent tracks the status of the sendEmail() method. Before sending any message, the value of the variable is false. After sending a message the value of the variable changes to true. As a result, the method will return false if the message is not delivered and true otherwise.

To send a message call the deliverMessage() method from the client object. Next, pass the message object as the argument of the method.

On successful email delivery, Postmark returns a response containing information about the email. One of the responses returned is the message ID. As a result, you can change the return value of the method depending on whether the message ID has a value or null.

Create the email controller

Create a file named EmailController.java under the controller package. Copy and paste the following code into the file.

package com.javawhizz.sendEmail.controller;

import com.javawhizz.sendEmail.model.CustomMessage;
import com.javawhizz.sendEmail.service.EmailService;
import com.postmarkapp.postmark.client.ApiClient;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
@RequiredArgsConstructor
public class EmailController {
    private final ApiClient apiClient;
    private final EmailService emailService;

    @GetMapping("/")
    public String home(Model model){
        model.addAttribute("customMessage",
                new CustomMessage());
        model.addAttribute("success", 
                false);
        return "index";
    }

    @PostMapping("/send-email")
    public String sendEmail(@ModelAttribute @Valid CustomMessage customMessage,
                            BindingResult bindingResult,
                            Model model){
        if (bindingResult.hasErrors()){
            return "index";
        }

        if (emailService.sendEmail(apiClient, customMessage)){
            model.addAttribute("customMessage", 
                    customMessage);
            model.addAttribute("success", 
                    true);
            return "index";
        }
        model.addAttribute("customMessage", 
                new CustomMessage());
        model.addAttribute("success", 
                false);
        return "index";
    }
}

To create a controller class, you only need to add the @Controller annotation to the class. Next, add the @RequiredArgsContructor to the class. This annotation when assist in creating constructors for the final fields.

Next, inject the ApiClient and the EmailService which you will use to send a message.

When you first access your application, the method named home() gets called. The method returns the HTML file named index.html which contains a form to send an email.

Once you enter the email details and press the send button, the request goes to the sendEmail() method. To send an email, call the sendEmail() method of EmailService and pass the arguments.

The arguments for the method include the injected ApiClient and the CustomMessage. If the delivery of the email is successful, the method shows a success message alert on the same page.

The model attribute named success stores the status of the email delivery. As a result, the value changes depending on whether the method returns true or false.

Create the email page

Create a file named index.html under the folder src/main/resources/templates. Copy and paste the following code into the file.

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap demo</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9"
        crossorigin="anonymous">
</head>
<body>
<div class="container">
  <div class="row">
    <div class="col-md-12">

      <form class="mb-3" th:object="${customMessage}"
            th:action="@{/send-email}"
            method="post">
        <h2>Announce a new tutorial</h2>
        <div class="mb-3">
          <label for="to" class="form-label">To</label>
          <input type="email" th:field="*{to}"
                 class="form-control" id="to"
                 aria-describedby="emailHelp">
          <p th:if="${#fields.hasErrors('to')}"
             th:errors="*{to}"
             style="color: red"/>
        </div>
        <div class="mb-3">
          <label for="subject" class="form-label">Subject</label>
          <input type="text"
                 th:field="*{subject}"
                 class="form-control"
                 id="subject">
          <p th:if="${#fields.hasErrors('subject')}"
             th:errors="*{subject}"
             style="color: red"/>
        </div>
        <div class="form-floating mb-3">
          <textarea class="form-control"
                    th:field="*{message}"
                    placeholder="Announce a new tutorial"
                    id="message"></textarea>
          <label for="message">Message</label>
          <p th:if="${#fields.hasErrors('message')}"
             th:errors="*{message}"
             style="color: red"/>
        </div>
        <button type="submit" class="btn btn-primary">Send</button>
      </form>

      <div class="container alert alert-success" th:if="${success}">
        <div class="row ">
          <div class="col-md-12 d-flex justify-content-center align-items-center">
            <div class="card mt-3">
              <div class="card-body">
                <button type="button" class="btn btn-success">
                  Message sent successfully. Check your inbox!
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm"
        crossorigin="anonymous"></script>
</body>
</html>

This is the form loaded when you first access the application. Note that it contains the three fields in the custom message and uses Thymeleaf as a template engine.

The th tags are Thymeleaf expressions and they will get processed on the server to bind the form data to an object. Once you click on the send button, the /send-email mapping will handle the request.

Any errors entered in the form get checked by the hasErrors() method. As a result, the error also gets displayed in a paragraph next to the input field.

Run and test the application

To run the application, use the command SHIFT+F10. If there were no errors in running the application, go to localhost:8080 on your browser to load the email page. As a result, you should see the following page on your browser.

how to send an email in Spring Boot using Postmark email page

Since you are using Postmark in test mode, you can only send an email to emails of the same domain. In this case, the email used here is sending an email to itself.

To send from other emails in your domain, you need to verify your domain in Postmark. Next, click on the Send button to send the email. If the delivery was successful, you should see the following alert on the same page.

How to send an email in Spring Boot using Postmark success message

As you can see, the delivery of the message is very fast, if you go to your inbox you will find the email you have sent. The contents of the message should be as shown below.

how to send an email in Spring Boot using Postmark

Conclusion

In this tutorial, you have learned how to send emails in Spring Boot using Postmark. Postmark is one of the fastest email delivery services that you can use in your applications.

Note that there are other email delivery services out there there. Some of these services include SendGrid, SparkPost, Mailgun, Amazon SES, and Mandrill. Feel free to try out one of these services and see which works best for you.

At the moment, play around with Postmarks API to learn how to send and receive emails. You can also try sending an email using their SMTP protocol to check whether the email delivery is also as fast.

Happy Hacking!


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *