View Javadoc
1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.services.implementations;
20  
21  import org.apache.log4j.Logger;
22  import org.itracker.services.ConfigurationService;
23  import org.itracker.services.EmailService;
24  import org.itracker.util.EmailAuthenticator;
25  import org.itracker.util.NamingUtilites;
26  
27  import javax.mail.*;
28  import javax.mail.internet.AddressException;
29  import javax.mail.internet.InternetAddress;
30  import javax.mail.internet.MimeMessage;
31  import javax.naming.InitialContext;
32  import javax.naming.NamingException;
33  import java.io.UnsupportedEncodingException;
34  import java.util.*;
35  
36  public class DefaultEmailService implements EmailService {
37  
38      private ConfigurationService configurationService;
39  
40      @Deprecated
41      public static final String DEFAULT_FROM_ADDRESS = "itracker@localhost";
42      @Deprecated
43      public static final String DEFAULT_FROM_TEXT = "ITracker Notification System";
44      @Deprecated
45      public static final String DEFAULT_REPLYTO_ADDRESS = "itracker@localhost";
46      @Deprecated
47      public static final String DEFAULT_SMTP_HOST = "localhost";
48  
49      public static final String DEFAULT_SMTP_CHARSET = "ISO-8859-1";
50  
51  
52      private Session session;
53  
54      private final Logger logger = Logger.getLogger(DefaultEmailService.class);
55      private InternetAddress replyTo;
56      private InternetAddress from;
57  
58      public void setConfigurationService(
59              ConfigurationService configurationService) {
60          if (null == configurationService) {
61              throw new IllegalArgumentException("configuration service must not be null.");
62          }
63          if (null != this.configurationService) {
64              throw new IllegalStateException("configuration service was already set.");
65          }
66          this.configurationService = configurationService;
67      }
68  
69      /**
70       * @deprecated use mailssession from JNDI instead
71       */
72      private void initMailsession(String smtpHost, String smtpUserid, String smtpPassword) {
73          Authenticator smtpAuth = null;
74          Properties props = new Properties();
75          props.put("mail.smtp.host", smtpHost);
76          // props.put("mail.mime.charset", this.smtpCharset);
77  
78          if (smtpUserid != null && smtpPassword != null) {
79              smtpAuth = new EmailAuthenticator(
80                      new PasswordAuthentication(smtpUserid,
81                              smtpPassword));
82          }
83          this.session = Session.getInstance(props, smtpAuth);
84      }
85  
86      private void initCharset(String smtpCharset) {
87          if (null != smtpCharset) {
88              try {
89                  new String(new byte[0], smtpCharset);
90                  this.session.getProperties().put("mail.mime.charset",
91                          smtpCharset);
92                  logger.info("initCharset: cherset was initialized to "
93                          + session.getProperty("mail.mime.charset"));
94              } catch (UnsupportedEncodingException use) {
95                  logger
96                          .warn(
97                                  "initCharset: unsupported smtp charset configured, ignoring",
98                                  use);
99              }
100         }
101     }
102 
103     private void initFrom(String fromAddress, String fromText) {
104         if (null != fromAddress) {
105             try {
106                 this.from = new InternetAddress(fromAddress, fromText, readSmtpCharset(this.session));
107                 logger.info("initFrom: initialized from-address: " + this.from);
108             } catch (UnsupportedEncodingException e) {
109                 logger.warn("initReplyTo: could not initialize reply-to (configured: " +
110                         fromText + " <" + fromAddress + ">", e);
111             }
112         }
113     }
114 
115     private void initReplyTo(String replyToAddress, String replyToText) {
116         try {
117             this.replyTo = new InternetAddress(replyToAddress, replyToText, readSmtpCharset(this.session));
118             logger.info("initFrom: initialized reply-to: " + this.replyTo);
119         } catch (UnsupportedEncodingException e) {
120             logger.warn("initReplyTo: could not initialize reply-to (configured: " + replyToText + " <" + replyToAddress + ">", e);
121         }
122     }
123 
124 
125     public void init() {
126 
127         if (this.configurationService == null) {
128             throw new IllegalStateException("configuration service was not set.");
129         }
130 
131         String fromAddress = configurationService.getProperty(
132                 "notification_from_address", DEFAULT_FROM_ADDRESS);
133         String fromText = configurationService.getProperty("notification_from_text",
134                 DEFAULT_FROM_TEXT);
135         String replyToAddress = configurationService.getProperty(
136                 "notification_replyto_address", DEFAULT_REPLYTO_ADDRESS);
137 
138         String smtpCharset = configurationService.getProperty(
139                 "notification_smtp_charset", DEFAULT_SMTP_CHARSET);
140 
141         String mailSessionLookupName = configurationService.getMailSessionLookupName();
142 
143         try {
144             InitialContext ctx = new InitialContext();
145             logger.debug("init: got Mailsession from Naming Context:" + NamingUtilites.lookup(ctx, mailSessionLookupName));
146 
147 
148             this.session = (Session) NamingUtilites.lookup(ctx, mailSessionLookupName);
149         } catch (NamingException e) {
150             logger.warn("init: failed to get Mailsession from initial context.", e);
151         }
152         if (null == this.session) {
153             logger
154                     .warn("init: failed to lookup Session from JNDI lookup " + mailSessionLookupName + ", using manual session");
155             String smtpHost = configurationService.getProperty(
156                     "notification_smtp_host", DEFAULT_SMTP_HOST);
157             String smtpUserid = configurationService.getProperty(
158                     "notification_smtp_userid", null);
159             String smtpPassword = configurationService.getProperty(
160                     "notification_smtp_password", null);
161 
162             logger
163                     .warn("init: setting up SMTP manually, no session-lookup found in configuration!");
164             if ("".equals(smtpUserid) || "".equals(smtpPassword)) {
165                 smtpUserid = null;
166                 smtpPassword = null;
167             }
168             initMailsession(smtpHost, smtpUserid, smtpPassword);
169             initCharset(smtpCharset);
170             initFrom(fromAddress, fromText);
171 
172             if (logger.isDebugEnabled()) {
173                 logger.debug("init: From Address set to: " + fromAddress);
174                 logger.debug("init: From Text set to: " + fromText);
175                 logger.debug("init: ReplyTo Address set to: " + replyToAddress);
176                 logger.debug("init: SMTP server set to: " + smtpHost);
177                 logger.debug("init: SMTP userid set to: " + smtpUserid);
178                 logger.debug("init: SMTP password set to: " + smtpPassword);
179             }
180         } else {
181             initCharset(smtpCharset);
182             // use mailsession to initialize from.
183             initFrom(fromAddress, fromText);
184         }
185         initReplyTo(replyToAddress, fromText);
186 
187 
188     }
189 
190     /**
191      * @param address
192      * @param subject
193      * @param msgText
194      */
195     public void sendEmail(String address, String subject, String msgText) {
196         try {
197             InternetAddress[] recipients = new InternetAddress[1];
198             recipients[0] = new InternetAddress(address);
199 
200             sendEmail(recipients, subject, msgText);
201         } catch (AddressException ex) {
202             logger.warn(
203                     "AddressException while sending email. caught. address was "
204                             + address, ex);
205         }
206     }
207 
208     public void sendEmail(Set<InternetAddress> recipients, String subject,
209                           String message) {
210 
211         InternetAddress[] recipientsArray = new ArrayList<InternetAddress>(recipients).toArray(new InternetAddress[new ArrayList<InternetAddress>(recipients).size()]);
212 
213         if (recipientsArray.length > 0) {
214             this.sendEmail(recipientsArray, subject, message);
215         }
216 
217     }
218 
219     /**
220      * @deprecated use method with InetAddress[] addresses instead.
221      */
222     public void sendEmail(HashSet<String> addresses, String subject,
223                           String msgText) {
224 
225         if (null == addresses || 0 == addresses.size()) {
226             throw new IllegalArgumentException(
227                     "No addresses in recipients set.");
228         }
229 
230         try {
231 
232             ArrayList<InternetAddress> recipients = new ArrayList<InternetAddress>(
233                     addresses.size());
234 
235             for (String address : addresses) {
236                 recipients.add(new InternetAddress(address));
237             }
238 
239             sendEmail(recipients.toArray(new InternetAddress[recipients.size()]), subject,
240                     msgText);
241         } catch (AddressException ex) {
242             logger.warn("AddressException while sending email.", ex);
243         }
244     }
245 
246     /**
247      * @param address
248      * @param subject
249      * @param msgText
250      */
251     public void sendEmail(InternetAddress address, String subject,
252                           String msgText) {
253         this.sendEmail(new InternetAddress[]{address}, subject, msgText);
254     }
255 
256     /**
257      * @param recipients
258      * @param subject
259      * @param msgText
260      */
261     public void sendEmail(InternetAddress[] recipients, String subject,
262                           String msgText) {
263         try {
264             if (logger.isDebugEnabled()) {
265                 logger.debug("sendEmail: called with recipients: " + Arrays.asList(recipients) + ", subject: " + subject + ", msgText: " + subject);
266             }
267             if (null == this.session) {
268                 throw new IllegalStateException("session was not initialized.");
269             }
270             if (null == recipients || recipients.length < 1) {
271                 throw new IllegalArgumentException(
272                         "at least one recipient must be specified.");
273             }
274             if (null == subject || subject.length() < 1) {
275                 throw new IllegalArgumentException("subject must be specified.");
276             }
277             if (null == msgText) {
278                 msgText = "Empty message";
279             }
280 
281             MimeMessage msg = new MimeMessage(this.session);
282 
283             if (null != this.from) {
284                 msg.setFrom(this.from);
285             }
286             if (null != this.replyTo) {
287                 msg.setReplyTo(new InternetAddress[]{this.replyTo});
288             }
289             for (InternetAddress internetAddress : recipients) {
290                 try {
291                     internetAddress.setPersonal(internetAddress.getPersonal(), readSmtpCharset(session));
292                 } catch (UnsupportedEncodingException e) {
293                     logger.info("sendEmail: could not encode " + internetAddress + " using " + readSmtpCharset(session));
294                 }
295             }
296             msg.setRecipients(javax.mail.Message.RecipientType.TO, recipients);
297             msg.setSubject(subject, readSmtpCharset(session));
298 
299             msg.setSentDate(new Date());
300 
301             msg.setContent(msgText, "text/plain; charset=\""
302                     + readSmtpCharset(session) + "\"");
303 
304             Transport.send(msg);
305 
306         } catch (MessagingException me) {
307             logger.warn("MessagingException while sending email, caught.", me);
308         }
309     }
310 
311     private String readSmtpCharset(Session session) {
312         String charset = null == session ? null : session.getProperty("mail.mime.charset");
313         if (null == charset) {
314             charset = configurationService.getProperty(
315                     "notification_smtp_charset", DEFAULT_SMTP_CHARSET);
316         }
317         return charset;
318     }
319 }