1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
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
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
183 initFrom(fromAddress, fromText);
184 }
185 initReplyTo(replyToAddress, fromText);
186
187
188 }
189
190
191
192
193
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
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
248
249
250
251 public void sendEmail(InternetAddress address, String subject,
252 String msgText) {
253 this.sendEmail(new InternetAddress[]{address}, subject, msgText);
254 }
255
256
257
258
259
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 }