6

I'm working on an application to send mails to lists etc. It's written in Java using the javax.mail api. The problem here is, I can't embed images using a CID.

This is the source of the mail that is sent:

Delivered-To: -@gmail.com
Received: by 10.43.50.4 with SMTP id vc4csp85536icb;
        Tue, 17 Apr 2012 05:08:00 -0700 (PDT)
Received: by 10.204.141.25 with SMTP id k25mr4406030bku.72.1334664479298;
        Tue, 17 Apr 2012 05:07:59 -0700 (PDT)
Return-Path: <-@gmail.com>
Received: from mail-bk0-f43.google.com (mail-bk0-f43.google.com [209.85.214.43])
        by mx.google.com with ESMTPS id ad16si7984294bkc.150.2012.04.17.05.07.58
        (version=TLSv1/SSLv3 cipher=OTHER);
        Tue, 17 Apr 2012 05:07:59 -0700 (PDT)
Received-SPF: pass (google.com: domain of -@gmail.com designates 209.85.214.43 as permitted sender) client-ip=209.85.214.43;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of - designates 209.85.214.43 as permitted sender) smtp.mail=-; dkim=pass header.i=@gmail.com
Received: by mail-bk0-f43.google.com with SMTP id j5so5978375bkw.2
        for <-@gmail.com>; Tue, 17 Apr 2012 05:07:58 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:message-id:subject:mime-version:content-type;
        bh=Xj44O9fBIzirvcquOGxJbYLtbqgBc2Ags7prNUuAtSQ=;
        b=WWTCdrFgs3RCT/g2qXHR0fLCTc73TmNMA15sff0oIDksB6Nn3IwTYAqTVmoGiNrkW5
         08WDpTRADEKAOvjQ5FC9/uBCh1RXWTjxtawfjHc7vfUpqKbXOCj8Ab6GWXQMmX/+WB6T
         KVYLhk3/+GddIJI1XsAX9zprSYVcP6MMJ5/U+idIDlC7xQGGNuvzvpAnlnlGuWzgKc6j
         qPoFSAAaio6zICY9uSaI0deBIYTEQ2hIuBDJG8oaRvGVvpjhzJaBK+ab+rPJEboHPg8S
         3WSCG/Pp212VOw/YXOLUQV0jmMbuqAbsGdeER+Okbwe11sWi+zvPz+jhplB0NB2wq0Fn
         mWzA==
Received: by 10.204.130.13 with SMTP id q13mr4084640bks.128.1334664478358;
        Tue, 17 Apr 2012 05:07:58 -0700 (PDT)
Return-Path: <-t@gmail.com>
Received: from Akoya ([xx])
        by mx.google.com with ESMTPS id z14sm37467763bky.15.2012.04.17.05.07.51
        (version=SSLv3 cipher=OTHER);
        Tue, 17 Apr 2012 05:07:54 -0700 (PDT)
Date: Tue, 17 Apr 2012 05:07:54 -0700 (PDT)
From: BP MM <-@gmail.com>
To: xx xx <-@gmail.com>
Message-ID: <404745073.01334664469900.JavaMail.xx@Akoya>
Subject: TestImage
MIME-Version: 1.0
Content-Type: multipart/mixed; 
    boundary="----=_Part_2_854532868.1334664469871"

------=_Part_2_854532868.1334664469871
Content-Type: multipart/mixed; 
    boundary="----=_Part_1_1457048287.1334664469871"

------=_Part_1_1457048287.1334664469871
Content-Type: image/png; name=logo.png
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=logo.png
Content-ID: img_cid

[base64 data]
------=_Part_1_1457048287.1334664469871--

------=_Part_2_854532868.1334664469871
Content-Type: multipart/alternative; 
    boundary="----=_Part_0_1033690582.1334664469858"

------=_Part_0_1033690582.1334664469858
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello


------=_Part_0_1033690582.1334664469858
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<html>
<body>
<H1>Hello</H1>
<img src="cid:img_cid">
</body>
</html>

------=_Part_0_1033690582.1334664469858--

------=_Part_2_854532868.1334664469871--

I've tried different CID's, adding < and > to the CID, setting disposition to inline, validated HTML etc. Can't get this to work, Thunderbird and Gmail view the mail with 'dead' images. I've read that the client looks for the cid in the mail, so I figuered it should fetch the image correctly. Sending the attachment does work, but embedding doesn't. Anyone that has a clue? Is it related to the Multipart structure?

