Reputation: 11550
I'm having difficulty getting my inline attachments to show up inline. When the email client receives the message all of the attachments are with Content-Disposition "attachment" even though I can see from the logs that I'm setting some to "inline". Also anytime I set the CID header it is not making it to the email client (eg. if I view the source / original). Somehow it is being lost as with the content-disposition.
I am using the following code:
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("[email protected]", "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);
}
A relevant snippet from my GAE log is
play.Logger info: Now attaching image myimage.jpg, with length 73336, content type image/jpeg, cid [email protected] and disposition inline
A relevant snippet of the email source looks like this :
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:[email protected]" border="0" /></div>
--20cf307f3beca61de604baa44d80--
--20cf307f3beca61df004baa44d82
Content-Type: image/jpeg; name="DamianKathrynWeddingSaveTheDate.jpg"
Content-Disposition: attachment;
filename="DamianKathrynWeddingSaveTheDate.jpg"
Content-Transfer-Encoding: base64
Any thoughts? Why is the disposition and CID being cleared? Am I missing some obvious piece or is this an example of the arcane arts of email?
I've dumped the outgoing email to a Log entity in the datastore. In there I can see that the inline image does indeed have the Content-Disposition of "inline". So by the time it gets to the email clients, something has removed it. The weird thing is that the html part is base64 encoded (as per below). Is this normal?
Here's what arrives at Gmail:
Message-ID: <[email protected]>
Date: Thu, 08 Mar 2012 11:39:12 +0000
Subject: Test invite
From: My Name <[email protected]>
To: My Name <[email protected]>
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:[email protected]" 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
And here's what is logged by me for the same message:
From: My Name <[email protected]>
To: My Name <[email protected]>
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: <[email protected]>
/9j/4AAQSkZJRgABAQEBLAEsAAD/7QBSUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAABkcAVoAAxsl
Any ideas? Email on GAE is quickly making it to the "too-hard" basket when I look at Amazon SES and Postmark.
Upvotes: 2
Views: 2080
Reputation: 422
Unfortunatelly GAE does not provides such functionality.
Google provides standard javax.mail API for GAE applications. You do not have to include any SUN’s/Oracle *.jar in your dependency list. In fact GAE provides its own implementation of javax.mail that is only semi-compatible with original SUN implementation. Moreover GAE performs some completely unexpected operations under the hood. For example, if you send a pure HTML email, receiver will get multipart message with mime “alternative” that will contain HTML stripped text/plain message plus your original HTML mail. Also you will get into bunch of exceptions, when trying to use html with cid – embedded inline images. Also any “MimeMultiPart” nesting will lend to exception or undefined behavior. When you examine it carefully, it will become obvious – from Google documentation – that support for javax.mail is very limited. They even mention it: “For security purposes, message parts and attachments must be of one of several allowed types”. Probably the security is one but not ultimate reason for such limited support.
Upvotes: 0
Reputation: 161
You might want to star the following AppEngine issue:
http://code.google.com/p/googleappengine/issues/detail?id=965
Upvotes: 0
Reputation: 29971
First, consider replacing Session.getDefaultInstance() with Session.getInstance(). I don't know if that has anything to do with your problem, but it will avoid potential future problems.
To find out why the message isn't getting through the way you expect, save a copy just before the Transport.send() using msg.writeTo(new FileOutputStream("msg.txt")), then compare what's in the file with what you're seeing in your mail client. If they're not the same, the most likely cause is that one of the mail servers you're using is transforming the message to what it thinks the message should look like. Exchange does this frequently.
Upvotes: 1