How do i attach image in email? I am using AWS SES Service to send email using JAVA – Spring Boot

huangapple go评论83阅读模式
英文:

How do i attach image in email? I am using AWS SES Service to send email using JAVA - Spring Boot

问题

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();
    MimeBodyPart messageBodyPart = new MimeBodyPart();
    
    // 设置邮件正文内容:
    messageBodyPart.setContent(body, "text/html");
    multipart.addBodyPart(messageBodyPart);
    
    // 添加图片:
    messageBodyPart = new MimeBodyPart();
    DataSource fds = new FileDataSource("Logo.png");
    messageBodyPart.setDataHandler(new DataHandler(fds));
    messageBodyPart.setHeader("Content-ID", "<image_01>");
    multipart.addBodyPart(messageBodyPart);
    
    // 将多部分内容设置为消息的内容:
    msg.setContent(multipart);
    
    // 设置其他属性:
    try {
        msg.setFrom(new InternetAddress(FROM, FROMNAME));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (MessagingException e) {
        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][2]

![Error_Log][1]


[1]: https://i.stack.imgur.com/lpRfS.png
[2]: https://i.stack.imgur.com/VsWy5.png
<details>
<summary>英文:</summary>
I have a Spring Boot application hosted on AWS. I am using AWS SES to trigger email. But i am lost as to how to attach an image using SES. I am using JAVA as application source code.The data are stored in the database but the email is not sent.:

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, &quot;text/html&quot;);
multipart.addBodyPart(messageBodyPart);
// the image:
messageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource(
&quot;Logo.png&quot;);
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setHeader(&quot;Content-ID&quot;, &quot;&lt;image_01&gt;&quot;);
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(&quot;Sending...&quot;);
transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD);
transport.sendMessage(msg, msg.getAllRecipients());
System.out.println(&quot;Email sent!&quot;);
} catch (Exception ex) {
System.out.println(&quot;The email was not sent.&quot;);
ex.printStackTrace();
} finally {
transport.close();
}
}

![project_structure][2] 
![Error_Log][1]
[1]: https://i.stack.imgur.com/lpRfS.png
[2]: https://i.stack.imgur.com/VsWy5.png
</details>
# 答案1
**得分**: 1
**将图像嵌入电子邮件中,需要对代码进行一些更改。我使用了SES帐户、JavaMail和Gmail Web客户端测试了这些更改:**
**使用内容ID方案(`cid:`)**
这是您的正文内容使用`cid`的方式:
```java
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头,并使用该名称检索相关图像 - 但该名称需要用尖括号 &lt;&gt; 括起来以内联显示(如下所示)。

在此处查看更多信息 [这里][1]。

创建多部分 MIME 消息

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

Message msg = new MimeMessage(session);
MimeMultipart multipart = new MimeMultipart();
try {
    BodyPart messageBodyPart = new MimeBodyPart();
    // 正文内容:
    messageBodyPart.setContent(BODY, "text/html");
    multipart.addBodyPart(messageBodyPart);
    // 图像:
    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);
    // 将多部分内容添加到消息中:
    msg.setContent(multipart);
    // 像往常一样设置其余的值:
    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, null, ex);
}

关于 JavaMailSender 的说明

在您的代码中,您包含了这个:

private JavaMailSender mailSender;

这是 Spring 对 JavaMail(现在是 JakartaMail)对象的封装。您在代码中没有使用这个对象。

考虑到您正在使用 Spring,我建议您先让上述方法运行起来,然后重构您的代码以利用 Spring 的邮件辅助工具函数。有很多关于这方面的指南和教程。

关于 SES 的说明

上述方法使用了亚马逊的 [SES SMTP 接口][2]。换句话说,在您的代码中不需要任何亚马逊 SDK 类。

这是我在测试这个答案中使用的方法(使用 SES 帐户)。

您当然可以查看 [这里][3] 和 [这里][4] 中所记录的另外两种方法 - 但是对于显示图像来说,这两种方法都不是必需的。


更新

有一个关于这一点的澄清问题:

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

文本 &lt;image_01&gt; 是您在 HTML 代码中引用图像的方式。因此,这就是为什么我的示例代码使用了这个:

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

您可以在这里使用任何标识符。在我的示例中,标识符 "image_01" 是指我的图像文件 "logo.png"。

但是请明确一点 - 在您的代码中确实需要包含 &lt;&gt;。它们不仅仅是我代码中的“占位符”,它们是您需要使用的语法的一部分。


但是请记住,如果您充分利用 Spring 和 Spring 邮件辅助函数,一切都可以变得更简单。

例如,以下是相同方法的 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

<details>
<summary>英文:</summary>

To embed an image into your e-mail, you need to make a couple of changes to your code. I tested these changes using an SES account, JavaMail and a gmail web client:

**Use the Content ID Scheme (`cid:`)**

Here is your body content using a `cid`:

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

In this example, `image_01` is whatever identifier I want to use. When the mail is displayed, the `cid:` scheme means that the email client will look for a `Content-ID` header in the message, and retrieve the related image using that name - but the name will need to be enclosed in angle brackets `&lt;` and `&gt;` to be displayed inline (see below).
See more info [here][1].
**Create a Multipart Mime Message**
Your `MimeMessage msg` object will need to be built differently:

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);
}

Here we build a message consisting of two parts:
1) The HTML contents from `BODY`.
2) The image.
In my example, the image is a file on the filesystem - but you can access it in whatever way you need for your application (e.g. via a resource).
Note the use of angle brackets when setting the header (as mentioned earlier):

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


Now you can send the message in the usual way:

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, null, ex);
}


**A Note on `JavaMailSender`**
In your code, you include this:

private JavaMailSender mailSender;

which is Spring&#39;s wrapper around the JavaMail (now JakartaMail) object. You don&#39;t make use of this object in your code.
Given you are using Spring, I would recommend you get the above approach working, and then refactor your code to make use of Spring&#39;s mail helper utilities. There are lots of guides and tutorials for that elsewere.
**A Note on SES**
The above approach is using Amazon&#39;s [SES SMTP interface][2]. In other words, no need for any Amazon SDK classes in your code.
This is what I used when testing the code in this answer (using an SES account).
You can certainly look into using either of the other two approaches documented [here][3] and [here][4] - but neither is required for images to be displayed.
----------
**Update**
A question was asked, for clarification, about this:

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


The text `&lt;image_01&gt;` is how you refer to your image, in your HTML code. So, that is why my example code uses this:

<img src=&quot;cid:image_01&quot;>

You can use any identifier you want here. In my case the identifier &quot;image_01&quot; refers to my image file &quot;logo.png&quot;. 
But just to be clear - you really do need to include the `&lt;` and the `&gt;` in your code. They are not there just as &quot;placeholders&quot; in my code - they are part of the syntax you need to use.
----------
But remember, you can make everything much simpler, if you take full advantage of Spring, and the **Spring Mail Helper functions**.
For example, here is the same approach, using Spring&#39;s `JavaMailSender` and `MimeMessageHelper`:

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 = &quot;donotreply@myaddress.com&quot;;
static final String FROMNAME = &quot;My Name&quot;;
static final String TO = &quot;my.email@myaddress.com&quot;;
static final String SUBJECT = &quot;Welcome to ABC&quot;;
static final String BODY = String.join(System.getProperty(&quot;line.separator&quot;),
&quot;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;img src=\&quot;cid:image_01\&quot;&gt;&lt;/html&gt; &lt;br&gt;&quot;
+ &quot;Welcome to ABC and have a really great experience.&quot;);
@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(&quot;c:/tmp/logo.png&quot;);
helper.addInline(&quot;image_01&quot;, res);
} catch (UnsupportedEncodingException | MessagingException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
javaMailSender.send(msg);
}

}


So, for example, now we can create a reference for our image file using this:

helper.addInline("image_01", res);

Note that Spring does not need us to use `&lt;` and `&gt;` here, when we are defining the name in our Java code. Spring takes care of that  for us, behind the scenes.
[1]: https://www.rfc-editor.org/rfc/rfc2392
[2]: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-using-smtp.html
[3]: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-using-sdk.html
[4]: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-raw-using-sdk.html
</details>
# 答案2
**得分**: 0
以下是用于通过SES发送电子邮件并将图像嵌入为附件的示例代码:
```java
String filePath = "src/main/resources/" + barcodeText + ".png";
System.out.println("barcodeImg was saved in System locally");
String subject = "测试主题";
String body = "<!DOCTYPE html>\n" +
"<html>\n" +
"    <head>\n" +
"        <meta charset=\"utf-8\">\n" +
"        <title></title>\n" +
"    </head>\n" +
"    <body>\n" +
"        <p>测试</p>\n" +
"        <p>-- 来自附件的条形码<br><img src=\"cid:barcode\"></p><br>条形码渲染完成\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()" + "电子邮件触发成功");
} catch (Exception ex) {
System.out.println("sendEmail()" + "电子邮件未发送。错误:" + ex.getMessage());
}
}