The java code for creating the message (i've commented some lines trying to solve it..)

    /*
     * The method to create a MimeMessage, this message can be sent with the transport method.
     */
    private Message createMessage(final Mail mail, final Member member, final MailingList list,
            final MailAccount mailAccount, final Session session)
            throws MessagingException, UnsupportedEncodingException {
        // Get attachments
        @SuppressWarnings("unchecked")
        List<File> attachments = (List<File>) mail.getProperty(Mail.ATTACHMENTS_KEY);

        // Create content parts
        String plainContent = templateEngine.replaceTemplateTags(mail, member, list, mailAccount);
        String htmlContent = templateEngine.replaceHTMLTemplateTags(mail, member, list, mailAccount);

        Multipart multiContentPart = new MimeMultipart("alternative");
//      Multipart attachmentsBodyPart = new MimeMultipart();
        Multipart rootBodyPart = new MimeMultipart();

        // Create plain text part
        if (!plainContent.equals("")) {
            BodyPart plainMessageBodyPart = new MimeBodyPart();
            plainMessageBodyPart.setContent(plainContent, "text/plain");
            multiContentPart.addBodyPart(plainMessageBodyPart);
        }

        // Create html part
        if (!htmlContent.equals("")) {
            BodyPart htmlMessageBodyPart = new MimeBodyPart();
            htmlMessageBodyPart.setContent(htmlContent, "text/html");
            multiContentPart.addBodyPart(htmlMessageBodyPart);
        }

        // Create attachments
        if (attachments != null && attachments.size() > 0) {
            for (int i = 0; i < attachments.size(); i++) {
                BodyPart attachmentBodyPart = new MimeBodyPart();
                DataSource source = new FileDataSource(attachments.get(i));
                attachmentBodyPart.setDataHandler(new DataHandler(source));
                attachmentBodyPart.setFileName(attachments.get(i).getName());
                attachmentBodyPart.setHeader("Content-ID", "<img_cid>");
                attachmentBodyPart.setDisposition(Part.INLINE);
//              attachmentsBodyPart.addBodyPart(attachmentBodyPart);
                rootBodyPart.addBodyPart(attachmentBodyPart);
            }
            // Build attachments
//          BodyPart attachmentsWrapper = new MimeBodyPart();
//          attachmentsWrapper.setContent(attachmentsBodyPart);
//          rootBodyPart.addBodyPart(attachmentsWrapper);
        }

        // Build content
        BodyPart contentWrapper = new MimeBodyPart();
        contentWrapper.setContent(multiContentPart);
        rootBodyPart.addBodyPart(contentWrapper);

        // Create message
        Message message = new MimeMessage(session);
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(
                member.getEmail(), member.getName()));
        message.setSubject((String) mail.getProperty(Mail.SUBJECT_KEY));
        message.setContent(rootBodyPart);

        // Add headers
        message.setFrom(new InternetAddress(mailAccount.getFromAddress(),
                mailAccount.getFromName()));
        if (mailAccount.getReplyTo() != "" && mailAccount.getReplyTo() != null)
            message.setReplyTo(InternetAddress.parse(mailAccount.getReplyTo()));

        return message;
    }

Don't mind the CID being the same for each attachment, later this will be the file name - I'm only testing with a single attachment for now. Hope this helps..

krobbens
  • 101
  • 1
  • 1
  • 9
  • the code would be really useful. – TheVoidSeeker Apr 17 '12 at 13:32
  • The same or a very similar problem was already solved in [this thread](http://stackoverflow.com/questions/2996514/inline-images-in-email-using-javamail)! – TheVoidSeeker Apr 17 '12 at 13:36
  • 1
    the thread you linked doesn't supply a valid solution. i need the attachment added as an inline embedded image. i cannot encodebase64 the image again for , that way the base64string will be in the mail twice.. I've added the code to create the message above. – krobbens Apr 17 '12 at 13:52
  • I don't understand why it doesn't fetch the attachment through the cid. the source of the sent mail looks exactly like one I would send with another email client. This problem is still not fixed, anyone that has an idea? – krobbens Apr 18 '12 at 09:06

3 Answers3

4

I found that there wasn't anything wrong with the mail source. It's the way mailclients handle CIDs. Gmail.com requires the CID to be set between < and >. Thunderbird hasn't shown my images yet.. I think it needs to be unique of some sort.. Still haven't figured why and how to fix it. Found it through Embedding images into html email with java mail

Community
  • 1
  • 1
krobbens
  • 101
  • 1
  • 1
  • 9
  • It seems to be due to the wrong content type of the MIME format. I think the structure of the body parts are wrong. The one that doesn't work has: Content-Type: multipart/mixed; this should work: Content-Type: multipart/related; type="multipart/alternative"; I haven't found the correct structure yet to display text/html/embedded images as it should. – krobbens Apr 19 '12 at 08:46
  • 1
    The solution is a combination of the cid reference and the multipart structure. Validate your cid (needs < and >, sometimes an @). Make sure your root is multipart/relative, add the multipart/alternative of html/text to it (wrapped in a bodypart) and afterwards add the attachments to the root part (each in its own bodypart). See http://www.coderanch.com/t/503380/java/java/Java-Mail-text-html-attachment – krobbens Apr 19 '12 at 09:53
  • 2
    A very good source for combining body parts http://blogs.technet.com/b/exchange/archive/2011/04/21/mixed-ing-it-up-multipart-mixed-messages-and-you.aspx – krobbens Apr 24 '12 at 08:49
  • 2
    To make it work in Thunderbird, remove this line: attachmentBodyPart.setHeader("Content-ID", ""); and add these two lines: attachmentBodyPart.addHeader("Content-ID", ""); attachmentBodyPart.addHeader("Content-Type", "image/png"); This assumes that you have the following somewhere in your HTML body: – JDJ Mar 17 '14 at 10:20
0

CID is working correctly , problem is when you are sending mail to mutilple email id , you have to initlize MimeMessage every time the you will not get error

MimeMessage m = new MimeMessage(mailSession);

0

It seems incredible, but all html tags must be on the same line. Between '<' and '>' there can be no carriage return. The parser is very seedy.