You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by di...@apache.org on 2007/02/23 00:35:26 UTC
svn commit: r510708 - in /jakarta/commons/proper/email/trunk/src:
java/org/apache/commons/mail/HtmlEmail.java
test/org/apache/commons/mail/HtmlEmailTest.java
test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java
Author: dion
Date: Thu Feb 22 15:35:23 2007
New Revision: 510708
URL: http://svn.apache.org/viewvc?view=rev&rev=510708
Log:
EMAIL-50 HTML Emails with images don't display in Outlook 2000
Modified:
jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java
jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/HtmlEmailTest.java
jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java
Modified: jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java?view=diff&rev=510708&r1=510707&r2=510708
==============================================================================
--- jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java (original)
+++ jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java Thu Feb 22 15:35:23 2007
@@ -20,9 +20,9 @@
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
+import java.util.Map;
import javax.activation.DataHandler;
import javax.activation.URLDataSource;
@@ -69,8 +69,11 @@
/** Html part of the message */
protected String html;
- /** Embedded images */
- protected List inlineImages = new ArrayList();
+ /**
+ * Embedded images Map<String,InlineImages> where the key is the
+ * user-defined image name
+ */
+ protected Map inlineImages = new HashMap();
/** HTML prefix and suffix for default HTML mail */
private static final String HTML_MESSAGE_START = "<html><body><pre>";
@@ -162,14 +165,14 @@
*/
public String embed(String url, String name) throws EmailException
{
- try
- {
- return embed(new URL(url), name);
- }
- catch (MalformedURLException e)
- {
- throw new EmailException("Invalid URL", e);
- }
+ try
+ {
+ return embed(new URL(url), name);
+ }
+ catch (MalformedURLException e)
+ {
+ throw new EmailException("Invalid URL", e);
+ }
}
/**
@@ -179,7 +182,8 @@
* the mail body. It allows, for instance, to add inline images
* to the email. Inline files may be referenced with a
* <code>cid:xxxxxx</code> URL, where xxxxxx is the Content-ID
- * returned by the embed function.
+ * returned by the embed function. It is an error to bind the same name
+ * to more than one URL.
*
* <p>Example of use:<br><code><pre>
* HtmlEmail he = new HtmlEmail();
@@ -189,6 +193,13 @@
* // code to set the others email fields (not shown)
* </pre></code>
*
+ * <p>
+ * NOTE: Clients should take care to ensure that different URLs are bound to
+ * different names. This implementation tries to detect this and throw
+ * <code>EmailException</code>. However, it is not guaranteed to catch
+ * all cases, especially when the URL refers to a remote HTTP host that
+ * may be part of a virtual host cluster.
+ *
* @param url The URL of the file.
* @param name The name that will be set in the filename header
* field.
@@ -199,6 +210,31 @@
*/
public String embed(URL url, String name) throws EmailException
{
+ InlineImage ii = null;
+
+ // check if the URL contents have already been attached;
+ // if so, return the cached CID value.
+ if (inlineImages.containsKey(name))
+ {
+ ii = (InlineImage) inlineImages.get(name);
+ // make sure the supplied URL points to the same thing
+ // as the one already associated with this name.
+ if (url.equals(ii.getURL()))
+ {
+ return ii.getCid();
+ }
+ else
+ {
+ throw new EmailException("embedded file name '" + name
+ + " is already bound to URL " + ii.getURL().toString()
+ + "; existing names cannot be rebound");
+ }
+ // NOTE: Comparing URLs with URL.equals() is known to be
+ // inconsistent when dealing with virtual hosting over HTTP,
+ // but since these are almost always files on the local machine,
+ // using equals() should be sufficient.
+ }
+
// verify that the URL is valid
try
{
@@ -218,8 +254,11 @@
mbp.setFileName(name);
mbp.setDisposition("inline");
String cid = EmailUtils.randomAlphabetic(HtmlEmail.CID_LENGTH).toLowerCase();
- mbp.addHeader("Content-ID", "<" + cid + ">");
- this.inlineImages.add(mbp);
+ mbp.setContentID("<" + cid + ">");
+
+ ii = new InlineImage(cid, url, mbp);
+ this.inlineImages.put(name, ii);
+
return cid;
}
catch (MessagingException me)
@@ -238,17 +277,7 @@
{
try
{
- // if the email has attachments then the base type is mixed,
- // otherwise it should be related
- if (this.isBoolHasAttachments())
- {
- this.buildAttachments();
- }
- else
- {
- this.buildNoAttachments();
- }
-
+ build();
}
catch (MessagingException me)
{
@@ -261,22 +290,29 @@
* @throws EmailException EmailException
* @throws MessagingException MessagingException
*/
- private void buildAttachments() throws MessagingException, EmailException
+ private void build() throws MessagingException, EmailException
{
MimeMultipart container = this.getContainer();
MimeMultipart subContainer = null;
- MimeMultipart subContainerHTML = new MimeMultipart("related");
BodyPart msgHtml = null;
BodyPart msgText = null;
- container.setSubType("mixed");
+ container.setSubType("related");
subContainer = new MimeMultipart("alternative");
if (EmailUtils.isNotEmpty(this.text))
{
msgText = new MimeBodyPart();
- subContainer.addBodyPart(msgText);
+ if (this.inlineImages.size() > 0)
+ {
+ subContainer.addBodyPart(msgText);
+ }
+ else
+ {
+ container.addBodyPart(msgText);
+ }
+ // apply default charset if one has been set
if (EmailUtils.isNotEmpty(this.charset))
{
msgText.setContent(
@@ -291,17 +327,17 @@
if (EmailUtils.isNotEmpty(this.html))
{
+ msgHtml = new MimeBodyPart();
if (this.inlineImages.size() > 0)
{
- msgHtml = new MimeBodyPart();
- subContainerHTML.addBodyPart(msgHtml);
+ subContainer.addBodyPart(msgHtml);
}
else
{
- msgHtml = new MimeBodyPart();
- subContainer.addBodyPart(msgHtml);
+ container.addBodyPart(msgHtml);
}
+ // apply default charset if one has been set
if (EmailUtils.isNotEmpty(this.charset))
{
msgHtml.setContent(
@@ -313,96 +349,91 @@
msgHtml.setContent(this.html, Email.TEXT_HTML);
}
- Iterator iter = this.inlineImages.iterator();
+ Iterator iter = this.inlineImages.values().iterator();
while (iter.hasNext())
{
- subContainerHTML.addBodyPart((BodyPart) iter.next());
+ InlineImage ii = (InlineImage) iter.next();
+ container.addBodyPart(ii.getMbp());
}
}
- // add sub containers to message
- this.addPart(subContainer, 0);
-
if (this.inlineImages.size() > 0)
{
// add sub container to message
- this.addPart(subContainerHTML, 1);
+ this.addPart(subContainer, 0);
}
}
/**
- * @throws EmailException EmailException
- * @throws MessagingException MessagingException
+ * Private bean class that encapsulates data about URL contents
+ * that are embedded in the final email.
+ * @since 1.1
*/
- private void buildNoAttachments() throws MessagingException, EmailException
+ private static class InlineImage
{
- MimeMultipart container = this.getContainer();
- MimeMultipart subContainerHTML = new MimeMultipart("related");
-
- container.setSubType("alternative");
-
- BodyPart msgText = null;
- BodyPart msgHtml = null;
-
- if (EmailUtils.isNotEmpty(this.text))
+ private String cid;
+ private URL url;
+ private MimeBodyPart mbp;
+
+ /**
+ * Creates an InlineImage object to represent the
+ * specified content ID and <code>MimeBodyPart</code>.
+ * @param cid the generated content ID
+ * @param url the URL that points to the content
+ * @param mbp the <code>MimeBodyPart</code> that contains the encoded
+ * data
+ */
+ public InlineImage(String cid, URL url, MimeBodyPart mbp)
+ {
+ this.cid = cid;
+ this.url = url;
+ this.mbp = mbp;
+ }
+
+ /**
+ * Returns the unique content ID of this InlineImage.
+ * @return the unique content ID of this InlineImage
+ */
+ public String getCid()
{
- msgText = this.getPrimaryBodyPart();
- if (EmailUtils.isNotEmpty(this.charset))
- {
- msgText.setContent(
- this.text,
- Email.TEXT_PLAIN + "; charset=" + this.charset);
- }
- else
- {
- msgText.setContent(this.text, Email.TEXT_PLAIN);
- }
+ return cid;
}
- if (EmailUtils.isNotEmpty(this.html))
+ /**
+ * Returns the URL that points to the encoded content.
+ * @return the URL pointing to the encoded content
+ */
+ public URL getURL() {
+ return url;
+ }
+
+ /**
+ * Returns the <code>MimeBodyPart</code> that contains the
+ * encoded InlineImage data.
+ * @return the <code>MimeBodyPart</code> containing the encoded
+ * InlineImage data
+ */
+ public MimeBodyPart getMbp()
+ {
+ return mbp;
+ }
+
+ // equals()/hashCode() implementations, since this class
+ // is stored as a entry in a Map.
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj) return true;
+ if (!(obj instanceof InlineImage)) return false;
+
+ InlineImage that = (InlineImage) obj;
+
+ return this.cid.equals(that.cid);
+ }
+
+ public int hashCode()
{
- // if the txt part of the message was null, then the html part
- // will become the primary body part
- if (msgText == null)
- {
- msgHtml = getPrimaryBodyPart();
- }
- else
- {
- if (this.inlineImages.size() > 0)
- {
- msgHtml = new MimeBodyPart();
- subContainerHTML.addBodyPart(msgHtml);
- }
- else
- {
- msgHtml = new MimeBodyPart();
- container.addBodyPart(msgHtml, 1);
- }
- }
-
- if (EmailUtils.isNotEmpty(this.charset))
- {
- msgHtml.setContent(
- this.html,
- Email.TEXT_HTML + "; charset=" + this.charset);
- }
- else
- {
- msgHtml.setContent(this.html, Email.TEXT_HTML);
- }
-
- Iterator iter = this.inlineImages.iterator();
- while (iter.hasNext())
- {
- subContainerHTML.addBodyPart((BodyPart) iter.next());
- }
-
- if (this.inlineImages.size() > 0)
- {
- // add sub container to message
- this.addPart(subContainerHTML);
- }
+ return cid.hashCode();
}
}
}
Modified: jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/HtmlEmailTest.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/HtmlEmailTest.java?view=diff&rev=510708&r1=510707&r2=510708
==============================================================================
--- jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/HtmlEmailTest.java (original)
+++ jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/HtmlEmailTest.java Thu Feb 22 15:35:23 2007
@@ -165,19 +165,44 @@
assertNotNull(strEmbed);
assertEquals(HtmlEmail.CID_LENGTH, strEmbed.length());
+ // if we embed the same name again, do we get the same content ID
+ // back?
+ String testCid =
+ this.email.embed(new URL(this.strTestURL), "Test name");
+ assertEquals(strEmbed, testCid);
+
+ // if we embed the same URL under a different name, is the content ID
+ // unique?
+ String newCid =
+ this.email.embed(new URL(this.strTestURL), "Test name 2");
+ assertFalse(strEmbed.equals(newCid));
+
// ====================================================================
// Test Exceptions
// ====================================================================
- // bad URL
+
+ // Does an invalid URL throw an exception?
try
{
- this.email.embed(new URL("http://bad.url"), "Test name");
+ this.email.embed(new URL("http://bad.url"), "Bad URL");
fail("Should have thrown an exception");
}
catch (EmailException e)
{
- assertTrue(true);
+ // expected
}
+
+ // if we try to embed a different URL under a previously used name,
+ // does it complain?
+ try
+ {
+ this.email.embed(new URL("http://www.google.com"), "Test name");
+ fail("shouldn't be able to use an existing name with a different URL!");
+ }
+ catch (EmailException e)
+ {
+ // expected
+ }
}
/**
Modified: jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java?view=diff&rev=510708&r1=510707&r2=510708
==============================================================================
--- jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java (original)
+++ jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java Thu Feb 22 15:35:23 2007
@@ -18,6 +18,7 @@
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
@@ -75,7 +76,7 @@
/**
* @return inlineImages
*/
- public List getInlineImages()
+ public Map getInlineImages()
{
return inlineImages;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org
Re: [email] svn commit: r510708 - in /jakarta/commons/proper/email/trunk/src: java/org/apache/commons/mail/HtmlEmail.java test/org/apache/commons/mail/HtmlEmailTest.java test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java
Posted by Rahul Akolkar <ra...@gmail.com>.
On 2/22/07, dion@apache.org <di...@apache.org> wrote:
> Author: dion
> Date: Thu Feb 22 15:35:23 2007
> New Revision: 510708
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=510708
> Log:
> EMAIL-50 HTML Emails with images don't display in Outlook 2000
>
> Modified:
> jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java
> jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/HtmlEmailTest.java
> jakarta/commons/proper/email/trunk/src/test/org/apache/commons/mail/mocks/MockHtmlEmailConcrete.java
>
> Modified: jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java
> URL: http://svn.apache.org/viewvc/jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java?view=diff&rev=510708&r1=510707&r2=510708
> ==============================================================================
> --- jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java (original)
> +++ jakarta/commons/proper/email/trunk/src/java/org/apache/commons/mail/HtmlEmail.java Thu Feb 22 15:35:23 2007
> @@ -20,9 +20,9 @@
> import java.io.InputStream;
> import java.net.MalformedURLException;
> import java.net.URL;
> -import java.util.ArrayList;
> +import java.util.HashMap;
> import java.util.Iterator;
> -import java.util.List;
> +import java.util.Map;
>
> import javax.activation.DataHandler;
> import javax.activation.URLDataSource;
> @@ -69,8 +69,11 @@
> /** Html part of the message */
> protected String html;
>
> - /** Embedded images */
> - protected List inlineImages = new ArrayList();
> + /**
> + * Embedded images Map<String,InlineImages> where the key is the
> + * user-defined image name
> + */
> + protected Map inlineImages = new HashMap();
>
<snip/>
EMAIL-50 has a fix version of 1.1, could break subclasses?
-Rahul
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org