Send mail easily! springboot, sendgrid and greenmail
Tags: microservices, java, mail, sendgrid
Published: 2019-06-24 10:39:29

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](https://sendgrid.com) 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](https://app.sendgrid.com/settings/api_keys).

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

```java
    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:

```java
    @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](https://sendgrid.com/solutions/transactional-email-templates/), 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

```java
    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:

```java
    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.

```java
  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](https://github.com/georgeoikawa/sendgrid-greenmail-client)
ENJOY!!!

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