DEV Community 👩‍💻👨‍💻

George
George

Posted on

Send mail easily! springboot, sendgrid and greenmail

This is a brief presentation for the use sendgrid email provider's api.
** Clone the github repository in order to get more details! **
I'm using this api through a sendgrid java client and inside a microservice made with springboot, and like all good code, is a tested code, let's use the greenmail library to simulate a smtp server to receive the emails.

First of all you need to create an account in Sendgrid and enable an api Key to use in client.

There are some ways to use this sendgrid sdk and in this case will be approached the sending of e-mail that will be transferred by http connection in json format. There is another way to send an email, which would be to register a template in the administrative panel of sendgrid site and send it through the client with the key of the registered template. To do any invocation of sendgrid it is necessary to send the key, which is available in the sendgrid admin area.

To call the sendgrid api it is necessary to build the request object like as below.

    public class RequestSendGridBuilder {
        private static final String MIME_TYPE_HTML = "text/html";
        private static final String ENDPOINT_MAIL_SEND = "mail/send";
        private Mail mail = new Mail();
        private Content content = new Content();
        public static RequestSendGridBuilder of() {
            return new RequestSendGridBuilder();
        }

        public RequestSendGridBuilder from(String from) {
            mail.setFrom(new Email(from));
            return this;
        }

        public RequestSendGridBuilder key(String key) {
            mail.addCustomArg("customerAccountNumber", key);
            return this;
        }

        public RequestSendGridBuilder content(String template) {
            content.setType(MIME_TYPE_HTML);
            content.setValue(template);
            return this;
        }

        public RequestSendGridBuilder subject(String subject) {
            mail.setSubject(subject);
            return this;
        }

        public RequestSendGridBuilder to(String to) {
            Personalization personalization = new Personalization();
            personalization.addTo(new Email(to));
            mail.addPersonalization(personalization);
            return this;
        }

        public Request build() throws IOException {
            mail.addContent(content);
            Request request = new Request();
            request.setMethod(Method.POST);
            request.setEndpoint(ENDPOINT_MAIL_SEND);
            request.setBody(mail.build());
            return request;
        }
    }

and after this call the service:

    @Override
    public EmailResponseDTO send(EmailRequestDTO request) throws EmailConnectionException {
        try {
            Request sendGridRequest = RequestSendGridBuilder.of()
                    .content(request.getContent())
                    .subject(request.getSubject())
                    .to(request.getTo())
                    .from(request.getFrom())
                    .key(sendGridKey)
                    .build();
            Response sendGridResponse = sendGrid.api(sendGridRequest);
            return getResponse(sendGridResponse, sendGridRequest);
        } catch (IOException e) {
            throw new EmailConnectionException(e);
        }
    }

Yes, this is very simple! but don't forget to set the sendgrid API_KEY, otherwise, it will not work.

Templates

It's possible use your own template engine, as long as you send a json with your html content. In this case, you will have your template (html for example) within your project and to update it is necessary a new deploy.

If you don't want to traffic large size of bytes over the network because of a very large email, it is possible, as previously said, to write your template in the administrative template panel, after creating the template, a key will be generated to identify it, and this key will be sent by the client to the service, so you do not have to traffic all the content of the email. In addition you will be able to update your template at runtime directly on the site https://sendgrid.com

    mail.setTemplateId(templateId);

    Request request = new Request();
    request.setMethod(Method.POST);
    request.setEndpoint(ENDPOINT_MAIL_SEND);
    request.setBody(mail.build());
    Response sendGridResponse = sendGrid.api(request);

Template parser parameters

In this example I have used mustache to make parse parameters to template.
It's very simple to use and very efficient library. To change the values of template variables simply pass a map of strings to the mustache engine, like below:

    public class TemplateService {
        private MustacheAutoConfiguration mustacheAutoConfiguration;

        public TemplateService(MustacheAutoConfiguration mustacheAutoConfiguration) {
            this.mustacheAutoConfiguration = mustacheAutoConfiguration;
        }

        public @NonNull String parseTemplateParams(EmailRequestDTO email) throws TemplateException {
            try {
                MustacheResourceTemplateLoader templateLoader = mustacheAutoConfiguration.mustacheTemplateLoader();
                Reader template = templateLoader.getTemplate(email.getTemplateName());
                return mustacheAutoConfiguration.mustacheCompiler(templateLoader)
                        .compile(template)
                        .execute(email.getTemplateParams());
            } catch (FileNotFoundException e) {
                throw new TemplateException("TEMPLATE_NOT_FOUND");
            } catch (MustacheException e) {
                throw new TemplateException("TEMPLATE_PARSE_ERROR", e);
            } catch (Exception e) {
                throw new TemplateException("GENERIC_ERROR", e);
            }
        }
    }

Test sending with a fake smtp mail server

To create e-mail integration tests I am using the greenmail library. This library allows you to create a fake smtp server that will receive the emails sent by the client, so it is possible to guarantee better eligibility, and efficiency in your implementation.

  public static GreenMail getGreenMail() {
        if (greenMail == null) {
            ServerSetup serverSetup = new ServerSetup(
                    SocketUtils.findAvailableTcpPort(
                            INIT_RANGE_EMAIL_PORT,
                            END_RANGE_EMAIL_PORT),
                    ServerSetup.getLocalHostAddress(),
                    ServerSetup.PROTOCOL_SMTP);
            greenMail = new GreenMail(serverSetup);
            greenMail.setUser(
                    EMAIL_USER_ADDRESS,
                    USER_NAME,
                    USER_PASSWORD);
            greenMail.start();
        }
        return greenMail;
    }

Source code

To see the client working you can use the complete code here
ENJOY!!!

References

http://www.icegreen.com/greenmail/
https://sendgrid.com/docs/api-reference/

Top comments (1)

Collapse
 
hendisantika profile image
Hendi Santika

Nice sample. But, If We're using Spring Boot latest version 2.6.3 this method doesn't work. public @NonNull
String parseTemplateParams(EmailRequestDTO email) throws TemplateException {
try {
MustacheResourceTemplateLoader templateLoader = mustacheAutoConfiguration.mustacheTemplateLoader();
Reader template = templateLoader.getTemplate(email.getTemplateName());
return mustacheAutoConfiguration.mustacheCompiler(templateLoader)

Any suggestion?
Thanks

🌚 Life is too short to browse without dark mode