KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > mail > MailMessageSender


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.mail;
17
18 import org.apache.avalon.framework.CascadingRuntimeException;
19 import org.apache.avalon.framework.activity.Initializable;
20 import org.apache.avalon.framework.component.Component;
21 import org.apache.avalon.framework.configuration.Configurable;
22 import org.apache.avalon.framework.configuration.Configuration;
23 import org.apache.avalon.framework.configuration.ConfigurationException;
24 import org.apache.avalon.framework.logger.AbstractLogEnabled;
25 import org.apache.avalon.framework.service.ServiceException;
26 import org.apache.avalon.framework.service.ServiceManager;
27 import org.apache.avalon.framework.service.Serviceable;
28
29 import org.apache.cocoon.mail.datasource.FilePartDataSource;
30 import org.apache.cocoon.mail.datasource.SourceDataSource;
31 import org.apache.cocoon.servlet.multipart.Part;
32
33 import org.apache.excalibur.source.Source;
34 import org.apache.excalibur.source.SourceResolver;
35
36 import javax.activation.DataHandler JavaDoc;
37 import javax.activation.DataSource JavaDoc;
38 import javax.mail.Authenticator JavaDoc;
39 import javax.mail.BodyPart JavaDoc;
40 import javax.mail.Message.RecipientType;
41 import javax.mail.MessagingException JavaDoc;
42 import javax.mail.Multipart JavaDoc;
43 import javax.mail.PasswordAuthentication JavaDoc;
44 import javax.mail.Session JavaDoc;
45 import javax.mail.Transport JavaDoc;
46 import javax.mail.internet.AddressException JavaDoc;
47 import javax.mail.internet.InternetAddress JavaDoc;
48 import javax.mail.internet.MimeBodyPart JavaDoc;
49 import javax.mail.internet.MimeMessage JavaDoc;
50 import javax.mail.internet.MimeMultipart JavaDoc;
51 import java.io.IOException JavaDoc;
52 import java.net.MalformedURLException JavaDoc;
53 import java.util.ArrayList JavaDoc;
54 import java.util.Date JavaDoc;
55 import java.util.Iterator JavaDoc;
56 import java.util.List JavaDoc;
57 import java.util.Properties JavaDoc;
58
59 /**
60  * A helper class used by the {@link org.apache.cocoon.acting.Sendmail}
61  * and the <code>sendmail.xsl</code> logicsheet for sending an email message.
62  *
63  * <h3>Configuration</h3>
64  * <table><tbody>
65  * <tr><th>smtp-host</th><td>SMTP server to use sending mail.</td><td>opt</td><td>String</td><td><code>localhost</code></td></tr>
66  * <tr><th>smtp-user</th><td>User name for authentication</td><td>opt</td><td>String</td></tr>
67  * <tr><th>smtp-password</th><td>Password for authentication</td><td>opt</td><td>String</td></tr>
68  * </tbody></table>
69  *
70  * @author <a HREF="mailto:frank.ridderbusch@gmx.de">Frank Ridderbusch</a>
71  * @author <a HREF="mailto:haul@apache.org">Christian Haul</a>
72  * @since 2.1
73  * @version CVS $Id: MailMessageSender.java 155031 2005-02-23 17:32:37Z vgritsenko $
74  */

