在Google App Engine(Java)上发送内联电子邮件附件

时间:2012-03-07 10:11:31

标签: java google-app-engine email javamail

我很难让我的内联附件显示为内联。当电子邮件客户端收到消息时,所有附件都带有 Content-Disposition “附件”,即使我可以从日志中看到我设置的内容为“内联” ”。此外,无论何时我设置CID标头,它都没有进入电子邮件客户端(例如,如果我查看源/原始)。不知何故,它与内容处置一样丢失。

我使用以下代码:

public static void performSend(Event event, Guest guest) throws Exception {
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    String htmlBody = event.getEmail().getHtmlBody(event.getInlineInvitationImages(), guest);
    Multipart mp = new MimeMultipart();

    MimeBodyPart htmlPart = new MimeBodyPart();
    htmlPart.setContent(htmlBody, "text/html");
    mp.addBodyPart(htmlPart);

    //Add attachments
    for(InvitationImage image : event.getInvitationImages()) {
        Logger.info("Now attaching image %s, with length %d, content type %s, cid %s and disposition %s", image.filename, image.imageData.length, image.contentType, image.cid, image.getDisposition().toString());
        MimeBodyPart attachment = new MimeBodyPart();
        attachment.setDisposition(image.getDisposition());
        attachment.setFileName(image.filename);
        attachment.setContentID("<"+image.cid+">");

        DataSource src = new ByteArrayDataSource(image.imageData, image.contentType); 
        attachment.setDataHandler(new DataHandler(src));
        mp.addBodyPart(attachment);
    }

    Message msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress("myname@gmail.com", "My Name"));
    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(guest.email, guest.getFullname()));
    msg.setSubject(event.getEmail().subject);
    msg.setContent(mp);
    msg.saveChanges();

    //Log the email
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    msg.writeTo(baos);
    new Log(baos.toByteArray()).save();

    Transport.send(msg);
}

我的GAE日志中的相关代码段是

  

play.Logger info:现在附上图片myimage.jpg,长度为73336,   内容类型image / jpeg,cid   e4ae3388-312d-498e-b958-12e814507934@rsvp-rocket.appspot.com和   内联处理

电子邮件来源的相关摘录如下所示:

Content-Type: multipart/mixed; boundary=20cf307f3beca61df004baa44d82
Return-Path: 3-jJXTwsJDD0qruo-qnbjdsflZhk.bnljZxcddcnqfZmgnslZhk.bnl@apphosting.bounces.google.com
X-OriginalArrivalTime: 07 Mar 2012 10:05:47.0455 (UTC) FILETIME=[DE047CF0:01CCFC49]

--20cf307f3beca61df004baa44d82
Content-Type: multipart/alternative; boundary=20cf307f3beca61de604baa44d80

--20cf307f3beca61de604baa44d80
Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes

Come to my wedding!



--20cf307f3beca61de604baa44d80
Content-Type: text/html; charset=ISO-8859-1

<p style="color: gray;">Come to my wedding!</p><div><img src="cid:e4ae3388-312d-498e-b958-12e814507934@rsvp-rocket.appspot.com" border="0" /></div>
--20cf307f3beca61de604baa44d80--
--20cf307f3beca61df004baa44d82
Content-Type: image/jpeg; name="DamianKathrynWeddingSaveTheDate.jpg"
Content-Disposition: attachment; 
    filename="DamianKathrynWeddingSaveTheDate.jpg"
Content-Transfer-Encoding: base64

有什么想法?为什么要清除处置和CID?我是否遗漏了一些明显的片段,或者这是电子邮件的神秘艺术的一个例子?

更新

我已将传出的电子邮件转储到数据存储区中的Log实体。在那里,我可以看到内联图像确实具有“内联”的内容配置。因此,当它到达电子邮件客户端时,某些东西已将其删除。奇怪的是,html部分是base64编码的(如下所示)。这是正常的吗?

以下是Gmail的内容:

Message-ID: <20cf307d02b099e30804bab9b98e@google.com>
Date: Thu, 08 Mar 2012 11:39:12 +0000
Subject: Test invite
From: My Name <myname@gmail.com>
To: My Name <myname@gmail.com>
Content-Type: multipart/mixed; boundary=20cf307d02b099e2fb04bab9b98d

