KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pentaho > plugin > email > EmailComponent


1 /*
2  * Copyright 2006 Pentaho Corporation. All rights reserved.
3  * This software was developed by Pentaho Corporation and is provided under the terms
4  * of the Mozilla Public License, Version 1.1, or any later version. You may not use
5  * this file except in compliance with the license. If you need a copy of the license,
6  * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
7  * BI Platform. The Initial Developer is Pentaho Corporation.
8  *
9  * Software distributed under the Mozilla Public License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
11  * the license for the specific language governing your rights and limitations.
12  *
13  * @created Apr 28, 2005
14  * @author James Dixon
15  */

16
17 package org.pentaho.plugin.email;
18
19 import java.io.BufferedInputStream JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Date JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 import javax.activation.DataHandler JavaDoc;
29 import javax.activation.DataSource JavaDoc;
30 import javax.activation.FileDataSource JavaDoc;
31 import javax.mail.AuthenticationFailedException JavaDoc;
32 import javax.mail.Authenticator JavaDoc;
33 import javax.mail.Message JavaDoc;
34 import javax.mail.Multipart JavaDoc;
35 import javax.mail.PasswordAuthentication JavaDoc;
36 import javax.mail.SendFailedException JavaDoc;
37 import javax.mail.Session JavaDoc;
38 import javax.mail.Transport JavaDoc;
39 import javax.mail.internet.InternetAddress JavaDoc;
40 import javax.mail.internet.MimeBodyPart JavaDoc;
41 import javax.mail.internet.MimeMessage JavaDoc;
42 import javax.mail.internet.MimeMultipart JavaDoc;
43
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46 import org.dom4j.Document;
47 import org.dom4j.Node;
48 import org.pentaho.core.solution.IActionResource;
49 import org.pentaho.core.system.PentahoSystem;
50 import org.pentaho.core.util.XmlHelper;
51 import org.pentaho.messages.Messages;
52 import org.pentaho.messages.util.LocaleHelper;
53 import org.pentaho.plugin.ComponentBase;
54
55 /**
56  * @author James Dixon
57  *
58  * TODO To change the template for this generated type comment go to Window -
59  * Preferences - Java - Code Style - Code Templates
60  */

