package railo.runtime.net.mail; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.activation.DataHandler; import javax.activation.URLDataSource; import javax.mail.BodyPart; import javax.mail.MessagingException; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMultipart; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.MultiPartEmail; import railo.commons.lang.StringUtil; /** * An HTML multipart email. * * <p>This class is used to send HTML formatted email. A text message * can also be set for HTML unaware email clients, such as text-based * email clients. * * <p>This class also inherits from MultiPartEmail, so it is easy to * add attachments to the email. * * <p>To send an email in HTML, one should create a HtmlEmail, then * use the setFrom, addTo, etc. methods. The HTML content can be set * with the setHtmlMsg method. The alternative text content can be set * with setTextMsg. * * <p>Either the text or HTML can be omitted, in which case the "main" * part of the multipart becomes whichever is supplied rather than a * multipart/alternative. * * */ public final class HtmlEmailImpl extends MultiPartEmail { /** Definition of the length of generated CID's */ public static final int CID_LENGTH = 10; /** * Text part of the message. This will be used as alternative text if * the email client does not support HTML messages. */ protected String text; /** Html part of the message */ protected String html; /** Embedded images */ protected List inlineImages = new ArrayList(); /** * Set the text content. * * @param aText A String. * @return An HtmlEmail. * @throws EmailException see javax.mail.internet.MimeBodyPart * for definitions * */ public HtmlEmailImpl setTextMsg(String aText) throws EmailException { if (StringUtil.isEmpty(aText)) { throw new EmailException("Invalid message supplied"); } this.text = aText; return this; } /** * Set the HTML content. * * @param aHtml A String. * @return An HtmlEmail. * @throws EmailException see javax.mail.internet.MimeBodyPart * for definitions * */ public HtmlEmailImpl setHtmlMsg(String aHtml) throws EmailException { if (StringUtil.isEmpty(aHtml)) { throw new EmailException("Invalid message supplied"); } this.html = aHtml; return this; } /** * Set the message. * * <p>This method overrides the MultiPartEmail setMsg() method in * order to send an HTML message instead of a full text message in * the mail body. The message is formatted in HTML for the HTML * part of the message, it is let as is in the alternate text * part. * * @param msg A String. * @return An Email. * @throws EmailException see javax.mail.internet.MimeBodyPart * for definitions * */ public Email setMsg(String msg) throws EmailException { if (StringUtil.isEmpty(msg)) { throw new EmailException("Invalid message supplied"); } setTextMsg(msg); setHtmlMsg( new StringBuffer() .append("<html><body><pre>") .append(msg) .append("</pre></body></html>") .toString()); return this; } /** * Embeds an URL in the HTML. * * <p>This method allows to embed a file located by an URL into * 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. * * <p>Example of use:<br><code><pre> * HtmlEmail he = new HtmlEmail(); * he.setHtmlMsg("<html><img src=cid:" + * embed("file:/my/image.gif","image.gif") + * "></html>"); * // code to set the others email fields (not shown) * </pre></code> * * @param url The URL of the file. * @param cid A String with the Content-ID of the file. * @param name The name that will be set in the filename header * field. * @throws EmailException when URL supplied is invalid * also see javax.mail.internet.MimeBodyPart for definitions * */ public void embed(URL url, String cid, String name) throws EmailException { // verify that the URL is valid try { InputStream is = url.openStream(); is.close(); } catch (IOException e) { throw new EmailException("Invalid URL"); } MimeBodyPart mbp = new MimeBodyPart(); try { mbp.setDataHandler(new DataHandler(new URLDataSource(url))); mbp.setFileName(name); mbp.setDisposition("inline"); mbp.addHeader("Content-ID", "<" + cid + ">"); this.inlineImages.add(mbp); } catch (MessagingException me) { throw new EmailException(me); } } /** * Does the work of actually building the email. * * @exception EmailException if there was an error. * */ public void buildMimeMessage() throws EmailException { 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(); } } catch (MessagingException me) { throw new EmailException(me); } super.buildMimeMessage(); } /** * @throws EmailException EmailException * @throws MessagingException MessagingException */ private void buildAttachments() throws MessagingException, EmailException { MimeMultipart container = this.getContainer(); MimeMultipart subContainer = null; MimeMultipart subContainerHTML = new MimeMultipart("related"); BodyPart msgHtml = null; BodyPart msgText = null; container.setSubType("mixed"); subContainer = new MimeMultipart("alternative"); if (!StringUtil.isEmpty(this.text)) { msgText = new MimeBodyPart(); subContainer.addBodyPart(msgText); if (!StringUtil.isEmpty(this.charset)) { msgText.setContent( this.text, Email.TEXT_PLAIN + "; charset=" + this.charset); } else { msgText.setContent(this.text, Email.TEXT_PLAIN); } } if (!StringUtil.isEmpty(this.html)) { if (this.inlineImages.size() > 0) { msgHtml = new MimeBodyPart(); subContainerHTML.addBodyPart(msgHtml); } else { msgHtml = new MimeBodyPart(); subContainer.addBodyPart(msgHtml); } if (!StringUtil.isEmpty(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()); } } // add sub containers to message this.addPart(subContainer, 0); if (this.inlineImages.size() > 0) { // add sub container to message this.addPart(subContainerHTML, 1); } } /** * @throws EmailException EmailException * @throws MessagingException MessagingException */ private void buildNoAttachments() throws MessagingException, EmailException { MimeMultipart container = this.getContainer(); MimeMultipart subContainerHTML = new MimeMultipart("related"); container.setSubType("alternative"); BodyPart msgText = null; BodyPart msgHtml = null; if(!StringUtil.isEmpty(this.text)) { msgText = this.getPrimaryBodyPart(); if (!StringUtil.isEmpty(this.charset)) { msgText.setContent( this.text, Email.TEXT_PLAIN + "; charset=" + this.charset); } else { msgText.setContent(this.text, Email.TEXT_PLAIN); } } if(!StringUtil.isEmpty(this.html)) { // 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(!StringUtil.isEmpty(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); } } } }