SendGrid Dynamic Template

Usually, in most email services, a dynamic template with placeholders is present in the source code. Every time a mail needs to be sent, placeholders will be filled, and HTML in String format will be created and posted to the SMTP server.

this takes a lot of time and increases the payload size which eventually decreases the API response time.
SendGrid provides an alternative way, instead of storing dynamic template in the system, save it in SendGrid Dynamic template section, and just send the Object with placeholder values in the API call, 
SendGrid will fill the placeholders with respective values and send the mail.

SendGrid uses Mustache/Handlebars as the dynamic template email engine.

Currently, there is no way to create a dynamic template via API call, go to https://mc.sendgrid.com/dynamic-templates  in web UI, Create a Dynamic Template, paste the Mustache HTML code, copy the dynamic template id.

 

SendGrid provides the option to directly paste the JSON object in the dynamic template section and live test the template.

dynamic template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
name is :- {{templateObject.name}}
<br>

boolean output :-
{{#templateObject.trueFlag}}
    true flag :<p>{{templateObject.name}}</p>
{{/templateObject.trueFlag}}
<br>

boolean false :-
{{^templateObject.falseFlag}}
    false flag : <p>{{templateObject.name}}</p>
{{/templateObject.falseFlag}}
<br>

href :-
<a href="{{templateObject.websiteUrl}}?">WeSome</a>
<br>
<br>
image :-
<br>
<img width="200px" height="100px" src="{{templateObject.imageUrl}}" alt="{{templateObject.imageAlt}}">
<br>

List of object output directly :-
{{#templateObject.courses}}
    {{.}}
{{/templateObject.courses}}
<br>
<br>

List output :-
<p>course name :- {{templateObject.course.courseName}}</p>
<p>course type :- {{templateObject.course.courseType}}</p>
<p>course price :- {{templateObject.course.price}}</p>

<br>
List of object output :-
{{#templateObject.courses}}
    {{courseName}}
    {{courseType}}
    {{price}}
{{/templateObject.courses}}

<br>
<br>
List of object output in table format :-
<table border="1">
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Price</th>
    </tr>
    {{#templateObject.courses}}
        <tr>
            <td>{{courseName}}</td>
            <td>{{courseType}}</td>
            <td>{{price}}</td>
        </tr>
    {{/templateObject.courses}}
</table>

</body>
</html>
{
  "templateObject": {
    "name": "wesome",
    "trueFlag": true,
    "falseFlag": false,
    "websiteUrl": "wesome.org",
    "imageUrl": "https://wesome.org/sites/default/files/inline-images/twilio_sendgrid_logo.png",
    "imageAlt": "wesome.org",
    "courses": [
      {
        "courseName": "Junit 5",
        "courseType": "Testing Framework",
        "price": "$0"
      },
      {
        "courseName": "Mockito 3",
        "courseType": "Mocking Framework",
        "price": "$0"
      }
    ],
    "course": {
      "courseName": "SendGrid",
      "courseType": "Email Communication Solution",
      "price": "$0"
    }
  }
}
package org.wesome.sendgrid;

import com.sendgrid.SendGrid;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SendGridApplication {
    @Value("${send.grid.api.key}")
    private String sendGridApiKey;

    public static void main(String[] args) {
        SpringApplication.run(SendGridApplication.class, args);
    }

    @Bean
    public SendGrid sendGrid() {
        SendGrid sendGrid = new SendGrid(sendGridApiKey);
        return sendGrid;
    }
}
package org.wesome.sendgrid.model;

import lombok.Data;

import java.util.List;

@Data
public class MainObject {
    TemplateObject templateObject;

    @Data
    static class Course {
        public String courseName;
        public String courseType;
        public String price;

    }

    @Data
    public static class TemplateObject {
        public String name;
        public boolean trueFlag;
        public boolean falseFlag;
        public String websiteUrl;
        public String imageUrl;
        public String imageAlt;
        public List<Course> courses;
        public Course course;
    }
}
package org.wesome.sendgrid.controller;

import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import com.google.gson.Gson;
import com.sendgrid.Method;
import com.sendgrid.Request;
import com.sendgrid.Response;
import com.sendgrid.SendGrid;
import com.sendgrid.helpers.mail.Mail;
import com.sendgrid.helpers.mail.objects.Email;
import com.sendgrid.helpers.mail.objects.Personalization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.wesome.sendgrid.model.MainObject;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.util.Objects;

@RestController
public class SendGridController {
    @Autowired
    private SendGrid sendGrid;

    @Value("${send.grid.api.template.id}")
    private String templateId;

    @GetMapping
    public ResponseEntity sendGridAPI() throws IOException {
        MainObject mainObject = getObjectFromJson();
        createLocalHtmlFile(mainObject);
        Response response = sendEmail(mainObject);
        return new ResponseEntity(HttpStatus.valueOf(response.getStatusCode()).getReasonPhrase(), HttpStatus.valueOf(response.getStatusCode()));
    }

    private MainObject getObjectFromJson() throws IOException {
        final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        final File file = new File(Objects.requireNonNull(classLoader.getResource("sample.json")).getFile());
        final String content = new String(Files.readAllBytes(file.toPath()));
        final Gson gson = new Gson();
        final MainObject mainObject = gson.fromJson(content, MainObject.class);
        return mainObject;
    }


    private void createLocalHtmlFile(MainObject mainObject) {
        MustacheFactory mf = new DefaultMustacheFactory();
        Mustache m = mf.compile("email.mustache");
        StringWriter writer = new StringWriter();
        String messageText = "";
        try {
            m.execute(writer, mainObject).flush();
            messageText = writer.toString();
            FileWriter fWriter = new FileWriter("mustache.html");
            final BufferedWriter bufferedWriter = new BufferedWriter(fWriter);
            bufferedWriter.write(messageText);
            bufferedWriter.newLine();
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Response sendEmail(MainObject mainObject) {
        Request request = new Request();
        try {
            Mail dynamicTemplate = buildDynamicTemplate(mainObject);
            request.setMethod(Method.POST);
            request.setEndpoint("mail/send");
            request.setBody(dynamicTemplate.build());
            Response response = sendGrid.api(request);
            response = sendGrid.api(request);
            System.out.println("Headers := \n" + response.getHeaders());
            System.out.println("Body := \n" + response.getBody());
            System.out.println("StatusCode := \n" + response.getStatusCode());
            return response;
        } catch (IOException ex) {
            System.out.println("ex = " + ex);
        }
        return null;
    }


    public Mail buildDynamicTemplate(MainObject mainObject) throws IOException {
        Mail mail = new Mail();
        Email fromEmail = new Email();
        fromEmail.setName("wesome");
        fromEmail.setEmail("[email protected]");
        mail.setFrom(fromEmail);
        mail.setTemplateId(templateId);
        Personalization personalization = new Personalization();
        personalization.setSubject("learning SendGrid from wesome.org");
        personalization.addDynamicTemplateData("templateObject", mainObject.getTemplateObject());
        personalization.addTo(new Email("[email protected]"));
        mail.addPersonalization(personalization);
        return mail;
    }
}
plugins {
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'org.springframework.boot' version '2.5.5'
    id 'io.freefair.lombok' version '6.0.0-m2'
    id 'java'
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

repositories {
    mavenCentral()
}
dependencies {
    implementation 'com.sendgrid:sendgrid-java:4.7.2'
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('com.github.spullara.mustache.java:compiler:0.9.5')
    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.7'
}

test {
    useJUnitPlatform()
}
send.grid.api.key=Your SendGrid Api Key
send.grid.api.template.id=d-c8e7be772bad40e3a9165e6477729ea0
curl --location --request GET 'http://localhost:8080'

follow us on