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.util;
20  
21  import java.io.UnsupportedEncodingException;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.Date;
25  import java.util.HashSet;
26  import java.util.Iterator;
27  import java.util.Properties;
28  import java.util.Set;
29  
30  import javax.mail.Authenticator;
31  import javax.mail.MessagingException;
32  import javax.mail.PasswordAuthentication;
33  import javax.mail.Session;
34  import javax.mail.Transport;
35  import javax.mail.internet.AddressException;
36  import javax.mail.internet.InternetAddress;
37  import javax.mail.internet.MimeMessage;
38  import javax.naming.InitialContext;
39  import javax.naming.NamingException;
40  
41  import org.apache.log4j.Logger;
42  import org.itracker.services.ConfigurationService;
43  
44  public class EmailService {
45  
46  	private ConfigurationService configurationService;
47  	
48  	@Deprecated
49  	public static final String DEFAULT_FROM_ADDRESS = "itracker@localhost";
50  	@Deprecated
51  	public static final String DEFAULT_FROM_TEXT = "ITracker Notification System";
52  	@Deprecated
53  	public static final String DEFAULT_REPLYTO_ADDRESS = "itracker@localhost";
54  	@Deprecated
55  	public static final String DEFAULT_SMTP_HOST = "localhost";
56  
57  	public static final String DEFAULT_SMTP_CHARSET = "ISO-8859-1";
58  
59  
60  
61  	private Session session;
62  
63  	private final Logger logger = Logger.getLogger(EmailService.class);
64  	private InternetAddress replyTo;
65  	private InternetAddress from;
66  
67  	public void setConfigurationService(
68  			ConfigurationService configurationService) {
69  		if (null == configurationService) {
70  			throw new IllegalArgumentException("configuration service must not be null.");
71  		}
72  		if (null != this.configurationService) {
73  			throw new IllegalStateException("configuration service was already set.");
74  		}
75  		this.configurationService = configurationService;
76  	}
77  	/**
78  	 * @deprecated use mailssession from JNDI instead
79  	 */
80  	private void initMailsession(String smtpHost, String smtpUserid, String smtpPassword) {
81  		Authenticator smtpAuth = null;
82  		Properties props = new Properties();
83  		props.put("mail.smtp.host", smtpHost);
84  		// props.put("mail.mime.charset", this.smtpCharset);
85  
86  		if (smtpUserid != null && smtpPassword != null) {
87  			smtpAuth = (Authenticator) new EmailAuthenticator(
88  					new PasswordAuthentication(smtpUserid,
89  							smtpPassword));
90  		}
91  		this.session = Session.getInstance(props, smtpAuth);
92  	}
93  
94  	private final void initCharset(String smtpCharset) {
95  		if (null != smtpCharset) {
96  			try {
97  				new String(new byte[0], smtpCharset);
98  				this.session.getProperties().put("mail.mime.charset",
99  						smtpCharset);
100 				logger.info("initCharset: cherset was initialized to "
101 						+ session.getProperty("mail.mime.charset"));
102 			} catch (UnsupportedEncodingException use) {
103 				logger
104 						.warn(
105 								"initCharset: unsupported smtp charset configured, ignoring",
106 								use);
107 			}
108 		}
109 	}
110 
111 	private final void initFrom(String fromAddress, String fromText) {
112 		if (null != fromAddress) {
113 			try {
114 				this.from = new InternetAddress(fromAddress, fromText, readSmtpCharset(this.session));
115 				logger.info("initFrom: initialized from-address: " + this.from);
116 			} catch (UnsupportedEncodingException e) {
117 				logger.warn("initReplyTo: could not initialize reply-to (configured: " + 
118 						fromText + " <" + fromAddress + ">" , e);
119 			}
120 		}
121 	}
122 
123 	private final void initReplyTo(String replyToAddress, String replyToText) {
124 		try {
125 			this.replyTo = new InternetAddress(replyToAddress, replyToText, readSmtpCharset(this.session));
126 			logger.info("initFrom: initialized reply-to: " + this.replyTo);
127 		} catch (UnsupportedEncodingException e) {
128 			logger.warn("initReplyTo: could not initialize reply-to (configured: " + replyToText + " <" + replyToAddress + ">" , e);
129 		}
130 	}
131 
132 	
133 	
134 	public void init() {
135 
136 		if (this.configurationService == null) {
137 			throw new IllegalStateException("configuration service was not set.");
138 		}
139 		
140 		String fromAddress = configurationService.getProperty(
141 				"notification_from_address", DEFAULT_FROM_ADDRESS);
142 		String fromText = configurationService.getProperty("notification_from_text",
143 				DEFAULT_FROM_TEXT);
144 		String replyToAddress = configurationService.getProperty(
145 				"notification_replyto_address", DEFAULT_REPLYTO_ADDRESS);
146 
147 		String smtpCharset = configurationService.getProperty(
148 				"notification_smtp_charset", DEFAULT_SMTP_CHARSET);
149 
150 		String mailSessionLookupName = configurationService.getProperty(
151 				"mail_session_jndi_lookup", "none");
152 
153 		logger
154 				.info("init: looking for Session in JNDI, lookup name from configuration: "
155 						+ mailSessionLookupName);
156 
157 		try {
158 			InitialContext ctx = new InitialContext();
159 			logger.debug("init: got Mailsession from Naming Context:" + NamingUtilites.lookup(ctx, mailSessionLookupName));
160 
161 		
162 			this.session = (Session) NamingUtilites.lookup(ctx, mailSessionLookupName);
163 		} catch (NamingException e) {
164 			logger.warn("init: failed to get Mailsession from initial context.", e);
165 		}
166 		if (null == this.session) {
167 			logger
168 					.warn("init: failed to lookup Session from JNDI lookup " + mailSessionLookupName + ", using manual session");
169 			String smtpHost = configurationService.getProperty(
170 					"notification_smtp_host", DEFAULT_SMTP_HOST);
171 			String smtpUserid = configurationService.getProperty(
172 					"notification_smtp_userid", null);
173 			String smtpPassword = configurationService.getProperty(
174 					"notification_smtp_password", null);
175 
176 			logger
177 					.warn("init: setting up SMTP manually, no session-lookup found in configuration!");
178 			if ("".equals(smtpUserid) || "".equals(smtpPassword)) {
179 				smtpUserid = null;
180 				smtpPassword = null;
181 			}
182 			initMailsession(smtpHost, smtpUserid, smtpPassword);
183 			initCharset(smtpCharset);
184 			initFrom(fromAddress, fromText);
185 
186 			if (logger.isDebugEnabled()) {
187 				logger.debug("init: From Address set to: " + fromAddress);
188 				logger.debug("init: From Text set to: " + fromText);
189 				logger.debug("init: ReplyTo Address set to: " + replyToAddress);
190 				logger.debug("init: SMTP server set to: " + smtpHost);
191 				logger.debug("init: SMTP userid set to: " + smtpUserid);
192 				logger.debug("init: SMTP password set to: " + smtpPassword);
193 			}
194 		} else {
195 			initCharset(smtpCharset);
196 			// use mailsession to initialize from.
197 			initFrom(fromAddress, fromText);
198 		}
199 		initReplyTo(replyToAddress, fromText);
200 		
201 
202 	}
203 
204 	/**
205 	 * 
206 	 * @param address
207 	 * @param subject
208 	 * @param msgText
209 	 */
210 	public void sendEmail(String address, String subject, String msgText) {
211 		try {
212 			InternetAddress[] recipients = new InternetAddress[1];
213 			recipients[0] = new InternetAddress(address);
214 
215 			sendEmail(recipients, subject, msgText);
216 		} catch (AddressException ex) {
217 			logger.warn(
218 					"AddressException while sending email. caught. address was "
219 							+ address, ex);
220 		}
221 	}
222 
223 	public void sendEmail(Set<InternetAddress> recipients, String subject,
224 			String message) {
225 		
226 		InternetAddress[] recipientsArray = new ArrayList<InternetAddress>(recipients).toArray(new InternetAddress[]{});
227 
228 		if (recipientsArray.length > 0) {
229 			this.sendEmail(recipientsArray, subject, message);
230 		}
231 
232 	}
233 
234 	/**
235 	 * @deprecated use method with InetAddress[] addresses instead.
236 	 * @param addresses
237 	 * @param subject
238 	 * @param msgText
239 	 */
240 	public void sendEmail(HashSet<String> addresses, String subject,
241 			String msgText) {
242 
243 		if (null == addresses || 0 == addresses.size()) {
244 			throw new IllegalArgumentException(
245 					"No addresses in recipients set.");
246 		}
247 
248 		try {
249 
250 			ArrayList<InternetAddress> recipients = new ArrayList<InternetAddress>(
251 					addresses.size());
252 
253 			Iterator<String> iterator = addresses.iterator();
254 			while (iterator.hasNext()) {
255 				recipients.add(new InternetAddress((String) iterator.next()));
256 			}
257 
258 			sendEmail(recipients.toArray(new InternetAddress[0]), subject,
259 					msgText);
260 		} catch (AddressException ex) {
261 			logger.warn("AddressException while sending email.", ex);
262 		}
263 	}
264 
265 	/**
266 	 * 
267 	 * @param address
268 	 * @param subject
269 	 * @param msgText
270 	 */
271 	public void sendEmail(InternetAddress address, String subject,
272 			String msgText) {
273 		this.sendEmail(new InternetAddress[] { address }, subject, msgText);
274 	}
275 
276 	/**
277 	 * 
278 	 * @param recipients
279 	 * @param subject
280 	 * @param msgText
281 	 */
282 	public void sendEmail(InternetAddress[] recipients, String subject,
283 			String msgText) {
284 		try {
285 			if (logger.isDebugEnabled()) {
286 				logger.debug("sendEmail: called with recipients: " + Arrays.asList(recipients) + ", subject: " + subject + ", msgText: " + subject);
287 			}
288 			if (null == this.session) {
289 				throw new IllegalStateException("session was not initialized.");
290 			}
291 			if (null == recipients || recipients.length < 1) {
292 				throw new IllegalArgumentException(
293 						"at least one recipient must be specified.");
294 			}
295 			if (null == subject || subject.length() < 1) {
296 				throw new IllegalArgumentException("subject must be specified.");
297 			}
298 			if (null == msgText) {
299 				msgText = "Empty message";
300 			}
301 
302 			MimeMessage msg = new MimeMessage(this.session);
303 
304 			if(null != this.from ){
305 				msg.setFrom(this.from);
306 			}
307 			if (null != this.replyTo) {
308 				msg.setReplyTo(new InternetAddress[] { this.replyTo });
309 			}
310             for (InternetAddress internetAddress: recipients) {
311                 try {
312                     internetAddress.setPersonal(internetAddress.getPersonal(), readSmtpCharset(session));
313                 } catch (UnsupportedEncodingException e) {
314                     logger.info("sendEmail: could not encode " + internetAddress + " using " + readSmtpCharset(session));
315                 }
316             }
317 			msg.setRecipients(javax.mail.Message.RecipientType.TO, recipients);
318 			msg.setSubject(subject, readSmtpCharset(session));
319 
320 			msg.setSentDate(new Date());
321 
322 			// really needed?
323 			//msg.setHeader("Content-Transfer-Encoding", "quoted-printable");
324 			msg.setContent(msgText.toString(), "text/plain; charset=\""
325 					+ readSmtpCharset(session) + "\"");
326 
327 			Transport.send(msg);
328 
329 		} catch (MessagingException me) {
330 			logger.warn("MessagingException while sending email, caught.", me);
331 		}
332 	}
333 
334     private String readSmtpCharset(Session session) {
335         String charset = null==session?null:session.getProperty("mail.mime.charset");
336         if (null == charset) {
337             charset = configurationService.getProperty(
338 				"notification_smtp_charset", DEFAULT_SMTP_CHARSET);
339         }
340         return charset;
341     }
342 }