Email and Java

Email templates

  • https://mailo.app/

 

Mailtrap

Mailtrap allows up to 1,000 emails to be sent per month for free.

  • Please sign up for an account or sign in if you already have an account. 
  • Navigate to your inbox list and click the inbox labeled "My Inbox".
  • Click the Integration tab.
  • Click the API tab.
  • Click the Java tab.
  • Study and copy the code.
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"from\":{\"email\":\"mailtrap@example.com\",\"name\":\"Mailtrap Test\"},\"to\":[{\"email\":\"your-email@example.com\"}],\"subject\":\"You are awesome!\",\"text\":\"Congrats for sending test email with Mailtrap!\",\"category\":\"Integration Test\"}");
Request request = new Request.Builder()
    .url("https://sandbox.api.mailtrap.io/api/send/YOUR-INBOX-ID")
    .method("POST", body)
    .addHeader("Authorization", "Bearer YOUR-TEST-API-CODE")
    .addHeader("Content-Type", "application/json")
    .build();
Response response = client.newCall(request).execute();

OkHttp Dependency

  • Add the OkHttp dependency to the pom.xml file. 
    • This package will allow us to make HTTP requests to third-party APIs.
  • Paste the sample code to the project's main method. 
  • Wrap the execute() method inside a try-catch statement.
try {
    Response response = client.newCall(request).execute();
    System.out.println("Email sent");
} catch (IOException e) {
    System.out.println("Email not sent");
}
  • The RequestBody.create() method has a warning message saying 'create(okhttp3.MediaType, java.lang.String)' is deprecated.
  • Run the program. View your Mailtrap inbox.
  • Note that a real email does not send.

JSON

  • Use a JSON formatter to study how the JSON object is formatted.
  • JavaScript Object Notation (JSON) is made up of "key" : "value" pairs.
    • The keys (from, to, subject, text, category) must be Strings.
    • The values can be objects, arrays, or Strings.
      • Curly brackets indicate an object.
      • Square brackets indicate an array.
      • Quotation marks indicate a String.
{
  "from": {
    "email": "mailtrap@example.com",
    "name": "Mailtrap Test"
  },
  "to": [
    {
      "email": "your-email@example.com"
    }
  ],
  "subject": "You are awesome!",
  "text": "Congrats for sending test email with Mailtrap!",
  "category": "Integration Test"
}

MailtrapPerson class

  • Note that "from" is an object that contains two Strings: email and name.
  • Note that "to" is an array of objects that contains one String: email.
    • The name String is optional.
  • Create a class called MailtrapPerson that represents an individual sender or recipient. Include constructors and getter methods.
public class MailtrapPerson {
    private String email;
    private String name;

    public MailtrapPerson(String email) {
        this.email = email;
        this.name = "";
    }

    public MailtrapPerson(String email, String name) {
        this.email = email;
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public String getName() {
        return name;
    }
 }

MailtrapEmail class

  • Create a class called MailtrapEmail that represents the entire JSON object. Include a constructor and getter methods.
  • Remember that "from" is an object, "to" is a List of objects, and "subject", "text", and "category" are Strings. 
public class MailtrapEmail {
    private MailtrapPerson from;
    private List<MailtrapPerson> to;
    private String subject;
    private String text;
    private String category;

    public MailtrapEmail(MailtrapPerson from, List<MailtrapPerson> to, String subject, String text, String category) {
        this.from = from;
        this.to = to;
        this.subject = subject;
        this.text = text;
        this.category = category;
    }

    public MailtrapPerson getFrom() {
        return from;
    }

    public List<MailtrapPerson> getTo() {
        return to;
    }

    public String getSubject() {
        return subject;
    }

    public String getText() {
        return text;
    }

    public String getCategory() {
        return category;
    }
}

Google Gson, Serialization

