通过 Gmail API 发送带有纯文本回退的 HTML 电子邮件

Posted

技术标签:

【中文标题】通过 Gmail API 发送带有纯文本回退的 HTML 电子邮件【英文标题】:Send HTML email with plain text fallback via Gmail API 【发布时间】:2016-03-13 22:10:25 【问题描述】:

An answered question at *** 建议将 html-markup 添加到电子邮件正文中。该解决方案正确吗?

但是如果收件人的电子邮件服务器/客户端不支持 HTML 电子邮件怎么办?

例如使用Apache commons email 时,我执行以下操作:

// set the html message
email.setHtmlMsg("<html>Our logo - <img src=\"cid:"+cid+"\"></html>");
// set the alternative message
email.setTextMsg("Your email client does not support HTML messages");

如果收件人电子邮件服务器/客户端不支持 HTML,有什么方法可以告诉 Gmail API 回退到哪个电子邮件?

附: 我对 Java 代码示例特别感兴趣。

谢谢

【问题讨论】:

【参考方案1】:

要提供两种选择,您可以将Content-Type 设置为mixed/alternative 而不是text/plaintext/html

如果我们想在API explorer 中尝试这一点,我们只需对邮件进行 Base64 编码,并通过将所有 / 替换为 _ 并将所有 + 替换为 - 来使其 url 安全。

在开发者控制台中:

btoa(
  "Subject: Example Subject\r\n" +
  "From: <example@gmail.com>\r\n" +
  "To: <example@gmail.com>\r\n" +
  "Content-Type: multipart/alternative; boundary=\"foo_bar\"\r\n\r\n" +

  "--foo_bar\r\n" +
  "Content-Type: text/plain; charset=UTF-8\r\n\r\n" +

  "*Bold example message text*\r\n\r\n" +

  "--foo_bar\r\n" +
  "Content-Type: text/html; charset=UTF-8\r\n\r\n" +

  "<div dir=\"ltr\"><b>Bold example message text</b></div>\r\n\r\n" +

  "--foo_bar--" 
).replace(/\+/g, '-').replace(/\//g, '_');

POST https://www.googleapis.com/gmail/v1/users/me/messages/send?access_token=YOUR_API_KEY


 "raw": "U3ViamVjdDogRXhhbXBsZSBTdWJqZWN0DQpGcm9tOiA8ZXhhbXBsZUBnbWFpbC5jb20-DQpUbzogPGV4YW1wbGVAZ21haWwuY29tPg0KQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvYWx0ZXJuYXRpdmU7IGJvdW5kYXJ5PSJmb29fYmFyIg0KDQotLWZvb19iYXINCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOA0KDQoqQm9sZCBleGFtcGxlIG1lc3NhZ2UgdGV4dCoNCg0KLS1mb29fYmFyDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1VVEYtOA0KDQo8ZGl2IGRpcj0ibHRyIj48Yj5Cb2xkIGV4YW1wbGUgbWVzc2FnZSB0ZXh0PC9iPjwvZGl2Pg0KDQotLWZvb19iYXItLQ=="

要在 Java 中做同样的事情,你可以这样做:

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

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

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

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

ByteArrayOutputStream output = new ByteArrayOutputStream();
message.writeTo(output);
String rawEmail = Base64.encodeBase64URLSafeString(output.toByteArray());

Message message = new Message();
message.setRaw(rawEmail);
message = service.users().messages().send(userId, message).execute();

【讨论】:

谢谢!看起来完全是正确的做法。测试它。 @LevRatinov 甜蜜! :) 很高兴我能帮上忙。【参考方案2】:

Throlle 为上述答案添加更新。 上面有一些差异,可能与更高版本的gmail api不同

发送消息并遵循他们默认提供的标准发送标准电子邮件:

这是在 grails 中,但您可以轻松更改为 java,此 html 内容之前的控制器内容可以是 found here。也许当我完成我正在做的事情并有机会使用所有这些示例更新 github 站点时:

在控制器sendHTMLEmail:

  def sendHTMLEmail() 
        String emailBox='me@gmail.com'
        String to ='someuser@domain.com'
        String html="<html><body><table><tr><td><b>aa</b></td><td>bb</td></tr></table><h1>html content</h1></body></html>"
        MimeMessage content = gmailService.createHTMLEmail(to,emailBox,'gmail test','testing gmail via app',html)
        def message = gmailService.sendMessage(gmail,'me',content)
        render "=== $message.id"

服务中createHTMLEmail

public static MimeMessage createHTMLEmail(String to, String from, String subject, String text, String html) 
        Properties props = new Properties()
        Session session = Session.getDefaultInstance(props, null)

        MimeMessage email = new MimeMessage(session)
        Multipart multiPart = new MimeMultipart("alternative")
        email.setFrom(new InternetAddress(from))
        email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to))
        email.setSubject(subject)

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

        MimeBodyPart htmlPart = new MimeBodyPart()
        htmlPart.setContent(html, "text/html; charset=utf-8")
        
        multiPart.addBodyPart(textPart)
        multiPart.addBodyPart(htmlPart)
        email.setContent(multiPart)
        return email
    

然后他们的标准提供sendMessage(以下位可以在github链接上找到):

public static Message sendMessage(Gmail service,String userId,MimeMessage emailContent) throws MessagingException, IOException 
        try 
            Message message = createMessageWithEmail(emailContent)
            message = service.users().messages().send(userId, message).execute()
            return message
         catch (Exception e) 
            //log.error "$e"
        
    

和 createMessageWithEmail

public static Message createMessageWithEmail(MimeMessage emailContent) throws MessagingException, IOException 
        ByteArrayOutputStream buffer = new ByteArrayOutputStream()
        emailContent.writeTo(buffer)
        byte[] bytes = buffer.toByteArray()
        String encodedEmail = Base64.encodeBase64URLSafeString(bytes)
        Message message = new Message()
        message.setRaw(encodedEmail)
        return message
    

【讨论】:

作为旁注,不确定来自 google 的窥视者是否留意此列表。如果是这样,也许值得将此示例添加到您的 api 文档站点的现有示例中。因为虽然这对我来说是一个相当小的过程来弄清楚如何正确地做到这一点。我怀疑对于新手初学者来说,这可能过于复杂,无法弄清楚这些事情 绝对正确。叹息!?

以上是关于通过 Gmail API 发送带有纯文本回退的 HTML 电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

jQuery和带有回退的jqueryui CDN

用于发送带有附件的电子邮件的 GMAIL API

GMail 显示纯文本电子邮件而不是 HTML

是否有任何详细的教程或案例研究用于使用带有 HLS 回退的 MPEG-DASH 构建在线视频交付服务?

带有 MimeKit、C# Winforms 和 Google API 的 Gmail 草稿(带附件的 HTML)

29. Xshell连接Linux下Oracle无法回退的解决办法