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

7
一个在StackOverflow上得到回答的问题建议在电子邮件正文中添加html标记以达到效果。这个解决方案正确吗?但是如果收件人的电子邮件服务器/客户端不支持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");

有没有办法告诉Gmail API如果收件人的电子邮件服务器/客户端不支持HTML,可以回退到哪一个电子邮件?
附言: 我特别想要Java代码示例。
谢谢。
2个回答

7
为了提供两个选择,您可以将Content-Type设置为mixed/alternative,而不是text/plaintext/html
如果我们想在API浏览器中尝试此操作,我们只需对邮件进行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();

谢谢你!看起来正是正确的做法。正在测试它。 - Scott Mayers
@LevRatinov 很好! :) 很高兴我能帮到你。 - Tholle

3

针对上面来自 Throlle 的回答进行一些更新。

如果想要发送一封标准的电子邮件并遵循他们默认提供的标准,则可以使用以下代码(此示例使用 grails 编写,但是您可以轻松将其更改为 Java。controller 部分在 html 标签之前,请参见此处)。完成后,可能会更新该 github 网站以包含所有这些示例:

在 controller 中的 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}"
        }
    }

并创建带有电子邮件的消息

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
    }

2
作为一则旁注,不确定谷歌的人是否会关注这个列表。如果是的话,也许值得将此示例添加到您现有的 API 文档站点中。因为虽然对我来说弄清楚如何正确地完成所有这些工作是一个相当小的过程,但我怀疑对于初学者来说,这可能会让人不知所措,难以弄清楚这些事情。 - V H
完全正确。叹息! - user13182598

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接