问题描述
我在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();
}
}
解决方法
要将图像嵌入到电子邮件中,您需要对代码进行一些更改。我使用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);
}
在这里,我们构建一条由两部分组成的消息:
-
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,ex);
}
关于JavaMailSender
的注释
在您的代码中,包括以下内容:
private JavaMailSender mailSender;
是Spring围绕JavaMail(现在为JakartaMail)对象的包装。您不会在代码中使用此对象。
鉴于您正在使用Spring,我建议您使用上述方法,然后重构代码以利用Spring的邮件帮助器实用程序。有很多其他的指南和教程。
关于SES的说明
以上方法使用的是Amazon的SES SMTP interface。换句话说,您的代码中不需要任何Amazon SDK类。
这是我在测试此答案中的代码时使用的(使用SES帐户)。
您当然可以考虑使用记录在here和here中的其他两种方法中的任何一种-但是显示图像都不是必需的。
更新
有人问了一个问题,以供澄清:
messageBodyPart.setHeader("Content-ID","<image_01>");
文本<image_01>
是在HTML代码中引用图像的方式。因此,这就是我的示例代码使用此代码的原因:
<img src=\"cid:image_01\">
您可以在此处使用所需的任何标识符。在我的情况下,标识符“ image_01”是指我的图像文件“ logo.png”。
但是要清楚一点-您确实需要在代码中包含<
和>
。它们不像我的代码中的“占位符”一样存在-它们是您需要使用的语法的一部分。
但是请记住,如果您充分利用Spring和 Spring Mail Helper功能,则可以使一切变得更加简单。
例如,这是使用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("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());
}
}