注意:上述代码示例是关于如何使用Java发送电子邮件,并将图像作为附件嵌入。代码中的变量和方法可能需要根据您的实际情况进行适当的更改。

英文:

Here is a sample code for sending an email through SES with embed an image as an attachment:

    String filePath = &quot;src/main/resources/&quot; + barcodeText + &quot;.png&quot;;
System.out.println(&quot;barcodeImg was saved in System locally&quot;);
String subject = &quot;test subject&quot;;
String body = &quot;&lt;!DOCTYPE html&gt;\n&quot; + &quot;&lt;html&gt;\n&quot; + &quot;    &lt;head&gt;\n&quot; + &quot;        &lt;meta charset=\&quot;utf-8\&quot;&gt;\n&quot;
+ &quot;        &lt;title&gt;&lt;/title&gt;\n&quot; + &quot;    &lt;/head&gt;\n&quot; + &quot;    &lt;body&gt;\n&quot; + &quot;        &lt;p&gt;test&lt;/p&gt;\n&quot;
+ &quot;        &lt;p&gt;-- BarCode from attachment&lt;br&gt;&lt;img src=\&quot;cid:barcode\&quot;&gt;&lt;/p&gt;&lt;br&gt;BarCode render completed\n&quot;
+ &quot;    &lt;/body&gt;\n&quot; + &quot;&lt;/html&gt;&quot;;
String toAddrsStr = &quot;emailID1, emailID2, emailID3&quot;;
sendEmailWithAttachment(toAddrsStr, subject, body, filePath);

Definition:

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, &quot;UTF-8&quot;);
message.setFrom(new InternetAddress(&quot;gowthamdpt@gmail.com&quot;));
//to address String should be with comma separated.
message.setRecipients(javax.mail.Message.RecipientType.TO, InternetAddress.parse(to));
MimeMultipart msg = new MimeMultipart(&quot;alternative&quot;);
MimeBodyPart wrap = new MimeBodyPart();
MimeMultipart msgBody = new MimeMultipart(&quot;mixed&quot;);
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(body, &quot;text/html; charset=UTF-8&quot;);
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(&quot;&lt;barcode&gt;&quot;);
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(&quot;sendEmail()&quot; + &quot;email triggered successfully&quot;);
} catch (Exception ex) {
System.out.println(&quot;sendEmail()&quot; + &quot;The email was not sent. Error: &quot; + ex.getMessage());
}
}

huangapple
  • 本文由 发表于 2020年8月28日 07:23:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63625403.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定