如何在电子邮件中附加图片?我正在使用AWS SES服务通过JAVA发送电子邮件-Spring Boot

问题描述

我在AWS上托管了一个Spring Boot应用程序。我正在使用AWS SES触发电子邮件。但是我不知道如何使用SES附加图像。我正在使用JAVA作为应用程序源代码。数据存储在数据库中,但未发送电子邮件


   public void sendEmail(String to,String subject,String body) throws MessagingException {
        Properties props = System.getProperties();
        props.put("mail.transport.protocol","smtp");
        props.put("mail.smtp.port",PORT);
        props.put("mail.smtp.starttls.enable","true");
        props.put("mail.smtp.auth","true");

        Session session = Session.getDefaultInstance(props);

        Message msg = new MimeMessage(session);
        MimeMultipart multipart = new MimeMultipart();
        BodyPart messageBodyPart = new MimeBodyPart();
        // the body content:
        messageBodyPart.setContent(BODY,"text/html");
        multipart.addBodyPart(messageBodyPart);
        // the image:
        messageBodyPart = new MimeBodyPart();
        DataSource fds = new FileDataSource(
                "logo.png");
        messageBodyPart.setDataHandler(new DataHandler(fds));
        messageBodyPart.setHeader("Content-ID","<image_01>");
        multipart.addBodyPart(messageBodyPart);
        // add the multipart to the message:
        msg.setContent(multipart);
        // set the remaining values as usual:
        try {
            msg.setFrom(new InternetAddress(FROM,FROMNAME));
        } catch (UnsupportedEncodingException e) {
            // Todo Auto-generated catch block
            e.printstacktrace();
        } catch (MessagingException e) {
            // Todo Auto-generated catch block
            e.printstacktrace();
        }
        msg.setRecipient(Message.RecipientType.TO,new InternetAddress(to));
        msg.setSubject(SUBJECT);

        Transport transport = session.getTransport();

        try {
            System.out.println("Sending...");
            transport.connect(HOST,SMTP_USERNAME,SMTP_PASSWORD);
            transport.sendMessage(msg,msg.getAllRecipients());
            System.out.println("Email sent!");
        } catch (Exception ex) {
            System.out.println("The email was not sent.");
            ex.printstacktrace();
        } finally {
            transport.close();
        }
    }

project_structure Error_Log

解决方法

要将图像嵌入到电子邮件中,您需要对代码进行一些更改。我使用SES帐户,JavaMail和gmail网络客户端测试了这些更改:

使用Content ID方案(cid:

以下是使用cid的内容:

static final String BODY = String.join(System.getProperty("line.separator"),"<html><head></head><body><img src=\"cid:image_01\"></html> <br>"
    + "Welcome to ABC and have a great experience.");

在此示例中,image_01是我要使用的任何标识符。显示邮件时,cid:方案意味着电子邮件客户端将在邮件中寻找Content-ID标头,并使用该名称检索相关图像-但名称必须包含在其中尖括号<>可以内嵌显示(见下文)。

查看更多信息here

创建多部分Mime消息

您的MimeMessage msg对象将需要以不同的方式构建:

Message msg = new MimeMessage(session);
MimeMultipart multipart = new MimeMultipart();
try {
    BodyPart messageBodyPart = new MimeBodyPart();
    // the body content:
    messageBodyPart.setContent(BODY,"text/html");
    multipart.addBodyPart(messageBodyPart);
    // the image:
    messageBodyPart = new MimeBodyPart();
    DataSource fds = new FileDataSource("/your/path/to/logo.png");
    messageBodyPart.setDataHandler(new DataHandler(fds));
    messageBodyPart.setHeader("Content-ID","<image_01>");
    multipart.addBodyPart(messageBodyPart);
    // add the multipart to the message:
    msg.setContent(multipart);
    // set the remaining values as usual:
    msg.setFrom(new InternetAddress(FROM,FROMNAME));
    msg.setRecipient(Message.RecipientType.TO,new InternetAddress(to));
    msg.setSubject(SUBJECT);
} catch (UnsupportedEncodingException | MessagingException ex) {
    Logger.getLogger(App.class.getName()).log(Level.SEVERE,null,ex);
}

在这里,我们构建一条由两部分组成的消息:

  1. BODY中的HTML内容。
  2. 图像。

在我的示例中,映像是文件系统上的文件-但您可以通过应用程序所需的任何方式(例如,通过资源)访问它。

请注意在设置标题时使用尖括号(如前所述):

messageBodyPart.setHeader("Content-ID","<image_01>");

现在,您可以按照通常的方式发送消息了:

try ( Transport transport = session.getTransport()) {
    System.out.println("Sending...");
    transport.connect(HOST,SMTP_USERNAME,SMTP_PASSWORD);
    transport.sendMessage(msg,msg.getAllRecipients());
    System.out.println("Email sent!");
} catch (Exception ex) {
    Logger.getLogger(App.class.getName()).log(Level.SEVERE,ex);
}

关于JavaMailSender的注释

在您的代码中,包括以下内容:

private JavaMailSender mailSender;

是Spring围绕JavaMail(现在为JakartaMail)对象的包装。您不会在代码中使用此对象。

鉴于您正在使用Spring,我建议您使用上述方法,然后重构代码以利用Spring的邮件帮助器实用程序。有很多其他的指南和教程。

关于SES的说明

以上方法使用的是Amazon的SES SMTP interface。换句话说,您的代码中不需要任何Amazon SDK类。

这是我在测试此答案中的代码时使用的(使用SES帐户)。

您当然可以考虑使用记录在herehere中的其他两种方法中的任何一种-但是显示图像都不是必需的。


更新

有人问了一个问题,以供澄清:

messageBodyPart.setHeader("Content-ID","<image_01>");

文本<image_01>是在HTML代码中引用图像的方式。因此,这就是我的示例代码使用此代码的原因:

<img src=\"cid:image_01\">

您可以在此处使用所需的任何标识符。在我的情况下,标识符“ image_01”是指我的图像文件“ logo.png”。

但是要清楚一点-您确实需要在代码中包含<>。它们不像我的代码中的“占位符”一样存在-它们是您需要使用的语法的一部分。


但是请记住,如果您充分利用Spring和 Spring Mail Helper功能,则可以使一切变得更加简单。

例如,这是使用Spring的JavaMailSenderMimeMessageHelper的相同方法:

import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

@Component
public class MySpringMailer {

    static final String FROM = "donotreply@myaddress.com";
    static final String FROMNAME = "My Name";
    static final String TO = "my.email@myaddress.com";
    static final String SUBJECT = "Welcome to ABC";
    static final String BODY = String.join(System.getProperty("line.separator"),"<html><head></head><body><img src=\"cid:image_01\"></html> <br>"
            + "Welcome to ABC and have a really great experience.");

    @Autowired
    private JavaMailSender javaMailSender;

    public void sendSpringEmailWithInlineImage() {
        MimeMessage msg = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(msg,true); // true = multipart
            helper.setFrom(FROM,FROMNAME);
            helper.setTo(TO);
            helper.setSubject(SUBJECT);
            helper.setText(BODY,true); // true = HTML
            DataSource res = new FileDataSource("c:/tmp/logo.png");
            helper.addInline("image_01",res);
        } catch (UnsupportedEncodingException | MessagingException ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE,ex);
        }
        javaMailSender.send(msg);
    }

}

