I am trying to write a Java app which can send emails to specify emails. In the email i also want to attach some pic.
Please find my code below :-
public class AmazonSESSample {
static final String FROM = "[email protected]";
static final String TO = "[email protected]";
static final String BODY = "This email was sent through Amazon SES by using the AWS SDK for Java. hello";
static final String SUBJECT = "Amazon SES test (AWS SDK for Java)";
public static void main(String[] args) throws IOException {
Destination destination = new Destination().withToAddresses(new String[] { TO });
Content subject = new Content().withData(SUBJECT);
Message msg = new Message().withSubject(subject);
// Include a body in both text and HTML formats
//Content textContent = new Content().withData("Hello - I hope you're having a good day.");
Content htmlContent = new Content().withData("<h2>Hi User,</h2>\n"
+ " <h3>Please find the ABC Association login details below</h3>\n"
+ " <img src=\"logo.png\" alt=\"Mountain View\">\n"
+ " Click <a href=\"http://google.com">here</a> to go to the association portal.\n"
+ " <h4>Association ID - 12345</h4>\n" + " <h4>Admin UID - suny342</h4>\n"
+ " <h4>Password - poass234</h4>\n" + " Regards,\n" + " <br>Qme Admin</br>");
Body body = new Body().withHtml(htmlContent);
msg.setBody(body);
SendEmailRequest request = new SendEmailRequest().withSource(FROM).withDestination(destination)
.withMessage(msg);
try {
System.out.println("Attempting to send an email through Amazon SES by using the AWS SDK for Java...");
AWSCredentials credentials = null;
credentials = new BasicAWSCredentials("ABC", "CDF");
try {
// credentialsProvider.
} catch (Exception e) {
throw new AmazonClientException("Cannot load the credentials from the credential profiles file. "
+ "Please make sure that your credentials file is at the correct "
+ "location (/Users/iftekharahmedkhan/.aws/credentials), and is in valid format.", e);
}
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials)).withRegion("us-west-2").build();
client.sendEmail(request);
System.out.println("Email sent!");
} catch (Exception ex) {
System.out.println("The email was not sent.");
System.out.println("Error message: " + ex.getMessage());
}
}
}
The image is placed in the resource directory but it is not being embeded in the email. Can anyone please help.
There is no single way to include images in emails. The best practice is to upload the images to a directory on your server and then link them to your HTML email using full URL paths. It requires download from the external server and faces issues of getting blocked by most email clients.
To send emails with attachments, you can call the Amazon SES SendRawEmail API, or use the AWS Software Development Kits (SDKs) to compose and send the message programmatically. The message, with attachment(s), will appear in the recipient's email client where it can be viewed or saved to disk.
To create a template to send personalized email messages, use the CreateTemplate operation. The template can be used by any account authorized to send messages in the AWS Region to which the template is added. Amazon SES doesn't validate your HTML, so be sure that HtmlPart is valid before sending an email.
Instead of relative path, you'll need to use either an absolute public path to the image itself or a data URL. For example:
<img src=\"https://example.com/logo.png\" alt=\"Mountain View\" />
or
<img src=\"data:image/png;base64, {BASE64_ENCODED_DATA}\" alt=\"Mountain View\" />
EDIT
As of January 2020, Gmail still does not support base64 encoded images.
The method posted by @sebagra works well.
In case of Python using boto3
and ses
client, the way to set to set the Content-Disposition
to inline is:
att.add_header('Content-ID', '<myImage>')
att.add_header('Content-Disposition', 'inline', filename=os.path.basename(IMAGE_PATH))
Full example based on the python example in the AWS docs:
import os
import boto3
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
# Replace [email protected] with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Sender Name <[email protected]>"
# Replace [email protected] with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = "[email protected]"
# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
CONFIGURATION_SET = "ConfigSet"
# If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
AWS_REGION = "us-west-2"
# The subject line for the email.
SUBJECT = "Customer service contact info"
# The full path to the file that will be attached to the email.
IMAGE_PATH = "path/to/myImage.png"
# The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."
# The HTML body of the email.
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
"""
# The character encoding for the email.
CHARSET = "utf-8"
# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
# Create a multipart/mixed parent container.
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
# Create a multipart/alternative child container.
msg_body = MIMEMultipart('alternative')
# Encode the text and HTML content and set the character encoding. This step is
# necessary if you're sending a message with characters outside the ASCII range.
textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
# Add the text and HTML parts to the child container.
msg_body.attach(textpart)
msg_body.attach(htmlpart)
# Define the attachment part and encode it using MIMEApplication.
att = MIMEApplication(open(IMAGE_PATH, 'rb').read())
# Add a header to tell the email client to treat this part as an attachment,
# and set an id and content disposition.
att.add_header('Content-ID', '<myImage>')
att.add_header('Content-Disposition', 'inline', filename=os.path.basename(IMAGE_PATH))
# Attach the multipart/alternative child container to the multipart/mixed
# parent container.
msg.attach(msg_body)
# Add the attachment to the parent container.
msg.attach(att)
try:
response = client.send_raw_email(
Source=SENDER,
Destinations=[
RECIPIENT
],
RawMessage={
'Data': msg.as_string(),
}
)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])
In case of using sesv2
the msg
is built the same but the the api to use is send_email
:
...
client = boto3.client('sesv2',region_name=AWS_REGION)
...
response = client.send_email(
FromEmailAddress=SENDER,
Destination={
'ToAddresses': [
RECIPIENT
]
},
Content={
'Raw': {
'Data': msg.as_string()
}
}
)
...
I was able to send an email using AWS SES with images that can be seen in the GMail client, by attaching the images to the message and using an inline disposition reference to them.
I used the code explained in the AWS docs to attach images to a MimeMessage, and then using the cid
reference from the HTML to those images (as explained in this post answer).
First, we attach the images to the message adding a couple of specific attributes (Header and Disposition):
MimeMultipart msg = new MimeMultipart("mixed");
DataSource fds = new FileDataSource("/path/to/my/image.png");
att.setDataHandler(new DataHandler(fds));
att.setFileName(fds.getName());
att.setHeader("Content-ID","<myImage>");
att.setDisposition("inline; filename=\"image.png\"");
msg.addBodyPart(att);
Note that the <
and >
in the Content-ID attribute must be present enclosing whatever id you choose (myImage
in my example).
Then, in the HTML of the message body we just need to add the cid (content id) of each image:
<img src="cid:myImage">
For the full code, I pretty much used the AWS reference above (using same variable names), the only changes made were the ones of the setHeader
and setDisposition
methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With