61 public class EmailComponent extends ComponentBase {
62
63     /**
64      *
65      */

66     private static final long serialVersionUID = 1584906077946023715L;
67
68     private String JavaDoc defaultFrom;
69
70     String JavaDoc mailer = "smtpsend"; //$NON-NLS-1$
71

72     String JavaDoc protocol = null, host = null;
73
74     String JavaDoc recordDir = null;
75
76     public Log getLogger() {
77         return LogFactory.getLog(EmailComponent.class);
78     }
79
80     protected boolean validateSystemSettings() {
81         // get the settings from the system configuration file
82
String JavaDoc mailhost = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.smtp.host", null); //$NON-NLS-1$ //$NON-NLS-2$
83
boolean authenticate = "true".equalsIgnoreCase(PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.smtp.auth", "false")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
84
// don't store these in a class member for secutiry
85
String JavaDoc user = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.userid", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
86
String JavaDoc password = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.password", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
87
defaultFrom = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.from.default", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
88

89         // Check the email server settings...
90
if (mailhost.equals("") || (user.equals("") && authenticate) || defaultFrom.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
91
// looks like the email stuff is not configured yet...
92
// see if we can provide feedback to the user...
93

94                 boolean allowParameterUI = feedbackAllowed();
95
96                 if (allowParameterUI) {
97                 OutputStream JavaDoc feedbackStream = getFeedbackOutputStream();
98                 StringBuffer JavaDoc messageBuffer = new StringBuffer JavaDoc();
99                 org.pentaho.core.util.UIUtil.formatErrorMessage(
100                         "text/html", Messages.getString("Email.USER_COULD_NOT_SEND_EMAIL"), Messages.getString("Email.USER_SETTINGS_HELP", "~/pentaho-demo/pentaho-solutions/system/smtp-email/email_config.xml"), messageBuffer); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
101
try {
102                     feedbackStream.write(messageBuffer.toString().getBytes(LocaleHelper.getSystemEncoding()));
103                 } catch (Exception JavaDoc e) {
104                     error(Messages.getErrorString("Base.ERROR_0003_INVALID_FEEDBACK_STREAM"), e); //$NON-NLS-1$
105
return false;
106                 }
107                 return false;
108             } else {
109                 // we are not allowed to provide feedback and cannot continue...
110
error(Messages.getErrorString("Email.ERROR_0009_SERVER_SETTINGS_NOT_SET")); //$NON-NLS-1$
111
return false;
112             }
113         }
114         boolean ok = (mailhost != null);
115         if (authenticate) {
116             ok &= (user != null) && (password != null);
117         }
118         ok &= defaultFrom != null;
119         return ok;
120     }
121
122     public boolean init() {
123         return true;
124     }
125
126     public boolean validateAction() {
127         // make sure that we can get a "to" email address
128
if (!isDefinedInput("to")) { //$NON-NLS-1$
129
error(Messages.getErrorString("Email.ERROR_0001_TO_NOT_DEFINED", getActionName())); //$NON-NLS-1$
130
return false;
131         }
132         // make sure that we can get a subject for the email
133
if (!isDefinedInput("subject")) { //$NON-NLS-1$
134
error(Messages.getErrorString("Email.ERROR_0002_SUBJECT_NOT_DEFINED", getActionName())); //$NON-NLS-1$
135
return false;
136         }
137         // make sure that we have either a plain text or html message for the email
138
if (!isDefinedInput("message-plain") && !isDefinedInput("message-html")) { //$NON-NLS-1$ //$NON-NLS-2$
139
error(Messages.getErrorString("Email.ERROR_0003_BODY_NOT_DEFINED", getActionName())); //$NON-NLS-1$
140
return false;
141         }
142
143         return true;
144
145     }
146
147     public boolean executeAction() {
148
149         ArrayList JavaDoc tos = new ArrayList JavaDoc();
150         String JavaDoc from;
151         String JavaDoc subject;
152         ArrayList JavaDoc ccs = new ArrayList JavaDoc();
153         ArrayList JavaDoc bccs = new ArrayList JavaDoc();
154
155         ArrayList JavaDoc attachments = new ArrayList JavaDoc();
156
157         String JavaDoc messagePlain = null;
158         Object JavaDoc toObj = getInputValue("to"); //$NON-NLS-1$
159
if (toObj instanceof HashMap JavaDoc) {
160             HashMap JavaDoc data = (HashMap JavaDoc) toObj;
161
162             tos.add(data.get("to")); //$NON-NLS-1$
163
subject = (String JavaDoc) data.get("subject"); //$NON-NLS-1$
164
messagePlain = (String JavaDoc) data.get("message-plain"); //$NON-NLS-1$
165
} else {
166             String JavaDoc toStr = getInputStringValue("to"); //$NON-NLS-1$
167
if (toStr.trim().length() > 0) {
168                 tos.add(toStr);
169             }
170
171             subject = getInputStringValue("subject"); //$NON-NLS-1$
172
if (isDefinedInput("message-plain")) { //$NON-NLS-1$
173
messagePlain = getInputStringValue("message-plain"); //$NON-NLS-1$
174
}
175         }
176
177         // these inputs are optional, so check before asking for them
178
from = null;
179         if (isDefinedInput("from")) { //$NON-NLS-1$
180
from = getInputStringValue("from"); //$NON-NLS-1$
181
} else {
182             from = defaultFrom;
183         }
184
185         if (isDefinedInput("cc")) { //$NON-NLS-1$
186
ccs.add(getInputStringValue("cc")); //$NON-NLS-1$
187
}
188
189         if (isDefinedInput("bcc")) { //$NON-NLS-1$
190
bccs.add(getInputStringValue("bcc")); //$NON-NLS-1$
191
}
192
193         String JavaDoc messageHtml = null;
194         if (isDefinedInput("message-html")) { //$NON-NLS-1$
195
messageHtml = getInputStringValue("message-html"); //$NON-NLS-1$
196
}
197
198         String JavaDoc attachParameter = null;
199         String JavaDoc attachName = null;
200         Node curNode = null;
201         boolean isResource;
202
203         List JavaDoc attachNodes = getComponentDefinition().selectNodes("attachment-ref"); //$NON-NLS-1$
204
if ( (attachNodes != null) && (attachNodes.size() > 0) ) {
205             for (int i = 0; i < attachNodes.size(); ++i) {
206                 curNode = (Node) attachNodes.get(i);
207                 attachName = getInputStringValue(XmlHelper.getNodeText("@name-param", curNode, null)); //$NON-NLS-1$
208
attachParameter = XmlHelper.getNodeText("@resource-param", curNode, null); //$NON-NLS-1$
209
isResource = true;
210                 if (attachParameter == null) {
211                     attachParameter = XmlHelper.getNodeText("@input-param", curNode, null); //$NON-NLS-1$
212
isResource = false;
213                 }
214
215                 AttachStruct attachData = getAttachData(attachParameter, attachName, isResource);
216                 if (attachData != null) {
217                     attachments.add(attachData);
218                 }
219             }
220         } else {// No attachments, try Old Style
221
if (isDefinedInput("attach")) { //$NON-NLS-1$
222
attachParameter = getInputStringValue("attach"); //$NON-NLS-1$
223
attachName = getInputStringValue("attach-name"); //$NON-NLS-1$
224
if ((attachParameter != null) && (attachName != null)) {
225                     AttachStruct attachData = getAttachData(attachParameter, attachName, false);
226                     if (attachData != null) {
227                         attachments.add(attachData);
228                     }
229                 }
230             }
231         }
232         /*
233          * if( context.getInputNames().contains( "attach" ) ) { //$NON-NLS-1$
234          * Object attachParameter = context.getInputParameter( "attach"
235          * ).getValue(); //$NON-NLS-1$ // We have a list of attachments, each
236          * element of the list is the name of the parameter containing the
237          * attachment // Use the parameter filename portion as the attachment
238          * name. if ( attachParameter instanceof String ) { String attachName =
239          * context.getInputParameter( "attach-name" ).getStringValue();
240          * //$NON-NLS-1$ AttachStruct attachData = getAttachData( context,
241          * (String)attachParameter, attachName ); if ( attachData != null ) {
242          * attachments.add( attachData ); } } else if ( attachParameter
243          * instanceof List ) { for ( int i = 0; i <
244          * ((List)attachParameter).size(); ++i ) { AttachStruct attachData =
245          * getAttachData( context, ((List)attachParameter).get( i ).toString(),
246          * null ); if ( attachData != null ) { attachments.add( attachData ); } } }
247          * else if ( attachParameter instanceof Map ) { for ( Iterator it =
248          * ((Map)attachParameter).entrySet().iterator(); it.hasNext(); ) {
249          * Map.Entry entry = (Map.Entry)it.next(); AttachStruct attachData =
250          * getAttachData( context, (String)entry.getValue(),
251          * (String)entry.getKey() ); if ( attachData != null ) {
252          * attachments.add( attachData ); } } } }
253          *
254          * int maxSize = Integer.MAX_VALUE; try { maxSize = new Integer(
255          * props.getProperty( "mail.max.attach.size" ) ).intValue(); } catch(
256          * Throwable t ) { //ignore if not set to a valid value }
257          *
258          * if ( totalAttachLength > maxSize ) { // Sort them in order TreeMap tm =
259          * new TreeMap(); for( int idx=0; idx<attachments.size(); idx++ ) { //
260          * tm.put( new Integer( )) } }
261          */

262
263         if (debug)
264             debug(Messages.getString("Email.DEBUG_TO_FROM", tos.toString(), from)); //$NON-NLS-1$
265
if (debug)
266             debug(Messages.getString("Email.DEBUG_CC_BCC", ccs.toString(), bccs.toString())); //$NON-NLS-1$
267
if (debug)
268             debug(Messages.getString("Email.DEBUG_SUBJECT", subject)); //$NON-NLS-1$
269
if (debug)
270             debug(Messages.getString("Email.DEBUG_PLAIN_MESSAGE", messagePlain)); //$NON-NLS-1$
271
if (debug)
272             debug(Messages.getString("Email.DEBUG_HTML_MESSAGE", messageHtml)); //$NON-NLS-1$
273

274         if (tos.size() == 0) {
275
276             // Get the output stream that the feedback is going into
277
OutputStream JavaDoc feedbackStream = getFeedbackOutputStream();
278             if (feedbackStream != null) {
279                 createFeedbackParameter("to", Messages.getString("Email.USER_ENTER_EMAIL_ADDRESS"), "", "", true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
280
setFeedbackMimeType("text/html"); //$NON-NLS-1$
281
return true;
282             } else {
283                 return false;
284             }
285         }
286         if (subject == null) {
287             error(Messages.getErrorString("Email.ERROR_0005_NULL_SUBJECT", getActionName())); //$NON-NLS-1$
288
return false;
289         }
290         if ((messagePlain == null) && (messageHtml == null)) {
291             error(Messages.getErrorString("Email.ERROR_0006_NULL_BODY", getActionName())); //$NON-NLS-1$
292
return false;
293         }
294
295         if (getRuntimeContext().isPromptPending() ) {
296                 return true;
297         }
298
299         try {
300
301             Properties JavaDoc props = new Properties JavaDoc();
302
303             try {
304                 Document configDocument = PentahoSystem.getSystemSettings().getSystemSettingsDocument("smtp-email/email_config.xml"); //$NON-NLS-1$
305
List JavaDoc properties = configDocument.selectNodes("/email-smtp/properties/*"); //$NON-NLS-1$
306
Iterator JavaDoc propertyIterator = properties.iterator();
307                 while (propertyIterator.hasNext()) {
308                     Node propertyNode = (Node) propertyIterator.next();
309                     String JavaDoc propertyName = propertyNode.getName();
310                     String JavaDoc propertyValue = propertyNode.getText();
311                     props.put(propertyName, propertyValue);
312                 }
313             } catch (Exception JavaDoc e) {
314                 error(Messages.getString("Email.ERROR_0013_CONFIG_FILE_INVALID"), e); //$NON-NLS-1$
315
return false;
316             }
317
318             boolean authenticate = "true".equalsIgnoreCase(props.getProperty("mail.smtp.auth")); //$NON-NLS-1$//$NON-NLS-2$
319

320             // Get a Session object
321

322             Session JavaDoc session;
323             if (authenticate) {
324                 Authenticator JavaDoc authenticator = new EmailAuthenticator();
325                 session = Session.getInstance(props, authenticator);
326             } else {
327                 session = Session.getInstance(props);
328             }
329
330             // if debugging is not set in the email config file, match the
331
// component debug setting
332
if (debug && !props.containsKey("mail.debug")) { //$NON-NLS-1$
333
session.setDebug(true);
334             }
335
336             // construct the message
337
MimeMessage JavaDoc msg = new MimeMessage JavaDoc(session);
338             if (from != null) {
339                 msg.setFrom(new InternetAddress JavaDoc(from));
340             } else {
341                 // There should be no way to get here
342
error(Messages.getString("Email.ERROR_0012_FROM_NOT_DEFINED")); //$NON-NLS-1$
343
}
344
345             if (tos != null) {
346                 for (int idx = 0; idx < tos.size(); idx++) {
347                     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse((String JavaDoc) tos.get(idx), false));
348                 }
349             }
350             if (ccs != null) {
351                 for (int idx = 0; idx < ccs.size(); idx++) {
352                     msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse((String JavaDoc) ccs.get(idx), false));
353                 }
354             }
355             if (bccs != null) {
356                 for (int idx = 0; idx < bccs.size(); idx++) {
357                     msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse((String JavaDoc) bccs.get(idx), false));
358                 }
359             }
360
361             if (subject != null) {
362                 msg.setSubject(subject);
363             }
364
365             if ((messagePlain != null) && (messageHtml == null) && (attachments.size() == 0)) {
366                 msg.setText(messagePlain);
367             } else if (attachments.size() == 0) {
368                 if (messagePlain != null) {
369                     msg.setContent(messagePlain, "text/plain"); //$NON-NLS-1$
370
}
371                 if (messageHtml != null) {
372                     msg.setContent(messageHtml, "text/html"); //$NON-NLS-1$
373
}
374             } else {
375                 // need to create a multi-part message...
376
// create the Multipart and add its parts to it
377
Multipart JavaDoc multipart = new MimeMultipart JavaDoc();
378                 // create and fill the first message part
379
if (messageHtml != null) {
380                     // create and fill the first message part
381
MimeBodyPart JavaDoc htmlBodyPart = new MimeBodyPart JavaDoc();
382                     htmlBodyPart.setContent(messageHtml, "text/html"); //$NON-NLS-1$
383
multipart.addBodyPart(htmlBodyPart);
384                 }
385
386                 if (messagePlain != null) {
387                     MimeBodyPart JavaDoc textBodyPart = new MimeBodyPart JavaDoc();
388                     textBodyPart.setContent(messagePlain, "text/plain"); //$NON-NLS-1$
389
multipart.addBodyPart(textBodyPart);
390                 }
391
392                 // add attachements
393
for (int idx = 0; idx < attachments.size(); idx++) {
394                     AttachStruct attachment = (AttachStruct) attachments.get(idx);
395
396                     DataSource JavaDoc dataSource = attachment.dataSrc;
397                     if (debug)
398                         debug(Messages.getString("Email.DEBUG_ADDING_ATTACHMENT", attachment.name)); //$NON-NLS-1$
399

400                     // create the second message part
401
MimeBodyPart JavaDoc attachmentBodyPart = new MimeBodyPart JavaDoc();
402
403                     // attach the file to the message
404
attachmentBodyPart.setDataHandler(new DataHandler JavaDoc(dataSource));
405                     attachmentBodyPart.setFileName(attachment.name);
406                     if (debug)
407                         debug(Messages.getString("Email.DEBUG_ATTACHMENT_SOURCE", dataSource.getName())); //$NON-NLS-1$
408
multipart.addBodyPart(attachmentBodyPart);
409                 }
410
411                 // add the Multipart to the message
412
msg.setContent(multipart);
413             }
414
415             msg.setHeader("X-Mailer", mailer); //$NON-NLS-1$
416
msg.setSentDate(new Date JavaDoc());
417
418             Transport.send(msg);
419
420             if (debug)
421                 debug(Messages.getString("Email.DEBUG_EMAIL_SUCCESS")); //$NON-NLS-1$
422
return true;
423             // TODO: persist the content set for a while...
424
} catch (SendFailedException JavaDoc e) {
425             error(Messages.getErrorString("Email.ERROR_0011_SEND_FAILED", tos.toString() ), e); //$NON-NLS-1$
426
/*
427             Exception ne;
428             MessagingException sfe = e;
429             while ((ne = sfe.getNextException()) != null && ne instanceof MessagingException) {
430                 sfe = (MessagingException) ne;
431                 error(Messages.getErrorString("Email.ERROR_0011_SEND_FAILED", sfe.toString()), sfe); //$NON-NLS-1$
432             }
433 */

434         } catch (AuthenticationFailedException JavaDoc e) {
435             error(Messages.getString("Email.ERROR_0014_AUTHENTICATION_FAILED", tos.toString()), e); //$NON-NLS-1$
436
} catch (Throwable JavaDoc e) {
437             error(Messages.getErrorString("Email.ERROR_0011_SEND_FAILED", tos.toString()), e); //$NON-NLS-1$
438
}
439         return false;
440     }
441
442     public void done() {
443
444     }
445
446     private AttachStruct getAttachData(String JavaDoc paramName, String JavaDoc attachName, boolean isResource) {
447         DataSource JavaDoc dataSrc = null;
448         if (isResource) {
449             IActionResource param = getResource(paramName);
450             if (param != null) {
451                 dataSrc = getResourceDataSource(param);
452             }
453         } else {
454             dataSrc = getDataSource(paramName);
455         }
456
457         int fileLength = -1;
458         if (dataSrc instanceof FileDataSource JavaDoc) {
459             fileLength = (int) ((FileDataSource JavaDoc) dataSrc).getFile().length();
460         } else {
461             try {
462                 BufferedInputStream JavaDoc inStrm = new BufferedInputStream JavaDoc(dataSrc.getInputStream());
463                 byte bytes[] = new byte[1024];
464                 fileLength = 0;
465                 int bytesRead = inStrm.read(bytes);
466                 while (bytesRead > 0) {
467                     bytesRead = inStrm.read(bytes);
468                     fileLength += bytesRead;
469                 }
470                 inStrm.close();
471             } catch (Throwable JavaDoc t) {
472                 return (null);
473             }
474         }
475         return (new AttachStruct(fileLength, (attachName == null) ? dataSrc.getName() : attachName, dataSrc));
476     }
477
478     private class EmailAuthenticator extends Authenticator JavaDoc {
479
480         protected PasswordAuthentication JavaDoc getPasswordAuthentication() {
481             String JavaDoc user = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.userid", null); //$NON-NLS-1$ //$NON-NLS-2$
482
String JavaDoc password = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.password", null); //$NON-NLS-1$ //$NON-NLS-2$
483
return new PasswordAuthentication JavaDoc(user, password);
484         }
485     }
486
487     class AttachStruct {
488         long size;
489
490         String JavaDoc name;
491
492         DataSource JavaDoc dataSrc;
493
494         AttachStruct(long size, String JavaDoc name, DataSource JavaDoc dataSrc) {
495             this.size = size;
496             this.name = name;
497             this.dataSrc = dataSrc;
498         }
499     }
500
501 }
502
Popular Tags