Make sure you have Domain or Account Admin permission for the domain you’ll use to send emails. If not, contact your Account Admin or Owner to grant you the permission.
Then, you can click the More menu (three vertical dots) and hit Copy token to copy it to your clipboard.
Step 3 – Create an email sender class
Like with SMTP, I’ll create an email sender class, only this time it’s designed for API calls.
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.IOException;
public class MailtrapApiEmailSender {
private final String mailtrapApiToken;
private final OkHttpClient client = new OkHttpClient();
public MailtrapApiEmailSender(String mailtrapApiToken) {
this.mailtrapApiToken = mailtrapApiToken;
}
public void sendEmail(String recipient, String subject, String body) throws IOException {
OkHttpClient client = new OkHttpClient();
String json = "{\n" +
" \"to\": [\n" +
" {\n" +
" \"email\": \"" + recipient + "\",\n" +
" \"name\": \"Recipient Name\"\n" +
" }\n" +
" ],\n" +
" \"from\": {\n" +
" \"email\": \"anyname@freelance.mailtrap.link\",\n" +
" \"name\": \"Sender Name\"\n" +
" },\n" +
" \"subject\": \"" + subject + "\",\n" +
" \"text\": \"" + body + "\"\n" +
"}";
MediaType mediaType = MediaType.parse("application/json");
RequestBody requestBody = RequestBody.create(json, mediaType);
Request request = new Request.Builder()
.url("https://send.api.mailtrap.io/api/send")
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Api-Token", token)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(@NonNull okhttp3.Call call, @NonNull Response response) {
sbSendEmail.dismiss();
if (response.isSuccessful()) {
Snackbar.make(binding.getRoot(), "Email Sent!", Snackbar.LENGTH_LONG).show();
} else {
Snackbar.make(binding.getRoot(), "Something Went Wrong!", Snackbar.LENGTH_LONG).show();
}
}
@Override
public void onFailure(@NonNull okhttp3.Call call, @NonNull IOException e) {
e.printStackTrace();
Snackbar.make(binding.getRoot(), "Something Went Wrong!", Snackbar.LENGTH_LONG).show();
}
});
}
}
Copy
Step 4 – Implement asynchronous email sending
Again, you want to avoid operations on the main thread, and I’ll be using the AsyncTask
.
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
new MailtrapApiEmailSender("your_mailtrap_api_token").sendEmail("to@example.com", "Subject", "Email Body");
} catch (IOException e) {
e.printStackTrace(); // Handle exceptions appropriately
}
return null;
}
}.execute();
Copy
Step 5 – Error handling and security
In the example above, the error handling is managed through the try-catch
block. The current implementation throws a generic IOException
for any unsuccessful response.
A more robust approach would be to analyze the response further and throw different exceptions based on the exact issue (e.g., authentication failure, rate limiting, invalid request format). Here’s an example of the extended error handling:
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
handleErrorResponse(response);
}
// Handle successful response or return it
}
}
private void handleErrorResponse(Response response) throws EmailSendingException, IOException {
switch (response.code()) {
case 401:
throw new EmailSendingException("Authentication failed.");
case 429:
throw new EmailSendingException("Rate limit exceeded.");
case 400:
throw new EmailSendingException("Invalid request format.");
default:
throw new IOException("Unexpected code " + response);
}
}
// Custom exception for email sending errors
public static class EmailSendingException extends Exception {
public EmailSendingException(String message) {
super(message);
}
}
}
Copy
As always, you should avoid exposing your API token in the code.
In the example under Step 3, the API token is passed to the MailtrapApiEmailSender
constructor, meaning it’s not hardcoded within the class. This is a good practice as it allows the token to be stored and retrieved securely from outside the class, such as from encrypted storage or a secure server.
The code uses HTTPS (https://send.api.mailtrap.io/api/send) for sending requests, which is critical for ensuring the data transmitted is encrypted and secure from eavesdropping or man-in-the-middle attacks.
Yeah, there’s still room for improvement. I won’t go into code examples here, but just list the points you may consider implementing, particularly if you wish to send at a volume.
- Token exposure: Although the token isn’t hardcoded, it’s still passed around, which could expose it to risks if not handled carefully. Ideally, the token should be accessed in a way that minimizes its exposure in memory and logs.
- Error logging: While not directly a security issue, careful error logging (without exposing sensitive information like tokens) can help identify and address security-related issues more quickly.
- Input validation: Before creating the JSON request, validating inputs like recipient, subject, and body can prevent injection attacks or unintended errors.
Send HTML email
I’ll continue with the example used for the API method and adjust the MailtrapApiEmailSender
class. Here’s the updated implementation:
import okhttp3.*;
import java.io.IOException;
public class MailtrapApiEmailSender {
private final String mailtrapApiToken;
private final OkHttpClient client = new OkHttpClient();
public MailtrapApiEmailSender(String mailtrapApiToken) {
this.mailtrapApiToken = mailtrapApiToken;
}
public void sendEmail(String recipient, String subject, String htmlBody) throws IOException, EmailSendingException {
// Construct JSON payload with HTML content
String json = "{\"to\": \"" + recipient + "\", \"subject\": \"" + subject + "\", \"html_body\": \"" + htmlBody + "\"}";
RequestBody requestBody = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url("https://send.api.mailtrap.io/api/send")
.addHeader("Authorization", "Bearer " + mailtrapApiToken)
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
handleErrorResponse(response);
}
// Handle or log the successful response
}
}
private void handleErrorResponse(Response response) throws EmailSendingException, IOException {
switch (response.code()) {
case 401:
throw new EmailSendingException("Authentication failed.");
case 429:
throw new EmailSendingException("Rate limit exceeded.");
case 400:
throw new EmailSendingException("Invalid request format.");
default:
throw new IOException("Unexpected code " + response);
}
}
public static class EmailSendingException extends Exception {
public EmailSendingException(String message) {
super(message);
}
}
}
Copy
In this code:
- HTML email content: The method
sendEmail
now accepts htmlBody
as a parameter, which should contain your HTML-formatted email content. - JSON payload: The JSON payload sent to the Mailtrap API includes the
html_body
field, ensuring the email body is treated as HTML. - Error handling: The method
handleErrorResponse
interprets different HTTP response codes to throw specific exceptions, offering more detailed insights into potential issues. - Custom exception: EmailSendingException is used to indicate issues specific to the email-sending process.
Send email with attachments
Again, I’m extending the example above and its MailtrapApiEmailSender
class. Simply put, I’m modifing the way the request body gets created. And since Mailtrap Email API expects the attachments to be sent as part of a multipart request, I’ll adjust the code accordingly.
import okhttp3.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class MailtrapApiEmailSender {
private final String mailtrapApiToken;
private final OkHttpClient client = new OkHttpClient();
public MailtrapApiEmailSender(String mailtrapApiToken) {
this.mailtrapApiToken = mailtrapApiToken;
}
public void sendEmailWithAttachments(String recipient, String subject, String htmlBody, List<String> attachmentPaths) throws IOException, EmailSendingException {
// Building the multipart request
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("to", recipient)
.addFormDataPart("subject", subject)
.addFormDataPart("html_body", htmlBody);
// Adding attachments
for (String filePath : attachmentPaths) {
File file = new File(filePath);
builder.addFormDataPart("attachment", file.getName(),
RequestBody.create(file, MediaType.parse("application/octet-stream")));
}
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url("https://send.api.mailtrap.io/api/send")
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Api-Token", mailtrapApiToken)
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
handleErrorResponse(response);
}
// Handle or log the successful response
}
}
private void handleErrorResponse(Response response) throws EmailSendingException, IOException {
// Error handling logic as before
}
// Custom exception class as before
Copy
In this code:
- Multipart request: The
MultipartBody.Builder
is used to create a multipart request. This is necessary because attachments are binary data and need to be sent differently compared to regular text fields. - Adding fields and attachments: The
to
, subject
, and html_body
are added as form data parts. Each attachment is added as a separate form data part with its content type specified as "application/octet-stream"
. This is a generic binary stream type, suitable for file attachments. - File handling: For each attachment, a
File
object is created from the provided path. The file’s name and body are included in the request. - Executing the request: The request is sent using the
OkHttpClient
, and the response is processed similarly to the previous example.
Security measures
Mailtrap API communication happens over HTTPS, ensuring that the data transmitted between the client and the server is encrypted. This includes the HTML content of the email and any attachments.
As a secure channel, HTTPS safeguards against eavesdropping and tampering. Even so, there are some additional methodologies you might consider.
- Encryption of attachments: Individually encrypting attachments before sending could be an additional layer of security to implement. This goes double for sensitive files which may contain personal user data.
- Checksums and file validation: Checksums for file validation and file type checks would be useful for ensuring file integrity and safety.
- Antivirus scanning: Antivirus scanning is typically handled at the server or endpoint level.
- Digital signatures: The digital signatures in the code could be used to verify the authenticity of the sender.
To sum up, HTTPS is a significant step in ensuring secure communication. And the implementation of additional security measures, like encryption of attachments or checksum validation, would depend on the specific requirements and the level of security desired.
Also, note that the more advanced security implementations require modifications to the email-sending mechanisms and the processing logic at the receiving end.
Send to multiple recipients
Guess what, I’ll be extending the previous example to handle multiple recipients. 😀
The trick is in modifying the sendEmail
method to accept a list of recipients instead of a single recipient. I’ll also provide comments to explain the method and the logic behind the code.
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class MailtrapApiEmailSender {
private final String mailtrapApiToken;
private final OkHttpClient client = new OkHttpClient();
public MailtrapApiEmailSender(String mailtrapApiToken) {
this.mailtrapApiToken = mailtrapApiToken;
}
// Method to send an email with attachments to multiple recipients
public void sendEmail(List<String> recipients, String subject, String body, List<File> attachments) throws IOException {
// Build the JSON string for the recipients
StringBuilder recipientJson = new StringBuilder();
for (String recipient : recipients) {
if (recipientJson.length() > 0) recipientJson.append(", ");
recipientJson.append("\"").append(recipient).append("\"");
}
// Create the JSON body for the email
String jsonBody = "{\"to\": [" + recipientJson + "], \"subject\": \"" + subject + "\", \"html_body\": \"" + body + "\"}";
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
builder.addFormDataPart("data", jsonBody);
// Add attachments to the request
for (File attachment : attachments) {
builder.addFormDataPart("attachment", attachment.getName(), RequestBody.create(attachment, MediaType.get("application/octet-stream")));
}
RequestBody requestBody = builder.build();
// Build and execute the request
Request request = new Request.Builder()
.url("https://send.api.mailtrap.io/api/send")
.addHeader("Authorization", "Bearer " + mailtrapApiToken)
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// Handle response or return it
}
}
}
Copy
In this code:
- Multiple recipients handling: The method
sendEmail
is modified to accept a list of email addresses (List<String> recipients
). A JSON array is constructed from this list to include multiple recipients in the API request. - Building JSON body: The JSON string for the email body is created with multiple recipients, subject, and HTML body.
- Attachments handling: The method now accepts a list of
File
objects as attachments. Each attachment is added as a form data part to the request body. - Creating multipart request: We use
MultipartBody.Builder
to construct a multipart request that includes both the JSON body and the attachments. - Executing the request: The request is then built and executed using
OkHttpClient
, with error handling to catch any issues during the execution.
Test emails before sending: why and how?
Testing emails in a sandbox environment, like the one Mailtrap provides, saves you a lot of trouble in the long run. Here’s a list of key reasons to test emails.
- Catch errors early: The sandbox environment allows you to identify and rectify issues like formatting errors, broken links, or typos before they reach your audience.