例如,现在,我们可以使用以下内容为图像文件创建引用:

helper.addInline("image_01",res);

请注意,当在Java代码中定义名称时,Spring不需要在这里使用<>。春天在幕后为我们解决了这个问题。

,

这是通过 SES 发送电子邮件并将图像作为附件嵌入的示例代码:

    String filePath = "src/main/resources/" + barcodeText + ".png";
    System.out.println("barcodeImg was saved in System locally");

    String subject = "test subject";
    String body = "<!DOCTYPE html>\n" + "<html>\n" + "    <head>\n" + "        <meta charset=\"utf-8\">\n"
            + "        <title></title>\n" + "    </head>\n" + "    <body>\n" + "        <p>test</p>\n"
            + "        <p>-- BarCode from attachment<br><img src=\"cid:barcode\"></p><br>BarCode render completed\n"
            + "    </body>\n" + "</html>";
    String toAddrsStr = "emailID1,emailID2,emailID3";
    sendEmailWithAttachment(toAddrsStr,subject,body,filePath);

定义:

public static void sendEmailWithAttachment(String to,String subject,String body,String attachmentFilePath) {
    Session session = Session.getDefaultInstance(new Properties());
    MimeMessage message = new MimeMessage(session);
    try {
        message.setSubject(subject,"UTF-8");
        message.setFrom(new InternetAddress("gowthamdpt@gmail.com"));
        //to address String should be with comma separated.
        message.setRecipients(javax.mail.Message.RecipientType.TO,InternetAddress.parse(to));

        MimeMultipart msg = new MimeMultipart("alternative");
        MimeBodyPart wrap = new MimeBodyPart();
        MimeMultipart msgBody = new MimeMultipart("mixed");

        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(body,"text/html; charset=UTF-8");
        msgBody.addBodyPart(htmlPart);
        wrap.setContent(msgBody);
        msg.addBodyPart(wrap);

        MimeBodyPart att = new MimeBodyPart();
        DataSource fds = new FileDataSource(attachmentFilePath);
        att.setDataHandler(new DataHandler(fds));
        att.setFileName(fds.getName());
        att.setContentID("<barcode>");
        msg.addBodyPart(att);
        message.setContent(msg);

        AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
                .withRegion(Regions.US_EAST_1).build();
        message.writeTo(System.out);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        message.writeTo(outputStream);
        RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
        SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage)
                .withConfigurationSetName(CONFIGSET);
        client.sendRawEmail(rawEmailRequest);
        System.out.println("sendEmail()" + "email triggered successfully");
    } catch (Exception ex) {
        System.out.println("sendEmail()" + "The email was not sent. Error: " + ex.getMessage());
    }
}