htopiwala
htopiwala

Reputation: 700

Using templates in AWS SES to send email with attachments

I'm trying to use email templates to personalize the email which I send by passing the data to already created templates through a JSON string. Even though I'm able to send a raw email by attaching the files, I want a way through which I can send email attachments in the email while using email templates in SES.

Upvotes: 8

Views: 7492

Answers (3)

Victor Soares
Victor Soares

Reputation: 882

Solution with SES v2, Java 17 and jakarta.mail:

public class EmailContentDto {
    private String templateName;
    private String content;
    private String subject;
    private String[] to;
    private String[] cc;
    private String[] bcc;
    private EmailAttachmentDto[] attachments;
}

private void sendTemplated(EmailContentDto email) throws Exception {
    EmailAttachmentDto[] attachments = email.getAttachments();
    if (attachments == null || attachments.length < 1) {
        Template template = Template.builder()
                .templateName(email.getTemplateName())
                .templateData(email.getContent())
                .build();

        EmailContent emailContent = EmailContent.builder()
                .template(template)
                .build();

        SendEmailRequest emailRequest = buildSendEmailRequest(email, emailContent);

        awsSesService.send(emailRequest);
    } else {
        sendRawTemplated(email);
    }
}

private void sendRawTemplated(EmailContentDto email) throws Exception {
    String mimeContent = awsSesService.getRenderedTemplate(email.getTemplateName(), email.getContent());
    String content = parseMimeContent(mimeContent);
    MimeBodyPart bodyPart = new MimeBodyPart();
    bodyPart.setContent(content, "text/html; charset=" + EmailConstants.DEF_CHARSET);
    sendRaw(email, bodyPart);
}

private String parseMimeContent(String mimeContent) throws Exception {
    Session session = Session.getDefaultInstance(new Properties());
    InputStream inputStream = new ByteArrayInputStream(mimeContent.getBytes());
    MimeMessage mimeMessage = new MimeMessage(session, inputStream);
    return mimeMessage.getContent().toString();
}

private SendEmailRequest buildSendEmailRequest(EmailContentDto emailDto, EmailContent content) {
    return SendEmailRequest.builder()
            .destination(Destination.builder()
                    .toAddresses(emailDto.getTo())
                    .bccAddresses(emailDto.getBcc() == null ? new String[0] : emailDto.getBcc())
                    .ccAddresses(emailDto.getCc() == null ? new String[0] : emailDto.getCc())
                    .build())
            .content(content)
            .fromEmailAddress(emailFrom)
            .build();
}

private void sendRaw(EmailDto email) throws Exception {
    MimeBodyPart textPart = new MimeBodyPart();
    textPart.setContent(email.getContent(), "text/plain; charset=" + EmailConstants.DEF_CHARSET);
    sendRaw(email, textPart);
}

private void sendRaw(EmailDto email, MimeBodyPart textPart) throws Exception {
    Session session = Session.getDefaultInstance(new Properties());
    MimeMessage message = new MimeMessage(session);

    // basic
    message.setSubject(email.getSubject(), EmailConstants.DEF_CHARSET);
    message.setFrom(new InternetAddress(emailFrom));
    message.setRecipients(jakarta.mail.Message.RecipientType.TO, InternetAddress.parse(email.getToJoining()));
    String cc = email.getCcJoining();
    if (cc != null) {
        message.setRecipients(jakarta.mail.Message.RecipientType.CC, InternetAddress.parse(cc));
    }
    String bcc = email.getBccJoining();
    if (bcc != null) {
        message.setRecipients(jakarta.mail.Message.RecipientType.BCC, InternetAddress.parse(bcc));
    }

    // multipart container.
    MimeMultipart msgBody = new MimeMultipart("alternative");
    MimeBodyPart wrap = new MimeBodyPart();
    msgBody.addBodyPart(textPart);
    wrap.setContent(msgBody);
    MimeMultipart msg = new MimeMultipart("mixed");
    message.setContent(msg);
    msg.addBodyPart(wrap);

    // attachments
    for (EmailAttachmentDto attachment : email.getAttachments()) {
        MimeBodyPart att = new MimeBodyPart();
        byte[] decoded = Base64.getDecoder().decode(attachment.getContent());
        DataSource fds = new ByteArrayDataSource(decoded, attachment.getMimeType());
        att.setDataHandler(new DataHandler(fds));
        att.setFileName(attachment.getName());
        msg.addBodyPart(att);
    }

    // RawMessage
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    message.writeTo(outputStream);
    ByteBuffer buf = ByteBuffer.wrap(outputStream.toByteArray());
    byte[] arr = new byte[buf.remaining()];
    buf.get(arr);
    SdkBytes data = SdkBytes.fromByteArray(arr);
    RawMessage rawMessage = RawMessage.builder().data(data).build();
    SendEmailRequest emailRequest = SendEmailRequest.builder()
            .content(EmailContent.builder().raw(rawMessage).build())
            .build();

    this.awsSesService.send(emailRequest);
}

class AWSSesService {
    public SendEmailResponse send(final SendEmailRequest request) {
        SesV2Client client = getClient();
        return client.sendEmail(request);
    }
    // ...
}

Imports jakarta.mail 2.0.1:

import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
import jakarta.mail.Session;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import jakarta.mail.util.ByteArrayDataSource;

Upvotes: 0

Manpreet Singh
Manpreet Singh

Reputation: 75

As per my RND there is no way to send an email using SES template along with attachment, But yes we can do something like this.

  1. Grab template from SES using the code below then we can replace the token and then we use these in SendRawEmail email along with the attachements.

     AmazonSimpleEmailService emailSendClient = 
      AmazonSimpleEmailServiceClient.builder()
             .withRegion(Regions.AP_SOUTH_1).build();
     String templateName = "MyTemplate";
     GetTemplateRequest getTemplateRequest = new GetTemplateRequest();
     getTemplateRequest.setTemplateName(templateName);
     GetTemplateResult temp = emailSendClient.getTemplate(getTemplateRequest);
     String htmlpart = temp.getTemplate().getHtmlPart();
    

Upvotes: 8

Shyam
Shyam

Reputation: 317

There is no option for sending the templated email with attachments. On the other hand, SendRawEmail requires you to build your own MIME formatted email message which is far from being easy. you can use nodemailer with AWS SES to accomplish this. follow this link

Upvotes: 0

Related Questions