001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.mail.transformation;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Properties;
026: import java.util.StringTokenizer;
027:
028: import javax.activation.DataHandler;
029: import javax.activation.DataSource;
030: import javax.mail.Address;
031: import javax.mail.BodyPart;
032: import javax.mail.Message;
033: import javax.mail.Multipart;
034: import javax.mail.SendFailedException;
035: import javax.mail.Session;
036: import javax.mail.Transport;
037: import javax.mail.internet.InternetAddress;
038: import javax.mail.internet.MimeBodyPart;
039: import javax.mail.internet.MimeMessage;
040: import javax.mail.internet.MimeMultipart;
041: import javax.xml.transform.OutputKeys;
042:
043: import org.apache.avalon.framework.configuration.Configuration;
044: import org.apache.avalon.framework.configuration.ConfigurationException;
045: import org.apache.avalon.framework.parameters.Parameters;
046: import org.apache.cocoon.ProcessingException;
047: import org.apache.cocoon.environment.SourceResolver;
048: import org.apache.cocoon.mail.datasource.SourceDataSource;
049: import org.apache.cocoon.transformation.AbstractSAXTransformer;
050: import org.apache.excalibur.source.Source;
051: import org.xml.sax.Attributes;
052: import org.xml.sax.SAXException;
053: import org.xml.sax.helpers.AttributesImpl;
054:
055: /**
056: * The SendMailTransformer send mails with optional attachments using a SMTP
057: * server and delivers furthermore a status report of each sent mail.
058: *
059: * <p>
060: * The SendMailTransformer requires the Sun's JavaMail API implementation. Please
061: * download and copy the following files to the Cocoon lib directory:
062: * <ul>
063: * <li><code>mail.jar</code> from
064: * <a href="http://java.sun.com/products/javamail/">http://java.sun.com/products/javamail/</a>
065: * </li>
066: * <li><code>activation.jar</code> from
067: * <a href="http://java.sun.com/products/javabeans/glasgow/jaf.html">http://java.sun.com/products/javabeans/glasgow/jaf.html</a>
068: * </li>
069: * </p>
070: *
071: * <p>
072: * Use the following sitemap component declaration to define, configure and
073: * parameterize the transformer.
074: * in the <code>map:sitemap/map:components/map:transformers</code>:
075:
076: * <pre>
077: * <map:transformer name="sendmail" src="org.apache.cocoon.mail.transformation.SendMailTransformer">
078: * <smtphost>smtp.foo.com</smtphost>
079: * <from>sender@localhost</from>
080: * </map:transformer>
081: * </pre>
082: *
083: * where
084: * <ul>
085: * <li>
086: * <smtphost> is the SMTP server host name, e.g. smtp.foo.com
087: * </li>
088: * <li>
089: * <from> is the sender e-mail address
090: * </li>
091: * </ul>
092: * </p>
093: *
094: * <p>
095: * Furthermore, these parameters can be defined in the sitemap pipeline section:
096: * <ul>
097: * <li>
098: * <b>smtphost</b>, <b>from</b> - If they are defined, this values overwrite
099: * the values from component section described above.
100: * </li>
101: * <li>
102: * <b>to</b> - email addresses of recipients
103: * e.g.: <code><map:parameter name="to" value="customer1@target.com,customer2@target.com"/></code>
104: * </li>
105: * <li>
106: * <b>subject</b> - a string, can also come from an input module
107: * e.g.; <map:parameter name="subject" value="{request-param:subject}"/>
108: * </li>
109: * <li>
110: * <b>body</b> - a string, can also come from an input module
111: * e.g.; <map:parameter name="body" value="{request-param:body}"/>
112: * </li>
113: * <li>
114: * <b>sendpartial</b> - a boolean, define how to send the mails. When mail is being send
115: * to more than one recipient and the parameter is set to false, then all email addresses
116: * will appear concatenated in the address field at the mail client of the recipient.
117: * The default is true.
118: * </li>
119: * </ul>
120: * </p>
121: *
122: * <p>
123: * More configurations can be made in a specific configuration file, which
124: * can be retrieved with a
125: * <a href="http://cocoon.apache.org/2.1/userdocs/generators/generators.html">generator</a> as
126: * the input document. The input document should have the following configuration entities:
127: * <ul>
128: * <li>
129: * <b><email:smtphost></b>, <b><email:from></b> and
130: * <b><email:subject></b> can be set to overwrite values from the
131: * sitemap
132: * </li>
133: * <li>
134: * <b><email:to></b> - each entry will be append to the list of
135: * email addresses
136: * </li>
137: * <li>
138: * <b><email:body></b> - Overwrites the value from the sitemap.
139: * If there is a <b>src</b> attribute, the transformer will try to retrieve
140: * the file and place it instead of a text-string as the mail body.
141: * </li>
142: * <li>
143: * <b><email:attachment></b> - each entry defines a attachment.
144: * The attribute <b>name</b> defines the name of the attachment. The <b>mime-type</b> attribute
145: * defines the content of the attachment.
146: * If there is a nested <email:content> - element, text can be included and the
147: * attachment will then be a plain text-file.
148: * Is there a <b>url</b> attribute, the transformer tries to retrieve the
149: * appropriate file and handle it as an attachment.
150: * To use a file as an attachment, retrieved over a protocol like http or
151: * cocoon, use the <b>src</b> attribute.
152: * </li>
153: * </ul>
154: * </p>
155: *
156: * <p>
157: * Input document sample:
158: * <pre>
159: * <?xml version="1.0" encoding="UTF-8"?>
160: * <document xmlns:email="http://apache.org/cocoon/transformation/sendmail">
161: * <email:sendmail>
162: * <email:smtphost>hostname.company.com</email:smtphost>
163: * <email:from>info@company.com</email:from>
164: * <email:to>customer3@target.com</email:to>
165: * <email:to>customer4@target.com</email:to>
166: * <email:to>customer5@target.com</email:to>
167: * <email:to>customer6@target.com</email:to>
168: * <email:subject>subject-content</email:subject>
169: * <email:body src="cocoon:/softwareupdate.html?locale=en&country=UK"/>
170: * <!-- <email:body>some Text</email:body> -->
171: * <email:attachment name="hello.html" mime-type="text/html">
172: * <email:content>
173: * Dear Customer, please visit out new Product-Shop.
174: * </email:content>
175: * </email:attachment>
176: * <email:attachment name="hello2.html" mime-type="text/html" src="cocoon:/src1"/>
177: * <email:attachment name="hello3.html" mime-type="text/html"
178: * url="C:\path\softwareupdate.html"/>
179: * <email:attachment name="hello.gif" mime-type="image/gif"
180: * url="c:\path\powered.gif"/>
181: * </email:sendmail>
182: * </document>
183: * </pre>
184: * </p>
185: *
186: * <p>
187: * After the transformation a report will be generated, where the state for each sent mail can be seen.
188: * In case of an exception, the exception-message and a stacktrace will be reported.
189: * </p>
190: *
191: * <p>
192: * <b style="color: red;">FIXME: Known Issues:</b>
193: * <ul>
194: * <li>Refactor to use MailSender component</li>
195: * <li>No support for <a href="http://www.ietf.org/rfc/rfc2554.txt">RFC 2554:
196: * SMTP Service Extension for Authentication</a></li>
197: * <li>No support for different mail servers, first one will always be used</li>
198: * </ul>
199: * </p>
200: *
201: * @author <a href="mailto:pklassen@s-und-n.de">Peter Klassen</a>
202: * @version $Id: SendMailTransformer.java 525980 2007-04-05 22:18:04Z hepabolu $
203: */
204: public class SendMailTransformer extends AbstractSAXTransformer {
205:
206: /*
207: * constants, related to elements in configuration-file
208: */
209: public static final String NAMESPACE = "http://apache.org/cocoon/transformation/sendmail";
210: public static final String ELEMENT_SENDMAIL = "sendmail";
211: public static final String ELEMENT_SMTPHOST = "smtphost";
212: public static final String ELEMENT_SMTPPORT = "smtpport";
213: public static final String ELEMENT_MAILFROM = "from";
214: public static final String ELEMENT_MAILTO = "to";
215: public static final String ELEMENT_REPLYTO = "reply-to";
216: public static final String ELEMENT_MAILSUBJECT = "subject";
217: public static final String ELEMENT_MAILBODY = "body";
218: public static final String ELEMENT_ATTACHMENT = "attachment";
219: public static final String ELEMENT_ATTACHMENT_CONTENT = "content";
220: public static final String ELEMENT_EMAIL_PREFIX = "email";
221: public static final String ELEMENT_ERROR = "error";
222: public static final String ELEMENT_SUCCESS = "success";
223: public static final String ELEMENT_FAILURE = "failure";
224: public static final String ELEMENT_RESULT = "result";
225:
226: public static final String DEFAULT_BODY_MIMETYPE = "text/html";
227:
228: /*
229: * mode-constants
230: */
231: protected static final int MODE_NONE = 0;
232: protected static final int MODE_SMTPHOST = 1;
233: protected static final int MODE_FROM = 2;
234: protected static final int MODE_TO = 3;
235: protected static final int MODE_SUBJECT = 4;
236: protected static final int MODE_BODY = 5;
237: protected static final int MODE_ATTACHMENT = 6;
238: protected static final int MODE_ATTACHMENT_CONTENT = 7;
239: protected static final int MODE_REPLY_TO = 8;
240: protected static final int MODE_SMTPPORT = 9;
241:
242: /*
243: * constants, related to parameter from request
244: */
245: public final static String PARAM_SMTPHOST = "smtphost";
246: public final static String PARAM_SMTPPORT = "smtpport";
247: public final static String PARAM_FROM = "from";
248: public final static String PARAM_TO = "to";
249: public final static String PARAM_REPLY_TO = "reply-to";
250: public final static String PARAM_SUBJECT = "subject";
251: public final static String PARAM_BODY = "body";
252: public final static String PARAM_SENDPARTIAL = "sendpartial";
253: protected int mode;
254:
255: /*
256: * communication parameters, which will be used to send mails
257: */
258: protected List toAddresses;
259: protected List replyToAddresses;
260: protected List defaultToAddresses;
261: protected List defaultReplyToAddresses;
262: protected List attachments;
263: protected String subject;
264: protected String body;
265: protected String bodyURI;
266: protected String bodyMimeType;
267: protected String mailHost;
268: protected int mailPort;
269: protected String fromAddress;
270: protected AttachmentDescriptor attachmentDescriptor;
271: protected int port;
272: protected String contextPath;
273: protected boolean sendPartial;
274: protected Message smtpMessage;
275:
276: protected String defaultSmtpHost;
277: protected int defaultSmtpPort;
278: protected String defaultFromAddress;
279:
280: protected List usedSources = new ArrayList();
281:
282: /**
283: * create a new Transformer
284: */
285: public SendMailTransformer() {
286: this .defaultNamespaceURI = NAMESPACE;
287: }
288:
289: /* (non-Javadoc)
290: * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
291: */
292: public void configure(Configuration configuration)
293: throws ConfigurationException {
294: super .configure(configuration);
295: this .defaultSmtpHost = configuration.getChild("smtphost")
296: .getValue("");
297: this .defaultSmtpPort = configuration.getChild("smtpport")
298: .getValueAsInteger(25);
299: this .defaultFromAddress = configuration.getChild("from")
300: .getValue("");
301: }
302:
303: /**
304: * invoked every time when the transformer is triggered by the pipeline
305: */
306: public void setup(SourceResolver resolver, Map objectModel,
307: String src, Parameters par) throws ProcessingException,
308: SAXException, IOException {
309: super .setup(resolver, objectModel, src, par);
310:
311: this .mailHost = par.getParameter(PARAM_SMTPHOST,
312: this .defaultSmtpHost);
313: this .mailPort = par.getParameterAsInteger(PARAM_SMTPPORT,
314: this .defaultSmtpPort);
315: this .fromAddress = par.getParameter(PARAM_FROM,
316: this .defaultFromAddress);
317: this .port = this .request.getServerPort();
318: this .contextPath = this .request.getContextPath();
319: this .sendPartial = par.getParameterAsBoolean(PARAM_SENDPARTIAL,
320: true);
321:
322: if (getLogger().isDebugEnabled()) {
323: getLogger().debug(
324: "Using host " + mailHost + " on port " + mailPort
325: + ", from address " + fromAddress);
326: }
327:
328: this .attachments = new ArrayList();
329: this .defaultToAddresses = new ArrayList();
330: appendToAddress(this .defaultToAddresses, par.getParameter(
331: PARAM_TO, ""));
332: this .defaultReplyToAddresses = new ArrayList();
333: appendToAddress(this .defaultReplyToAddresses, par.getParameter(
334: PARAM_REPLY_TO, ""));
335:
336: this .subject = par.getParameter(PARAM_SUBJECT, null);
337: this .body = par.getParameter(PARAM_BODY, null);
338: }
339:
340: /* (non-Javadoc)
341: * @see org.apache.cocoon.transformation.AbstractSAXTransformer#startTransformingElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
342: */
343: public void startTransformingElement(String uri, String name,
344: String raw, Attributes attr) throws SAXException {
345: if (name.equals(ELEMENT_SENDMAIL)) {
346: // Clean from possible previous usage
347: this .toAddresses = new ArrayList(this .defaultToAddresses);
348: this .replyToAddresses = new ArrayList(
349: this .defaultReplyToAddresses);
350: this .attachments.clear();
351: } else if (name.equals(ELEMENT_SMTPHOST)) {
352: startTextRecording();
353: this .mode = MODE_SMTPHOST;
354: } else if (name.equals(ELEMENT_SMTPPORT)) {
355: this .startTextRecording();
356: this .mode = MODE_SMTPPORT;
357: } else if (name.equals(ELEMENT_MAILFROM)) {
358: startTextRecording();
359: this .mode = MODE_FROM;
360: } else if (name.equals(ELEMENT_MAILTO)) {
361: startTextRecording();
362: this .mode = MODE_TO;
363: } else if (name.equals(ELEMENT_REPLYTO)) {
364: startTextRecording();
365: this .mode = MODE_REPLY_TO;
366: } else if (name.equals(ELEMENT_MAILSUBJECT)) {
367: startTextRecording();
368: this .mode = MODE_SUBJECT;
369: } else if (name.equals(ELEMENT_MAILBODY)) {
370: String strBody = attr.getValue("src");
371: if (strBody != null) {
372: this .bodyURI = strBody;
373: }
374:
375: String mType = attr.getValue("mime-type");
376: if (mType != null) {
377: this .bodyMimeType = mType;
378: } else {
379: this .bodyMimeType = DEFAULT_BODY_MIMETYPE;
380: }
381:
382: Properties outputProperties = new Properties();
383: if (this .bodyMimeType.equals("text/plain"))
384: outputProperties.put(OutputKeys.METHOD, "text");
385: else if (this .bodyMimeType.equals("text/html"))
386: outputProperties.put(OutputKeys.METHOD, "html");
387: startSerializedXMLRecording(outputProperties);
388: this .mode = MODE_BODY;
389: } else if (name.equals(ELEMENT_ATTACHMENT)) {
390: this .attachmentDescriptor = new AttachmentDescriptor(attr
391: .getValue("name"), attr.getValue("mime-type"), attr
392: .getValue("src"), attr.getValue("url"));
393: this .mode = MODE_ATTACHMENT;
394: } else if (name.equals(ELEMENT_ATTACHMENT_CONTENT)) {
395: startSerializedXMLRecording(new Properties());
396: this .mode = MODE_ATTACHMENT_CONTENT;
397: } else {
398: throw new SAXException("Unknown element <" + name + ">");
399: }
400: }
401:
402: /* (non-Javadoc)
403: * @see org.apache.cocoon.transformation.AbstractSAXTransformer#endTransformingElement(java.lang.String, java.lang.String, java.lang.String)
404: */
405: public void endTransformingElement(String uri, String name,
406: String raw) throws SAXException, ProcessingException {
407: if (name.equals(ELEMENT_SENDMAIL)) {
408: if (getLogger().isInfoEnabled()) {
409: getLogger().info(
410: "Mail Subject: " + this .subject + "\n"
411: + "Body: " + this .body);
412: }
413: sendMail();
414: } else if (name.equals(ELEMENT_SMTPHOST)) {
415: this .mailHost = endTextRecording();
416: this .mode = MODE_NONE;
417: } else if (name.equals(ELEMENT_SMTPPORT)) {
418: this .mailPort = Integer.parseInt(this .endTextRecording());
419: this .mode = MODE_NONE;
420: } else if (name.equals(ELEMENT_MAILFROM)) {
421: this .fromAddress = endTextRecording();
422: this .mode = MODE_NONE;
423: } else if (name.equals(ELEMENT_MAILTO)) {
424: this .toAddresses.add(endTextRecording());
425: this .mode = MODE_NONE;
426: } else if (name.equals(ELEMENT_REPLYTO)) {
427: this .replyToAddresses.add(endTextRecording());
428: this .mode = MODE_NONE;
429: } else if (name.equals(ELEMENT_MAILSUBJECT)) {
430: String strSubject = endTextRecording();
431: if (strSubject != null) {
432: this .subject = strSubject;
433: } else {
434: getLogger().debug("Mail: No Subject");
435: }
436: this .mode = MODE_NONE;
437: } else if (name.equals(ELEMENT_ATTACHMENT)) {
438: this .attachments.add(this .attachmentDescriptor.copy());
439: this .attachmentDescriptor = null;
440: this .mode = MODE_NONE;
441: } else if (name.equals(ELEMENT_ATTACHMENT_CONTENT)) {
442: this .attachmentDescriptor
443: .setContent(endSerializedXMLRecording());
444: this .mode = MODE_NONE;
445: } else if (name.equals(ELEMENT_MAILBODY)) {
446: String strB = null;
447: try {
448: strB = endSerializedXMLRecording();
449: } catch (Exception e) {
450: if (getLogger().isDebugEnabled()) {
451: getLogger()
452: .debug(
453: "Mail: No Body as String in config-file available");
454: }
455: }
456: if (strB != null) {
457: this .body = strB;
458: }
459: this .mode = MODE_NONE;
460: } else {
461: throw new SAXException("Unknown element <" + name + ">");
462: }
463: }
464:
465: private static void appendToAddress(List addresses, String s) {
466: StringTokenizer t = new StringTokenizer(s.trim(), ";");
467: while (t.hasMoreElements()) {
468: addresses.add(t.nextToken());
469: }
470: }
471:
472: /**
473: *
474: */
475: private void sendMail() throws SAXException {
476: try {
477: this .ignoreHooksCount++;
478: super .sendStartElementEventNS(ELEMENT_RESULT);
479: Properties props = new Properties();
480: props.put("mail.smtp.host", this .mailHost);
481: props.put("mail.smtp.port", String.valueOf(this .mailPort));
482:
483: if (this .subject == null) {
484: this .ignoreHooksCount++;
485: super .sendStartElementEventNS(ELEMENT_ERROR);
486: super
487: .sendTextEvent("Subject not available - sending mail aborted");
488: super .sendEndElementEventNS(ELEMENT_ERROR);
489: this .ignoreHooksCount--;
490: return;
491: }
492:
493: if (this .body == null && this .bodyURI == null) {
494: this .ignoreHooksCount++;
495: super .sendStartElementEventNS(ELEMENT_ERROR);
496: super
497: .sendTextEvent("Mailbody not available - sending mail aborted");
498: super .sendEndElementEventNS(ELEMENT_ERROR);
499: this .ignoreHooksCount--;
500: return;
501: }
502:
503: Session session = Session.getDefaultInstance(props, null);
504: Transport trans = session.getTransport("smtp");
505: trans.connect();
506:
507: this .smtpMessage = setUpMessage(session);
508:
509: if (this .sendPartial) {
510: for (int i = 0; i < this .toAddresses.size(); i++) {
511: List v = new ArrayList(1);
512: v.add(this .toAddresses.get(i));
513: sendMail(v, trans);
514: }
515: } else {
516: sendMail(this .toAddresses, trans);
517: }
518:
519: trans.close();
520: } catch (SAXException e) {
521: throw e;
522: } catch (Exception e) {
523: getLogger().error("Exception sending mail", e);
524: sendExceptionElement(e);
525: } finally {
526: super .sendEndElementEventNS(ELEMENT_RESULT);
527: this .ignoreHooksCount--;
528: }
529: }
530:
531: /**
532: * @see <a href="http://java.sun.com/products/javamail/1.3/docs/javadocs/com/sun/mail/smtp/package-summary.html">Sun Javamail Javadoc</a>
533: * @throws Exception
534: */
535: private void sendMail(List newAddresses, Transport trans)
536: throws Exception {
537: AddressHandler[] iA = new AddressHandler[newAddresses.size()];
538:
539: try {
540: for (int i = 0; i < newAddresses.size(); i++) {
541: InternetAddress inA = new InternetAddress(
542: (String) newAddresses.get(i));
543: iA[i] = new AddressHandler(inA);
544: }
545: InternetAddress[] iaArr = SendMailTransformer
546: .getAddresses(iA);
547: this .smtpMessage.setRecipients(Message.RecipientType.TO,
548: iaArr);
549: trans.sendMessage(this .smtpMessage, iaArr);
550: } catch (SendFailedException e) {
551: getLogger().error("Exception during sending of mail", e);
552:
553: Address[] adr = e.getInvalidAddresses();
554: for (int isfEx = 0; isfEx < iA.length; isfEx++) {
555: String tmpAddress = iA[isfEx].getAddress().getAddress();
556: for (int sei = 0; sei < adr.length; sei++) {
557: if (((InternetAddress) adr[sei]).getAddress()
558: .equalsIgnoreCase(tmpAddress)) {
559: iA[isfEx].setSendMailResult("Invalid address");
560: }
561: }
562: }
563:
564: Address[] ad = e.getValidUnsentAddresses();
565: for (int isfEx = 0; isfEx < iA.length; isfEx++) {
566: String tmpAddress = iA[isfEx].getAddress().getAddress();
567: for (int sei = 0; sei < ad.length; sei++) {
568: if (((InternetAddress) ad[sei]).getAddress()
569: .equalsIgnoreCase(tmpAddress)) {
570: iA[isfEx]
571: .setSendMailResult("Recipient not found");
572: }
573: }
574: }
575: } catch (Exception e) {
576: getLogger().error("Exception sending mail", e);
577: sendExceptionElement(e);
578: return;
579: }
580:
581: generateSAXReportStatements(iA);
582: }
583:
584: private Message setUpMessage(Session session) throws Exception {
585: Message sm = new MimeMessage(session);
586:
587: //sm.setAllow8bitMIME(true);
588: Address[] replyTo = new Address[this .replyToAddresses.size()];
589: for (int i = 0; i < this .replyToAddresses.size(); i++) {
590: replyTo[i] = new InternetAddress(
591: (String) this .replyToAddresses.get(i));
592: }
593: sm.setReplyTo(replyTo);
594: sm.setFrom(new InternetAddress(this .fromAddress));
595: sm.setSubject(this .subject);
596:
597: // process mail-body
598: BodyPart messageBodyPart = new MimeBodyPart();
599:
600: // decide, if to take content from source or plain text
601: // from variable to build mailbody
602: if (this .bodyURI != null) {
603: Source inSrc = resolver.resolveURI(this .bodyURI);
604: this .usedSources.add(inSrc);
605: InputStream inStr = inSrc.getInputStream();
606: byte[] byteArr = new byte[inStr.available()];
607: inStr.read(byteArr);
608:
609: String mailBody = new String(byteArr);
610: messageBodyPart.setContent(mailBody, this .bodyMimeType);
611: } else {
612: messageBodyPart.setContent(this .body, this .bodyMimeType);
613: }
614:
615: Multipart multipart = new MimeMultipart();
616: multipart.addBodyPart(messageBodyPart);
617:
618: // process attachments
619: Iterator i = this .attachments.iterator();
620: while (i.hasNext()) {
621: AttachmentDescriptor aD = (AttachmentDescriptor) i.next();
622: messageBodyPart = new MimeBodyPart();
623:
624: if (!aD.isTextContent()) {
625: Source inputSource = resolver
626: .resolveURI(aD.isURLSource() ? aD.strAttrSrc
627: : aD.strAttrFile);
628: this .usedSources.add(inputSource);
629:
630: DataSource dataSource = new SourceDataSource(
631: inputSource, aD.strAttrMimeType, aD.strAttrName);
632: ((SourceDataSource) dataSource)
633: .enableLogging(getLogger());
634:
635: messageBodyPart.setDataHandler(new DataHandler(
636: dataSource));
637: } else {
638: messageBodyPart.setContent(aD.strContent,
639: aD.strAttrMimeType);
640: }
641:
642: messageBodyPart.setFileName(aD.strAttrName);
643: multipart.addBodyPart(messageBodyPart);
644: }
645:
646: sm.setContent(multipart);
647:
648: //sm.setReturnOption(SMTPMessage.RETURN_FULL);
649: sm.saveChanges();
650:
651: return sm;
652: }
653:
654: private void generateSAXReportStatements(AddressHandler[] addressArr)
655: throws SAXException {
656: AttributesImpl impl = new AttributesImpl();
657:
658: for (int i = 0; i < addressArr.length; i++) {
659: String tmpAddress = addressArr[i].getAddress().getAddress();
660:
661: if (addressArr[i].getSendMailResult() == null) {
662: impl.addAttribute("", "to", "to", "CDATA", tmpAddress);
663: super .sendStartElementEventNS(ELEMENT_SUCCESS, impl);
664: super .sendTextEvent("Mail sent");
665: super .sendEndElementEventNS(ELEMENT_SUCCESS);
666: } else {
667: impl.addAttribute("", "to", "to", "CDATA", tmpAddress);
668: super .sendStartElementEventNS(ELEMENT_FAILURE, impl);
669: super .sendTextEvent(addressArr[i].getSendMailResult());
670: super .sendEndElementEventNS(ELEMENT_FAILURE);
671: }
672: }
673: }
674:
675: private void sendExceptionElement(Exception ex) {
676: try {
677: this .ignoreHooksCount++;
678: super .sendStartElementEventNS("exception");
679: super .sendStartElementEventNS("message");
680: super .sendTextEvent(ex.getMessage());
681: super .sendEndElementEventNS("message");
682:
683: /* only with jdk 1.4
684: super.sendStartElementEvent("email:stacktrace");
685:
686: for (int i = 0; i < ex.getStackTrace().length; i++) {
687: String s = ((StackTraceElement) ex.getStackTrace()[i]).toString();
688: super.sendTextEvent(s + "\n");
689: }
690:
691: super.sendEndElementEvent("email:stacktrace");*/
692:
693: super .sendEndElementEventNS("exception");
694: this .ignoreHooksCount--;
695: } catch (SAXException e) {
696: getLogger().error("Error while sending a SAX-Event", e);
697: }
698: }
699:
700: public static InternetAddress[] getAddresses(
701: AddressHandler[] handlerArr) {
702: InternetAddress[] iaArr = new InternetAddress[handlerArr.length];
703:
704: for (int i = 0; i < handlerArr.length; i++) {
705: iaArr[i] = handlerArr[i].getAddress();
706: }
707:
708: return iaArr;
709: }
710:
711: /**
712: * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
713: */
714: public void recycle() {
715: this .toAddresses = null;
716: this .defaultToAddresses = null;
717: this .attachments = null;
718: this .subject = null;
719: this .body = null;
720: this .bodyURI = null;
721: this .mailHost = null;
722: this .mailPort = 0;
723: this .fromAddress = null;
724: this .attachmentDescriptor = null;
725: this .port = 0;
726: this .contextPath = null;
727: this .sendPartial = true;
728: this .smtpMessage = null;
729: final Iterator i = this .usedSources.iterator();
730: while (i.hasNext()) {
731: final Source source = (Source) i.next();
732: this .resolver.release(source);
733: }
734: this .usedSources.clear();
735: super .recycle();
736: }
737:
738: static class AttachmentDescriptor {
739: String strAttrName;
740: String strAttrMimeType;
741: String strAttrSrc;
742: String strAttrFile;
743: String strContent;
744:
745: protected AttachmentDescriptor(String newAttrName,
746: String newAttrMimeType, String newAttrSrc,
747: String newAttrFile) {
748: this .strAttrName = newAttrName;
749: this .strAttrMimeType = newAttrMimeType;
750: this .strAttrSrc = newAttrSrc;
751: this .strAttrFile = newAttrFile;
752: }
753:
754: protected void setContent(String newContent) {
755: this .strContent = newContent;
756: }
757:
758: protected AttachmentDescriptor copy() {
759: AttachmentDescriptor aD = new AttachmentDescriptor(
760: this .strAttrName, this .strAttrMimeType,
761: this .strAttrSrc, this .strAttrFile);
762: aD.setContent(this .strContent);
763:
764: return aD;
765: }
766:
767: protected boolean isURLSource() {
768: return (this .strAttrSrc != null);
769: }
770:
771: protected boolean isFileSource() {
772: return (this .strAttrFile != null);
773: }
774:
775: protected boolean isTextContent() {
776: return (this .strContent != null);
777: }
778: }
779:
780: static class AddressHandler {
781: private InternetAddress address;
782: private String sendMailResult;
783:
784: protected AddressHandler(InternetAddress newAddress) {
785: this .address = newAddress;
786: }
787:
788: protected void setSendMailResult(String newSendMailResult) {
789: this .sendMailResult = newSendMailResult;
790: }
791:
792: /**
793: * @return mail-address
794: */
795: public InternetAddress getAddress() {
796: return address;
797: }
798:
799: /**
800: * @return sendMailResult as String
801: */
802: public String getSendMailResult() {
803: return sendMailResult;
804: }
805: }
806: }
|