001: /*
002: * Copyright 2001-2005 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.mail;
017:
018: import java.io.IOException;
019: import java.io.InputStream;
020: import java.net.URL;
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import javax.activation.DataHandler;
026: import javax.activation.URLDataSource;
027: import javax.mail.BodyPart;
028: import javax.mail.MessagingException;
029: import javax.mail.internet.MimeBodyPart;
030: import javax.mail.internet.MimeMultipart;
031:
032: /**
033: * An HTML multipart email.
034: *
035: * <p>This class is used to send HTML formatted email. A text message
036: * can also be set for HTML unaware email clients, such as text-based
037: * email clients.
038: *
039: * <p>This class also inherits from MultiPartEmail, so it is easy to
040: * add attachments to the email.
041: *
042: * <p>To send an email in HTML, one should create a HtmlEmail, then
043: * use the setFrom, addTo, etc. methods. The HTML content can be set
044: * with the setHtmlMsg method. The alternative text content can be set
045: * with setTextMsg.
046: *
047: * <p>Either the text or HTML can be omitted, in which case the "main"
048: * part of the multipart becomes whichever is supplied rather than a
049: * multipart/alternative.
050: *
051: * @since 1.0
052: * @author <a href="mailto:unknown">Regis Koenig</a>
053: * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
054: * @version $Id: HtmlEmail.java 279285 2005-09-07 09:52:44Z henning $
055: */
056: public class HtmlEmail extends MultiPartEmail {
057: /** Definition of the length of generated CID's */
058: public static final int CID_LENGTH = 10;
059:
060: /**
061: * Text part of the message. This will be used as alternative text if
062: * the email client does not support HTML messages.
063: */
064: protected String text;
065:
066: /** Html part of the message */
067: protected String html;
068:
069: /** Embedded images */
070: protected List inlineImages = new ArrayList();
071:
072: /**
073: * Set the text content.
074: *
075: * @param aText A String.
076: * @return An HtmlEmail.
077: * @throws EmailException see javax.mail.internet.MimeBodyPart
078: * for definitions
079: * @since 1.0
080: */
081: public HtmlEmail setTextMsg(String aText) throws EmailException {
082: if (EmailUtils.isEmpty(aText)) {
083: throw new EmailException("Invalid message supplied");
084: }
085:
086: this .text = aText;
087: return this ;
088: }
089:
090: /**
091: * Set the HTML content.
092: *
093: * @param aHtml A String.
094: * @return An HtmlEmail.
095: * @throws EmailException see javax.mail.internet.MimeBodyPart
096: * for definitions
097: * @since 1.0
098: */
099: public HtmlEmail setHtmlMsg(String aHtml) throws EmailException {
100: if (EmailUtils.isEmpty(aHtml)) {
101: throw new EmailException("Invalid message supplied");
102: }
103:
104: this .html = aHtml;
105: return this ;
106: }
107:
108: /**
109: * Set the message.
110: *
111: * <p>This method overrides the MultiPartEmail setMsg() method in
112: * order to send an HTML message instead of a full text message in
113: * the mail body. The message is formatted in HTML for the HTML
114: * part of the message, it is let as is in the alternate text
115: * part.
116: *
117: * @param msg A String.
118: * @return An Email.
119: * @throws EmailException see javax.mail.internet.MimeBodyPart
120: * for definitions
121: * @since 1.0
122: */
123: public Email setMsg(String msg) throws EmailException {
124: if (EmailUtils.isEmpty(msg)) {
125: throw new EmailException("Invalid message supplied");
126: }
127:
128: setTextMsg(msg);
129:
130: setHtmlMsg(new StringBuffer().append("<html><body><pre>")
131: .append(msg).append("</pre></body></html>").toString());
132:
133: return this ;
134: }
135:
136: /**
137: * Embeds an URL in the HTML.
138: *
139: * <p>This method allows to embed a file located by an URL into
140: * the mail body. It allows, for instance, to add inline images
141: * to the email. Inline files may be referenced with a
142: * <code>cid:xxxxxx</code> URL, where xxxxxx is the Content-ID
143: * returned by the embed function.
144: *
145: * <p>Example of use:<br><code><pre>
146: * HtmlEmail he = new HtmlEmail();
147: * he.setHtmlMsg("<html><img src=cid:" +
148: * embed("file:/my/image.gif","image.gif") +
149: * "></html>");
150: * // code to set the others email fields (not shown)
151: * </pre></code>
152: *
153: * @param url The URL of the file.
154: * @param name The name that will be set in the filename header
155: * field.
156: * @return A String with the Content-ID of the file.
157: * @throws EmailException when URL supplied is invalid
158: * also see javax.mail.internet.MimeBodyPart for definitions
159: * @since 1.0
160: */
161: public String embed(URL url, String name) throws EmailException {
162: // verify that the URL is valid
163: try {
164: InputStream is = url.openStream();
165: is.close();
166: } catch (IOException e) {
167: throw new EmailException("Invalid URL");
168: }
169:
170: MimeBodyPart mbp = new MimeBodyPart();
171:
172: try {
173: mbp.setDataHandler(new DataHandler(new URLDataSource(url)));
174: mbp.setFileName(name);
175: mbp.setDisposition("inline");
176: String cid = EmailUtils.randomAlphabetic(
177: HtmlEmail.CID_LENGTH).toLowerCase();
178: mbp.addHeader("Content-ID", "<" + cid + ">");
179: this .inlineImages.add(mbp);
180: return cid;
181: } catch (MessagingException me) {
182: throw new EmailException(me);
183: }
184: }
185:
186: /**
187: * Does the work of actually building the email.
188: *
189: * @exception EmailException if there was an error.
190: * @since 1.0
191: */
192: public void buildMimeMessage() throws EmailException {
193: try {
194: // if the email has attachments then the base type is mixed,
195: // otherwise it should be related
196: if (this .isBoolHasAttachments()) {
197: this .buildAttachments();
198: } else {
199: this .buildNoAttachments();
200: }
201:
202: } catch (MessagingException me) {
203: throw new EmailException(me);
204: }
205: super .buildMimeMessage();
206: }
207:
208: /**
209: * @throws EmailException EmailException
210: * @throws MessagingException MessagingException
211: */
212: private void buildAttachments() throws MessagingException,
213: EmailException {
214: MimeMultipart container = this .getContainer();
215: MimeMultipart subContainer = null;
216: MimeMultipart subContainerHTML = new MimeMultipart("related");
217: BodyPart msgHtml = null;
218: BodyPart msgText = null;
219:
220: container.setSubType("mixed");
221: subContainer = new MimeMultipart("alternative");
222:
223: if (EmailUtils.isNotEmpty(this .text)) {
224: msgText = new MimeBodyPart();
225: subContainer.addBodyPart(msgText);
226:
227: if (EmailUtils.isNotEmpty(this .charset)) {
228: msgText.setContent(this .text, Email.TEXT_PLAIN
229: + "; charset=" + this .charset);
230: } else {
231: msgText.setContent(this .text, Email.TEXT_PLAIN);
232: }
233: }
234:
235: if (EmailUtils.isNotEmpty(this .html)) {
236: if (this .inlineImages.size() > 0) {
237: msgHtml = new MimeBodyPart();
238: subContainerHTML.addBodyPart(msgHtml);
239: } else {
240: msgHtml = new MimeBodyPart();
241: subContainer.addBodyPart(msgHtml);
242: }
243:
244: if (EmailUtils.isNotEmpty(this .charset)) {
245: msgHtml.setContent(this .html, Email.TEXT_HTML
246: + "; charset=" + this .charset);
247: } else {
248: msgHtml.setContent(this .html, Email.TEXT_HTML);
249: }
250:
251: Iterator iter = this .inlineImages.iterator();
252: while (iter.hasNext()) {
253: subContainerHTML.addBodyPart((BodyPart) iter.next());
254: }
255: }
256:
257: // add sub containers to message
258: this .addPart(subContainer, 0);
259:
260: if (this .inlineImages.size() > 0) {
261: // add sub container to message
262: this .addPart(subContainerHTML, 1);
263: }
264: }
265:
266: /**
267: * @throws EmailException EmailException
268: * @throws MessagingException MessagingException
269: */
270: private void buildNoAttachments() throws MessagingException,
271: EmailException {
272: MimeMultipart container = this .getContainer();
273: MimeMultipart subContainerHTML = new MimeMultipart("related");
274:
275: container.setSubType("alternative");
276:
277: BodyPart msgText = null;
278: BodyPart msgHtml = null;
279:
280: if (EmailUtils.isNotEmpty(this .text)) {
281: msgText = this .getPrimaryBodyPart();
282: if (EmailUtils.isNotEmpty(this .charset)) {
283: msgText.setContent(this .text, Email.TEXT_PLAIN
284: + "; charset=" + this .charset);
285: } else {
286: msgText.setContent(this .text, Email.TEXT_PLAIN);
287: }
288: }
289:
290: if (EmailUtils.isNotEmpty(this .html)) {
291: // if the txt part of the message was null, then the html part
292: // will become the primary body part
293: if (msgText == null) {
294: msgHtml = getPrimaryBodyPart();
295: } else {
296: if (this .inlineImages.size() > 0) {
297: msgHtml = new MimeBodyPart();
298: subContainerHTML.addBodyPart(msgHtml);
299: } else {
300: msgHtml = new MimeBodyPart();
301: container.addBodyPart(msgHtml, 1);
302: }
303: }
304:
305: if (EmailUtils.isNotEmpty(this .charset)) {
306: msgHtml.setContent(this .html, Email.TEXT_HTML
307: + "; charset=" + this .charset);
308: } else {
309: msgHtml.setContent(this .html, Email.TEXT_HTML);
310: }
311:
312: Iterator iter = this .inlineImages.iterator();
313: while (iter.hasNext()) {
314: subContainerHTML.addBodyPart((BodyPart) iter.next());
315: }
316:
317: if (this .inlineImages.size() > 0) {
318: // add sub container to message
319: this.addPart(subContainerHTML);
320: }
321: }
322: }
323: }
|