Add embedded image in emails in AWS SES service
Stefan Bogdanescu
Founder & Senior Architect
Mastering Embedded Images in AWS SES Emails: A Developer's Guide
Sending rich, visually appealing emails often involves more than just plain text. Developers frequently need to embed images, logos, or charts directly into their communications. When using a service like Amazon SES (Simple Email Service), achieving this requires understanding the nuances of email formatting and MIME structures, which can often trip up even experienced users.
If you are attempting to embed an image in your email body but it isn't appearing, the issue is almost always related to how the image resource is referenced—it’s not just about saving the file; it’s about making that file accessible to the recipient’s mail client.
This guide will walk you through the correct methods for embedding images in emails sent via AWS SES using a Java application, focusing on practical solutions and best practices.
The Root Cause: Why src="logo.png" Fails in Emails
The code snippet you provided attempts to embed an image using a standard HTML tag:
<img src="logo.png" alt="Mountain View">
When SES sends an email, the recipient's mail client tries to fetch the resource specified in the src attribute. For external files like logo.png, this path (logo.png) is relative to the web server where the email is being rendered. Since an email payload does not inherently contain the necessary web context for fetching arbitrary files, the image fails to load.
To successfully embed an image, you must ensure the image data is either hosted publicly or fully included within the email's MIME structure. We have two robust solutions: external linking and inline embedding.
Solution 1: Hosting Images Externally (The Standard Approach)
The most common and practical way to include images in emails via SES is to host the image file on a publicly accessible web server (like Amazon S3, or any public CDN) and reference it using a full HTTPS URL. This approach keeps your email payload lightweight and leverages existing infrastructure.
Best Practice: Use AWS S3 for hosting assets, as it integrates seamlessly with other AWS services.
Java Implementation with External Links
Instead of linking to a local file path, you must use the public URL.
// Example: Assuming 'logo.png' is hosted at this public URL
String imageUrl = "https://your-s3-bucket.s3.amazonaws.com/logo.png";
Content htmlContent = new Content().withData("<h2>Hi User,</h2>\n"
+ " <img src=\"" + imageUrl + "\" alt=\"Mountain View\">\n" // Use the full URL here
// ... rest of your HTML content
);
// ... proceed with building the Message object and sending via SES
This method is clean, scalable, and relies on standard web protocols. This aligns perfectly with modern infrastructure principles, much like how developers build robust systems using frameworks like those found in the Laravel ecosystem.
Solution 2: Embedding Images Directly (Base64 Encoding)
For maximum reliability—especially when dealing with highly sensitive content or ensuring the email is fully self-contained regardless of external connectivity—you can embed the image data directly into the email body using Base64 encoding. This method turns the binary image data into a text string that can be safely transmitted within the MIME message.
This process requires reading the image file, converting its bytes to Base64, and then embedding that resulting string directly into your HTML content as a Data URI.
Java Implementation with Base64 Encoding
This approach is more complex but guarantees that the image travels with the email payload.
import java.nio.file.Files;
import java.io.IOException;
import java.util.Base64;
// ... inside your main method or helper function
try {
// 1. Read the image file into bytes
byte[] imageBytes = Files.readAllBytes(Paths.get("logo.png"));
// 2. Encode the bytes to Base64 string
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
// 3. Construct the Data URI for embedding in HTML
String inlineImage = "data:image/png;base64," + base64Image;
Content htmlContent = new Content().withData("<html><body>"
+ "<h2>Hi User,</h2>\n"
// Embed the image directly using the Data URI
+ "<img src=\"" + inlineImage + "\" alt=\"Mountain View\">\n"
// ... rest of your HTML content
+ "</body></html>");
Body body = new Body().withHtml(htmlContent);
// ... continue building and sending the SendEmailRequest
} catch (IOException e) {
e.printStackTrace();
System.err.println("Error reading or encoding image file.");
}
Conclusion
When integrating AWS SES with custom application logic, remember that email delivery operates on strict MIME standards. Avoid assuming local file paths will work for embedded content. For simplicity and scalability, hosting images externally (Solution 1) is the recommended path for most applications. However, if you require absolute self-containment, Base64 encoding (Solution 2) provides the ultimate guarantee that your visual assets are delivered with the message itself.
By mastering these techniques, you move beyond simple text messaging and begin crafting professional, rich communications using the power of cloud services like AWS.
Note: Blog content is currently available in English.