英文:
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, "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][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
头,并使用该名称检索相关图像 - 但该名称需要用尖括号 <
和 >
括起来以内联显示(如下所示)。
在此处查看更多信息 [这里][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);
}
在此示例中,我们构建了一个包含两部分的消息:
- 来自
BODY
的 HTML 内容。 - 图像。
在我的示例中,图像是文件系统上的一个文件 - 但您可以根据应用程序的需要以任何方式访问它(例如通过资源)。
注意在设置头文件时尖括号的使用(如前面所述):
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>");
文本 <image_01>
是您在 HTML 代码中引用图像的方式。因此,这就是为什么我的示例代码使用了这个:
<img src=\"cid:image_01\">
您可以在这里使用任何标识符。在我的示例中,标识符 "image_01" 是指我的图像文件 "logo.png"。
但是请明确一点 - 在您的代码中确实需要包含 <
和 >
。它们不仅仅是我代码中的“占位符”,它们是您需要使用的语法的一部分。
但是请记住,如果您充分利用 Spring 和 Spring 邮件辅助函数,一切都可以变得更简单。
例如,以下是相同方法的 Spring JavaMailSender
和 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 = "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="cid:image_01"></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 `<` and `>` 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's wrapper around the JavaMail (now JakartaMail) object. You don'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's mail helper utilities. There are lots of guides and tutorials for that elsewere.
**A Note on SES**
The above approach is using Amazon'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 `<image_01>` is how you refer to your image, in your HTML code. So, that is why my example code uses this:
<img src="cid:image_01">
You can use any identifier you want here. In my case the identifier "image_01" refers to my image file "logo.png".
But just to be clear - you really do need to include the `<` and the `>` in your code. They are not there just as "placeholders" 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'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 = "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, 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 `<` and `>` 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 = "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);
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, "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());
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论