--20cf307d02b099e2fb04bab9b98d
Content-Type: multipart/alternative; boundary=20cf307d02b099e2f404bab9b98b

--20cf307d02b099e2f404bab9b98b
Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes

Come to my wedding!



--20cf307d02b099e2f404bab9b98b
Content-Type: text/html; charset=ISO-8859-1

<p style="color: gray;">Come to my wedding!</p><div><img src="cid:e4ae3388-312d-498e-b958-12e814507934@rsvp-rocket.appspot.com" border="0" /></div>
--20cf307d02b099e2f404bab9b98b--
--20cf307d02b099e2fb04bab9b98d
Content-Type: image/jpeg; name="DamianKathrynWeddingSaveTheDate.jpg"
Content-Disposition: attachment; 
    filename="DamianKathrynWeddingSaveTheDate.jpg"
Content-Transfer-Encoding: base64

/9j/4AAQSkZJRgABAQEBLAEsAAD/7QBSUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAABkcAVoAAxsl

以下是我为同一条消息记录的内容:

From: My Name <myname@gmail.com>
To: My Name <myname@gmail.com>
Message-ID: <29985819.01331206751990.JavaMail.javamailuser@localhost>
Subject: Test invite
MIME-Version: 1.0
Content-Type: multipart/mixed; 
    boundary="----=_Part_0_20814850.1331206751553"

------=_Part_0_20814850.1331206751553
Content-Type: text/html
Content-Transfer-Encoding: base64

PHAgc3R5bGU9ImNvbG9yOiBncmF5OyI+Q29tZSB0byBteSB3ZWRkaW5nITwvcD48ZGl2PjxpbWcg
c3JjPSJjaWQ6ZTRhZTMzODgtMzEyZC00OThlLWI5NTgtMTJlODE0NTA3OTM0QHJzdnAtcm9ja2V0
LmFwcHNwb3QuY29tIiBib3JkZXI9IjAiIC8+PC9kaXY+
------=_Part_0_20814850.1331206751553
Content-Type: image/jpeg; name=DamianKathrynWeddingSaveTheDate.jpg
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=DamianKathrynWeddingSaveTheDate.jpg
Content-ID: <e4ae3388-312d-498e-b958-12e814507934@rsvp-rocket.appspot.com>

/9j/4AAQSkZJRgABAQEBLAEsAAD/7QBSUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAABkcAVoAAxsl

有什么想法吗?当我查看亚马逊SES和邮戳时,GAE上的电子邮件很快就会变成“太难”的篮子。

3 个答案:

答案 0 :(得分:1)

首先,考虑使用Session.getInstance()替换Session.getDefaultInstance()。我不知道这是否与您的问题有关,但它将避免潜在的未来问题。

要找出消息未达到预期效果的原因,请使用msg.writeTo(new FileOutputStream(“msg.txt”))在Transport.send()之前保存副本,然后比较其中的内容您在邮件客户端中看到的文件。如果它们不相同,最可能的原因是您正在使用的一个邮件服务器正在将消息转换为认为消息应该是什么样的。 Exchange经常这样做。

答案 1 :(得分:0)

您可能希望为以下AppEngine问题加注星标:

http://code.google.com/p/googleappengine/issues/detail?id=965

答案 2 :(得分:0)

不幸的是GAE没有提供这样的功能。

Google为GAE应用程序提供标准的javax.mail API。您不必在依赖项列表中包含任何SUN的/ Oracle * .jar。事实上,GAE提供了自己的javax.mail实现,它只与原始SUN实现半兼容。此外,GAE在引擎盖下执行一些完全意外的操作。例如,如果您发送纯HTML电子邮件,接收方将获得带有mime“alternative”的多部分消息,该消息将包含HTML剥离文本/纯文本消息以及原始HTML邮件。当你尝试使用带有cid嵌入式内嵌图像的html时,你也会遇到一堆例外。此外,任何“MimeMultiPart”嵌套都会导致异常或未定义的行为。仔细检查后,从Google文档中可以明显看出,对javax.mail的支持非常有限。他们甚至提到它:“出于安全考虑,消息部分和附件必须是几种允许类型之一”。对于这种有限的支持,安全性可能只是一个而非最终的原因。