  • Add the Google Gson dependency to the pom.xml file.
    • This dependency will be used to convert Java objects to JSON (called serialization) or convert JSON to Java objects (called deserialization).
  • Modify the code to instantiate our custom objects, serialize them, and send the email. 
OkHttpClient client = new OkHttpClient().newBuilder()
        .build();
MediaType mediaType = MediaType.parse("application/json");
MailtrapPerson from = new MailtrapPerson("mailtrap@example.com", "Mailtrap Test");
List<MailtrapPerson> to = new ArrayList<>();
to.add(new MailtrapPerson("your-email@example.com"));
String subject = "You are awesome!";
String text = "Congrats for sending test email with Mailtrap!";
String category = "Integration Test";
MailtrapEmail mailtrapEmail = new MailtrapEmail(from, to, subject, text, category);
String serializedMailtrapEmail = new Gson().toJson(mailtrapEmail);
RequestBody body = RequestBody.create(serializedMailtrapEmail, mediaType);
Request request = new Request.Builder()
        .url("https://sandbox.api.mailtrap.io/api/send/2541140")
        .method("POST", body)
        .addHeader("Authorization", "Bearer 9a7fa0723b331f4eec4d5d5e5a9ba0ea")
        .addHeader("Content-Type", "application/json")
        .build();
try {
    Response response = client.newCall(request).execute();
    System.out.println("Email sent");
} catch (IOException e) {
    System.out.println("Email not sent");
}
  • This code is an example of how Gson can deserialize an object.
String json = "{\"from\":{\"email\":\"mailtrap@example.com\",\"name\":\"Mailtrap Test\"},\"to\":[{\"email\":\"your-email@example.com\"}],\"subject\":\"You are awesome!\",\"text\":\"Congrats for sending test email with Mailtrap!\",\"category\":\"Integration Test\"}";
MailtrapEmail mailtrapEmail = new Gson().fromJson(json, MailtrapEmail.class);
System.out.println(mailtrapEmail.toString());

Google Gson, Deserialization

  • This code is an example of how Gson can deserialize an object.
  • Generate toString methods in the MailtrapEmail and MailtrapPerson classes before running it.
String json = "{\"from\":{\"email\":\"mailtrap@example.com\",\"name\":\"Mailtrap Test\"},\"to\":[{\"email\":\"your-email@example.com\"}],\"subject\":\"You are awesome!\",\"text\":\"Congrats for sending test email with Mailtrap!\",\"category\":\"Integration Test\"}";
try {
    MailtrapEmail mailtrapEmail = new Gson().fromJson(json, MailtrapEmail.class);
    System.out.println(mailtrapEmail.toString());
} catch(JsonSyntaxException e) {
    System.out.println("Invalid JSON");
}
public class MailtrapEmail {
    // Code omitted

    @Override
    public String toString() {
        return "MailtrapEmail{" +
                "from=" + from +
                ", to=" + to +
                ", subject='" + subject + '\'' +
                ", text='" + text + '\'' +
                ", category='" + category + '\'' +
                '}';
    }
}
public class MailtrapPerson {
    // Code omitted

