最佳实践 - 发送 javamail mime 多部分电子邮件 - 和 gmail

2022-01-17 00:00:00 html-email smtp java tomcat jakarta-mail

我有一个需要发送确认电子邮件等的 Tomcat 应用程序.我已经使用 Javamail (mail.jar) 对电子邮件程序进行了编码,以发送多部分文本/html 电子邮件.我的代码基于 Java EE 示例.我在本地服务器上使用 SMTP MTA.

I have a Tomcat application that needs to send confirmation emails etc. I have coded the emailer with Javamail (mail.jar) to send multipart text/html emails. I based the code on the Java EE examples. I'm using the SMTP MTA on the local server.

效果很好.在 Outlook 中,我看到了 HTML 版本.如果我将它拖到 Outlook 垃圾邮件文件夹中,我会看到文本版本.所以我将其解释为有效.

It works great. In Outlook, I see the HTML version. If I drag it into the Outlook spam folder, I see the text version. So I interpret that as saying it works.

但是,如果我在 Gmail 中查看电子邮件,我只能看到文本版本.我知道 HTML 就在那里(Outlook 就是从那里得到它的).但是 Gmail 没有显示它...我有很多来自其他系统的电子邮件在 Gmail 中显示为 HTML.

However, if I view the emails in Gmail, I see only the text version. I know the HTML is there (that's where Outlook got it from). But Gmail is not showing it... I have lots of emails from other systems that show as HTML in Gmail.

谁能指出我所缺少的规范?我需要创建特殊的标题吗?

Can anyone point me to the spec that shows what I am missing? Are there special headers I need to create?

谢谢

代码如下:

Message message = new MimeMessage(session);
Multipart multiPart = new MimeMultipart("alternative");

try {

    MimeBodyPart textPart = new MimeBodyPart();
    textPart.setText(text, "utf-8");

    MimeBodyPart htmlPart = new MimeBodyPart();
    htmlPart.setContent(html, "text/html; charset=utf-8");

    multiPart.addBodyPart(htmlPart);
    multiPart.addBodyPart(textPart);
    message.setContent(multiPart);

    if(from != null){
        message.setFrom(new InternetAddress(from));
    }else
        message.setFrom();

    if(replyto != null)
        message.setReplyTo(new InternetAddress[]{new InternetAddress(replyto)});
    else
        message.setReplyTo(new InternetAddress[]{new InternetAddress(from)});

    InternetAddress[] toAddresses = { new InternetAddress(to) };
    message.setRecipients(Message.RecipientType.TO, toAddresses);
    message.setSubject(subject);
    message.setSentDate(new Date());

    Transport.send(message);

} catch (AddressException e) {
    e.printStackTrace();
    System.out.println("Error: "+e.getMessage());

} catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("Error: "+e.getMessage());

} finally {     
    System.out.println("Email sent!");
}

推荐答案

解决了!似乎根据多部分 MIME 规范,部分的顺序很重要.应按从低保真到高保真的顺序添加它们.因此,GMail 似乎遵循规范并使用最后一部分.就我而言,我有它们 HTML,文本.我只是将订单换成文本、HTML 和 Gmail 正确呈现它...

Solved! It seems according to the multipart MIME spec, the order of the parts are important. They should be added in order from low fidelity to high fidelity. So it seems GMail follows the spec and uses the last part. In my case I had them HTML, Text. I just swapped the order to Text, HTML and Gmail renders it correctly...

MimeBodyPart textPart = new MimeBodyPart();
textPart.setText(text, "utf-8");

MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(html, "text/html; charset=utf-8");

multiPart.addBodyPart(textPart); // <-- first
multiPart.addBodyPart(htmlPart); // <-- second
message.setContent(multiPart);

感谢您的帮助!

相关文章