75 public class MailMessageSender
76         extends AbstractLogEnabled
77         implements MailSender, Configurable, Serviceable, Initializable, Component {
78
79     private ServiceManager manager;
80
81     private Session JavaDoc session;
82
83     private String JavaDoc smtpHost;
84     private String JavaDoc smtpUser;
85     private String JavaDoc smtpPswd;
86
87     private String JavaDoc from;
88     private String JavaDoc to;
89     private String JavaDoc replyTo;
90     private String JavaDoc cc;
91     private String JavaDoc bcc;
92     private String JavaDoc subject;
93     private String JavaDoc charset;
94     private String JavaDoc src;
95     private String JavaDoc srcMimeType;
96     private String JavaDoc body;
97     private List JavaDoc attachments;
98     private Exception JavaDoc exception;
99
100     /**
101      * Helper class for attachment data.
102      * @author haul
103      * @since 2.1
104      */

105     private static class Attachment {
106         private Object JavaDoc obj = null;
107         private String JavaDoc type = null;
108         private String JavaDoc name = null;
109         protected boolean isURL = false;
110
111         /**
112          * Create a new attachment object encapsulating obj.
113          * @param obj attachment
114          */

115         public Attachment(Object JavaDoc obj) {
116             this(obj, null, null);
117         }
118
119         /**
120          * Create a new attachment object encapsulating obj
121          * @param obj attachment
122          * @param type override mime type
123          * @param name override attachment name
124          */

125         public Attachment(Object JavaDoc obj, String JavaDoc type, String JavaDoc name) {
126             this(obj, type, name, false);
127         }
128
129         /**
130          * Create a new attachment object encapsulating obj
131          * @param obj attachment
132          * @param type override mime type
133          * @param name override attachment name
134          * @param isURI obj is an instance of String and contains a URL
135          */

136         public Attachment(Object JavaDoc obj, String JavaDoc type, String JavaDoc name, boolean isURI) {
137             this.obj = obj;
138             this.type = type;
139             this.name = name;
140             this.isURL = isURI;
141             if (isNullOrEmpty(this.type))
142                 this.type = null;
143             if (isNullOrEmpty(this.name))
144                 this.name = null;
145         }
146
147         /**
148          * Check String for null or empty.
149          * @param str
150          * @return true if str is null, empty string, or equals "null"
151          */

152         private boolean isNullOrEmpty(String JavaDoc str) {
153             return (str == null || "".equals(str) || "null".equals(str));
154         }
155
156         /**
157          * Is the encapsulated object a URL?
158          * @return true if URL
159          */

160         public boolean isURL() {
161             return this.isURL;
162         }
163
164         /**
165          * Return attachment name. The argument overrides the stored name.
166          * @param name
167          * @return stored name or otherwise parameter
168          */

169         public String JavaDoc getName(String JavaDoc name) {
170             return (this.name == null ? name : this.name);
171         }
172
173         /**
174          * Return attachment type. The argument overrides the stored type.
175          * @param type attachment type
176          * @return stored type or otherwise parameter
177          */

178         public String JavaDoc getType(String JavaDoc type) {
179             return (this.type == null ? type : this.type);
180         }
181
182         /**
183          * Returns encapsulated object
184          */

185         public Object JavaDoc getObject() {
186             return this.obj;
187         }
188     }
189
190     public MailMessageSender() {
191     }
192
193     /**
194      * Creates a new instance of MailMessageSender
195      * Keep constructor for backwards compatibility.
196      * @param smtpHost The host name or ip-address of a host to accept
197      * the email for delivery.
198      * @deprecated Since 2.1.5. Please use {@link MailSender} component instead.
199      */

200     public MailMessageSender(String JavaDoc smtpHost) {
201         smtpHost = smtpHost.trim();
202         setSmtpHost(smtpHost);
203         initialize();
204     }
205
206     public void service(ServiceManager manager) {
207         this.manager = manager;
208     }
209
210     /* (non-Javadoc)
211      * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
212      */

213     public void configure(Configuration config) throws ConfigurationException {
214         this.smtpHost = config.getChild("smtp-host").getValue(null);
215         this.smtpUser = config.getChild("smtp-user").getValue(null);
216         this.smtpPswd = config.getChild("smtp-password").getValue(null);
217     }
218
219     /* (non-Javadoc)
220      * @see org.apache.avalon.framework.activity.Initializable#initialize()
221      */

222     public void initialize() {
223         initSession();
224         this.attachments = new ArrayList JavaDoc();
225     }
226
227     private void initSession() {
228         Properties JavaDoc properties = new Properties JavaDoc();
229         if (smtpHost == null || smtpHost.equals("") || smtpHost.equals("null")) {
230             properties.put("mail.smtp.host", "127.0.0.1");
231         } else {
232             properties.put("mail.smtp.host", smtpHost);
233         }
234
235         if (smtpUser == null || smtpUser.equals("") || smtpUser.equals("null")) {
236             this.session = Session.getInstance(properties);
237         } else {
238             properties.put("mail.smtp.auth", "true");
239             this.session = Session.getInstance(properties, new Authenticator JavaDoc() {
240                 protected PasswordAuthentication JavaDoc getPasswordAuthentication() {
241                     return new PasswordAuthentication JavaDoc(smtpUser, smtpPswd);
242                 }
243             });
244         }
245     }
246
247     /* (non-Javadoc)
248      * @see org.apache.cocoon.mail.MailSender#setSmtpHost(java.lang.String)
249      */

250     public void setSmtpHost(String JavaDoc hostname) {
251         this.smtpHost = hostname;
252         initSession();
253     }
254
255     public void setSmtpHost(String JavaDoc hostname, String JavaDoc username, String JavaDoc password) {
256         this.smtpUser = username;
257         this.smtpPswd = password;
258         setSmtpHost(hostname);
259     }
260
261
262     /**
263      * Assemble the message from the defined fields and send it.
264      * @throws AddressException when problems with email addresses are found
265      * @throws MessagingException when message could not be send.
266      */

267     public void send() throws AddressException JavaDoc, MessagingException JavaDoc {
268         SourceResolver resolver = null;
269         try {
270             resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
271             doSend(resolver);
272         } catch(ServiceException se) {
273             throw new CascadingRuntimeException("Cannot get Source Resolver to send mail", se);
274         } finally {
275             this.manager.release(resolver);
276         }
277     }
278
279     /**
280      * Assemble the message from the defined fields and send it.
281      * @throws AddressException when problems with email addresses are found
282      * @throws MessagingException when message could not be send.
283      * @deprecated Since 2.1.5. Use {@link #send()} which doesn't require passing the source resolver
284      */

285     public void send(org.apache.cocoon.environment.SourceResolver resolver)
286     throws AddressException JavaDoc, MessagingException JavaDoc {
287         // resolver is automatically down-casted
288
doSend(resolver);
289     }
290
291     private void doSend(SourceResolver resolver)
292     throws AddressException JavaDoc, MessagingException JavaDoc {
293         final List JavaDoc sourcesList = new ArrayList JavaDoc();
294
295         final MimeMessage JavaDoc message = new MimeMessage JavaDoc(this.session);
296
297         if (this.from == null) {
298             throw new AddressException JavaDoc("No from address");
299         } else {
300             try {
301                 message.setFrom(new InternetAddress JavaDoc(this.from));
302             } catch (AddressException JavaDoc e) {
303                 throw new AddressException JavaDoc("Invalid from address: " + this.from + ": " +
304                                            e.getMessage());
305             }
306         }
307
308         if (this.to == null) {
309             throw new AddressException JavaDoc("no to address");
310         } else {
311             try {
312                 message.setRecipients(RecipientType.TO,
313                                       InternetAddress.parse(this.to));
314             } catch (AddressException JavaDoc e) {
315                 throw new AddressException JavaDoc("Invalid to address: " + this.to + ": " +
316                                            e.getMessage());
317             }
318         }
319
320         if (this.replyTo != null) {
321             try {
322                 message.setReplyTo(InternetAddress.parse(this.replyTo));
323             } catch (AddressException JavaDoc e) {
324                 throw new AddressException JavaDoc("Invalid replyTo address: " + this.replyTo + ": " +
325                                            e.getMessage());
326             }
327         }
328
329         if (this.cc != null) {
330             try {
331                 message.setRecipients(RecipientType.CC,
332                                       InternetAddress.parse(this.cc));
333             } catch (AddressException JavaDoc e) {
334                 throw new AddressException JavaDoc("Invalid cc address: " + this.cc + ": " +
335                                            e.getMessage());
336             }
337         }
338
339         if (this.bcc != null) {
340             try {
341                 message.setRecipients(RecipientType.BCC,
342                                       InternetAddress.parse(this.bcc));
343             } catch (AddressException JavaDoc e) {
344                 throw new AddressException JavaDoc("Invalid bcc address: " + this.bcc + ": " +
345                                            e.getMessage());
346             }
347         }
348
349         if (this.subject != null) {
350             message.setSubject(this.subject);
351         }
352
353         message.setSentDate(new Date JavaDoc());
354
355         Attachment a = null;
356         try {
357             if (this.attachments.isEmpty()) {
358                 if (this.src != null) {
359                     DataSource ds = null;
360
361                     Source source = resolver.resolveURI(this.src);
362                     sourcesList.add(source);
363                     if (source.exists()) {
364                         ds =
365                             new SourceDataSource(
366                                 source,
367                                 (this.srcMimeType == null
368                                     ? source.getMimeType()
369                                     : this.srcMimeType),
370                                 this.src.substring(this.src.lastIndexOf('/') + 1));
371                     }
372
373                     message.setDataHandler(new DataHandler JavaDoc(ds));
374
375                 } else if (this.body != null) {
376                     if (this.charset != null) {
377                         message.setText(this.body, this.charset);
378                     } else {
379                         message.setText(this.body);
380                     }
381                 }
382             } else {
383                 Multipart JavaDoc multipart = new MimeMultipart JavaDoc();
384                 BodyPart JavaDoc bodypart = new MimeBodyPart JavaDoc();
385                 multipart.addBodyPart(bodypart);
386                 message.setContent(multipart);
387
388                 if (this.src != null) {
389                     DataSource ds = null;
390
391                     Source source = resolver.resolveURI(this.src);
392                     sourcesList.add(source);
393                     if (source.exists()) {
394                         ds =
395                             new SourceDataSource(
396                                 source,
397                                 (this.srcMimeType == null
398                                     ? source.getMimeType()
399                                     : this.srcMimeType),
400                                 this.src.substring(this.src.lastIndexOf('/') + 1));
401                     }
402
403                     bodypart.setDataHandler(new DataHandler JavaDoc(ds));
404                     bodypart.setFileName(ds.getName());
405
406                 } else if (this.body != null) {
407                     bodypart.setText(this.body);
408                 }
409
410                 for (Iterator JavaDoc i = this.attachments.iterator(); i.hasNext();) {
411                     a = (Attachment) i.next();
412                     DataSource ds = null;
413                     if (a.isURL) {
414                         String JavaDoc name = (String JavaDoc) a.getObject();
415                         Source src = resolver.resolveURI(name);
416                         sourcesList.add(src);
417                         if (src.exists()) {
418                             ds =
419                                 new SourceDataSource(
420                                     src,
421                                     a.getType(src.getMimeType()),
422                                     a.getName(name.substring(name.lastIndexOf('/') + 1)));
423                         }
424                     } else {
425                         if (a.getObject() instanceof Part) {
426                             Part part = (Part) a.getObject();
427                             ds =
428                                 new FilePartDataSource(
429                                     part,
430                                     a.getType(part.getMimeType()),
431                                     a.getName(part.getUploadName()));
432                         } else {
433                             // TODO: other classes?
434
throw new AddressException JavaDoc("Not yet supported: " + a.getObject());
435                         }
436                     }
437
438                     bodypart = new MimeBodyPart JavaDoc();
439                     bodypart.setDataHandler(new DataHandler JavaDoc(ds));
440                     bodypart.setFileName(ds.getName());
441                     multipart.addBodyPart(bodypart);
442                 }
443             }
444
445             message.saveChanges();
446             Transport.send(message);
447         } catch (MessagingException JavaDoc me) {
448             throw new MessagingException JavaDoc(me.getMessage());
449         } catch (MalformedURLException JavaDoc e) {
450             throw new AddressException JavaDoc("Malformed attachment URL: " +
451                                        a.getObject() + " error " + e.getMessage());
452         } catch (IOException JavaDoc e) {
453             throw new AddressException JavaDoc("IOException accessing attachment URL: " +
454                                        a.getObject() + " error " + e.getMessage());
455         } finally {
456             if (sourcesList != null) {
457                 for (Iterator JavaDoc j = sourcesList.iterator(); j.hasNext();) {
458                     resolver.release((Source) j.next());
459                 }
460             }
461         }
462     }
463
464     /**
465      * Invokes the {@link #send()} method but catches any exception thrown. This
466      * method is intended to be used from the sendmail logicsheet.
467      * @return true when successful
468      */

469     public boolean sendIt() {
470         this.exception = null;
471         try {
472             send();
473         } catch (Exception JavaDoc e) {
474             this.exception = e;
475         }
476         return exception == null;
477     }
478
479     /**
480      * Invokes the {@link #send(org.apache.cocoon.environment.SourceResolver)}
481      * method but catches any exception thrown. This
482      * method is intended to be used from the sendmail logicsheet.
483      *
484      * @return true when successful
485      * @deprecated Since 2.1.5. Use {@link #sendIt()} which doesn't require passing the source resolver
486      */

487     public boolean sendIt(org.apache.cocoon.environment.SourceResolver resolver) {
488         this.exception = null;
489         try {
490             send(resolver);
491         } catch (Exception JavaDoc e) {
492             this.exception = e;
493         }
494         return exception == null;
495     }
496
497     /**
498      * Accesses any Exception caught by
499      * {@link #sendIt(org.apache.cocoon.environment.SourceResolver)}.
500      *
501      * @return AddressException or MessagingException
502      */

503     public Exception JavaDoc getException() {
504         return this.exception;
505     }
506
507
508     /**
509      * Set the <CODE>from</CODE> address of the message.
510      * @param from The address the message appears to be from.
511      */

512     public void setFrom(String JavaDoc from) {
513         if (!("".equals(from) || "null".equals(from))) {
514             this.from = from.trim();
515         }
516     }
517
518     /**
519      * Sets the destination address(es) for the message. The address
520      * is in the format, that
521      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
522      * (one or more email addresses separated by a commas).
523      * @param to the destination address(es)
524      * @see javax.mail.internet.InternetAddress#parse(String)
525      */

526     public void setTo(String JavaDoc to) {
527         if (!("".equals(to) || "null".equals(to))) {
528             this.to = to.trim();
529         }
530     }
531
532     /**
533      * Sets the reply-to address(es) for the message. The address
534      * is in the format, that
535      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
536      * (one or more email addresses separated by a commas).
537      * @param replyTo the address(es) that replies should be sent to
538      * @see javax.mail.internet.InternetAddress#parse(String)
539      */

540     public void setReplyTo(String JavaDoc replyTo) {
541         if (!("".equals(replyTo) || "null".equals(replyTo))) {
542             this.replyTo = replyTo.trim();
543         }
544     }
545
546     /**
547      * Sets the address(es), which should receive a carbon copy of the
548      * message. The address is in the format, that
549      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
550      * (one or more email addresses separated by a commas).
551      * @param cc the address(es), which should receive a carbon copy.
552      * @see javax.mail.internet.InternetAddress#parse(String)
553      */

554     public void setCc(String JavaDoc cc) {
555         if (!("".equals(cc) || "null".equals(cc))) {
556             this.cc = cc.trim();
557         }
558     }
559
560     /**
561      * Sets the address(es), which should receive a black carbon copy of
562      * the message. The address is in the format, that
563      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
564      * (one or more email addresses separated by a commas).
565      * @param bcc the address(es), which should receive a black carbon copy.
566      * @see javax.mail.internet.InternetAddress#parse(String)
567      */

568     public void setBcc(String JavaDoc bcc) {
569         if (!("".equals(bcc) || "null".equals(bcc))) {
570             this.bcc = bcc.trim();
571         }
572     }
573
574     /**
575      * Sets the character set for encoding the message. This has no effect,
576      * if any attachments are send in the message.
577      * @param charset the character set to be used for enbcoding the message
578      */

579     public void setCharset(String JavaDoc charset) {
580         if (!("".equals(charset) || "null".equals(charset))) {
581             this.charset = charset.trim();
582         }
583     }
584
585     /**
586      * Sets the subject line of the message.
587      * @param subject the subject line of the message
588      */

589     public void setSubject(String JavaDoc subject) {
590         if (!("".equals(subject) || "null".equals(subject))) {
591             this.subject = subject;
592         }
593     }
594
595     /**
596      * Sets the body text of the email message.
597      * If both a text body and a body read from a source are set,
598      * only the latter will be used.
599      *
600      * @param body The body text of the email message
601      */

602     public void setBody(String JavaDoc body) {
603         if (!("".equals(body) || "null".equals(body))) {
604             this.body = body;
605         }
606     }
607
608     /**
609      * Sets the body source URL of the email message.
610      * If both a text body and a body read from a source are set,
611      * only the latter will be used.
612      *
613      * @param src The body source URL of the email message
614      */

615     public void setBodyFromSrc(String JavaDoc src) {
616         if (!("".equals(src) || "null".equals(src))) {
617             this.src = src;
618         }
619     }
620
621     /**
622      * Sets the optional body source Mime Type of the email message.
623      * @param srcMimeType The optional body source Mime Type of the email message
624      */

625     public void setBodyFromSrcMimeType(String JavaDoc srcMimeType) {
626         if (!("".equals(srcMimeType) || "null".equals(srcMimeType))) {
627             this.srcMimeType = srcMimeType;
628         }
629     }
630
631     /**
632      * Add an attachement to the message to be send. The attachment can
633      * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
634      * {@link org.apache.cocoon.servlet.multipart.Part} or its
635      * subclasses.
636      * @param attachment to be send with the message
637      * @see org.apache.excalibur.source.Source
638      */

639     public void addAttachment(Object JavaDoc attachment) {
640         if (attachment != null) {
641             attachments.add(new Attachment(attachment));
642         }
643     }
644
645     /**
646      * Add an attachement to the message to be send. The attachment can
647      * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
648      * {@link org.apache.cocoon.servlet.multipart.Part} or its
649      * subclasses.
650      * @param attachment to be send with the message
651      * @param type mime type (optional)
652      * @param name attachment name (optional)
653      * @see org.apache.excalibur.source.Source
654      */

655     public void addAttachment(Object JavaDoc attachment, String JavaDoc type, String JavaDoc name) {
656         if (attachment != null) {
657             attachments.add(new Attachment(attachment, type, name));
658         }
659     }
660
661     /**
662      * Add an attachement to the message to be send. The attachment can
663      * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
664      * {@link org.apache.cocoon.servlet.multipart.Part} or its
665      * subclasses.
666      * @param url URL to attach to the message
667      * @see org.apache.excalibur.source.Source
668      */

669     public void addAttachmentURL(String JavaDoc url) {
670         if (url != null) {
671             attachments.add(new Attachment(url, null, null, true));
672         }
673     }
674
675     /**
676      * Add an attachement to the message to be send. The attachment can
677      * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
678      * {@link org.apache.cocoon.servlet.multipart.Part} or its
679      * subclasses.
680      * @param url URL to attach to the message
681      * @param type mime type (optional)
682      * @param name attachment name (optional)
683      * @see org.apache.excalibur.source.Source
684      */

685     public void addAttachmentURL(String JavaDoc url, String JavaDoc type, String JavaDoc name) {
686         if (url != null) {
687             attachments.add(new Attachment(url, type, name, true));
688         }
689     }
690 }
691
Popular Tags