    @Override
    public String toString() {
        return "MailtrapPerson{" +
                "email='" + email + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
  • Keys that are misspelled or have incorrect capitalization will be assigned null values.
  • An invalid JSON String will cause a JsonSyntaxException.

Dotenv

  • Add .env to the .gitignore file so Git does not track our environment variables.
.env
  • Create a .env file in the /src/main/resources folder.
  • The EMAIL_SERVICE variable defines which email service to use.
  • The ADMIN_EMAIL and ADMIN_EMAIL_NAME define the email account I will send emails from.
  • Change the values of MAILTRAP_INBOX and MAILTRAP_KEY to define your personal account info.
EMAIL_SERVICE=mailtrap
ADMIN_EMAIL=YOUR-EMAIL
ADMIN_EMAIL_NAME=YOUR-NAME
MAILTRAP_HOST_URL=YOUR-MAILTRAP-HOST-URL
MAILTRAP_API_TOKEN=YOUR-MAILTRAP-API-TOKEN

MailtrapEmail.send()

  • Create a method called send() in the MailtrapEmail class.
  • Call helper methods to get the environment variables.
  • This method includes code specific to Mailtrap.
public class MailtrapEmail {
    // Code omitted

    public static boolean send(String sendFromEmail, String sendFromName, String sendToEmail, String sendToName, String subject, String message, String category) {
        String hostURL = getURL();
        String apiToken = getToken();
        MailtrapPerson from = new MailtrapPerson(sendFromEmail, sendFromName);
        List<MailtrapPerson> to = new ArrayList<>();
        to.add(new MailtrapPerson(sendToEmail, sendToName));
        MailtrapEmail mailtrapEmail = new MailtrapEmail(from, to, subject, message, category);
        String serializedMailtrapEmail = new Gson().toJson(mailtrapEmail);
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(serializedMailtrapEmail, mediaType);
        Request request = new Request.Builder()
                .url(hostURL)
                .method("POST", body)
                .addHeader("Authorization", "Bearer " + apiToken)
                .addHeader("Content-Type", "application/json")
                .build();
        try(Response response = client.newCall(request).execute()) {
            return response.isSuccessful();
        } catch (IOException e) {
            return false;
        }
    }

    private static String getURL() {
        Dotenv dotenv = Dotenv.load();
        String url = dotenv.get("MAILTRAP_HOST_URL");
        if(url == null) {
            throw new RuntimeException("MAILTRAP_HOST_URL environment variable not set");
        }
        return url;
    }

    private static String getToken() {
        Dotenv dotenv = Dotenv.load();
        String url = dotenv.get("MAILTRAP_API_TOKEN");
        if(url == null) {
            throw new RuntimeException("MAILTRAP_API_TOKEN environment variable not set");
        }
        return url;
    }
}

EmailService.sendTestEmail()

  • Create a new class called EmailService. This class will contain methods to send various emails (examples: user registration, login, password reset, account security, marketing, etc.)
  • Create a method to send a test email. This method should contain generic content that can be used with any email service.
  • Call helper methods to get the environment variables.
public class EmailService {
    public static boolean sendTestEmail(String sendToEmail, String sendToName) {
        boolean sent = false;
        String subject = "You are awesome!";
        String message = "Congrats for sending test email!";
        String emailService = getEmailService();
        String[] sendFrom = getSendFrom("admin");
        if(emailService.equals("mailtrap")) {
            String category = "Integration test";
            sent = MailtrapEmail.send(sendFrom[0], sendFrom[1], sendToEmail, sendToName, subject, message, category);
        }
        return sent;
    }

    private static String getEmailService() {
        Dotenv dotenv = Dotenv.load();
        String emailService = dotenv.get("EMAIL_SERVICE");
        if(emailService == null) {
            throw new RuntimeException("EMAIL_SERVICE environment variable not set");
        }
        return emailService;
    }

    private static String[] getSendFrom(String type) {
        Dotenv dotenv = Dotenv.load();
        String[] sendFrom = new String[2];
        String sendFromEmail = "";
        String sendFromName = "";
        if(type.equals("admin")) {
            sendFromEmail = dotenv.get("ADMIN_EMAIL");
            sendFromName = dotenv.get("ADMIN_EMAIL_NAME");
            if(sendFromEmail == null) {
                throw new RuntimeException("ADMIN_EMAIL environment variable not set");
            }
            if(sendFromName == null) {
                throw new RuntimeException("ADMIN_EMAIL_NAME environment variable not set");
            }
        }
        sendFrom[0] = sendFromEmail;
        sendFrom[1] = sendFromName;
        return sendFrom;
    }
}
public class Main {
    public static void main(String[] args)  {
        boolean sent = EmailService.sendTestEmail("YOUR-EMAIL-ADDRESS", "YOUR-NAME");
        System.out.println(sent ? "Email sent" : "Email not sent");
    }
}
  • Call the sendTestEmail() method from the main method to test it.

Email Domains

  • You must own a domain in order to send real emails. Mailtrap allows one domain for free.
  • These domain registration services offer free domains for students enrolled as a GitHub Student Developer.
  • Go to Mailtrap’s "Sending Domains" section to add your domain.
  • I used Siteground hosting to setup my domain, javability.com

Email Domains

  • From Mailtrap’s "Sending Domains" section, click the Integration tab. Click the blue Integrate button in the Transactional Stream section.
  • Click the API tab, then the Java tab.
  • Notice the code is the same, but the URL and API key are different.
  • Update the .env file with the new URL and API key.
EMAIL_SERVICE=mailtrap
ADMIN_EMAIL=YOUR-DOMAIN-SPECIFIC-EMAIL
ADMIN_EMAIL_NAME=YOUR-NAME
MAILTRAP_HOST_URL=YOUR-MAILTRAP-PRODUCTION-HOST-URL
#YOUR-MAILTRAP-TEST-HOST-URL
MAILTRAP_API_TOKEN=YOUR-MAILTRAP-PRODUCTION-API-TOKEN
#YOUR-MAILTRAP-TEST-API-TOKEN
  • When I tested this, it delivered 24 minutes later to my school email account, and it delivered immediately to my gmail account.
  • From Mailtrap’s "Email API/SMTP" section, visit the subsections to see data about the emails you sent.

More GSON

  • Compare the Google GSON dependency with the Jackson Databind Dependency.
    • https://www.baeldung.com/jackson-vs-gson
  • Save Data to JSON File with GSON
    • https://www.baeldung.com/gson-save-file

Java Send Email

By Marc Hauschildt

Java Send Email

  • 380