DefaultEmailService.java

  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. package org.itracker.services.implementations;

  19. import org.apache.log4j.Logger;
  20. import org.itracker.services.ConfigurationService;
  21. import org.itracker.services.EmailService;
  22. import org.itracker.util.EmailAuthenticator;
  23. import org.itracker.util.NamingUtilites;

  24. import javax.mail.*;
  25. import javax.mail.internet.AddressException;
  26. import javax.mail.internet.InternetAddress;
  27. import javax.mail.internet.MimeMessage;
  28. import javax.naming.InitialContext;
  29. import javax.naming.NamingException;
  30. import java.io.UnsupportedEncodingException;
  31. import java.util.*;

  32. public class DefaultEmailService implements EmailService {

  33.     private ConfigurationService configurationService;

  34.     @Deprecated
  35.     public static final String DEFAULT_FROM_ADDRESS = "itracker@localhost";
  36.     @Deprecated
  37.     public static final String DEFAULT_FROM_TEXT = "ITracker Notification System";
  38.     @Deprecated
  39.     public static final String DEFAULT_REPLYTO_ADDRESS = "itracker@localhost";
  40.     @Deprecated
  41.     public static final String DEFAULT_SMTP_HOST = "localhost";

  42.     public static final String DEFAULT_SMTP_CHARSET = "ISO-8859-1";


  43.     private Session session;

  44.     private final Logger logger = Logger.getLogger(DefaultEmailService.class);
  45.     private InternetAddress replyTo;
  46.     private InternetAddress from;

  47.     public void setConfigurationService(
  48.             ConfigurationService configurationService) {
  49.         if (null == configurationService) {
  50.             throw new IllegalArgumentException("configuration service must not be null.");
  51.         }
  52.         if (null != this.configurationService) {
  53.             throw new IllegalStateException("configuration service was already set.");
  54.         }
  55.         this.configurationService = configurationService;
  56.     }

  57.     /**
  58.      * @deprecated use mailssession from JNDI instead
  59.      */
  60.     private void initMailsession(String smtpHost, String smtpUserid, String smtpPassword) {
  61.         Authenticator smtpAuth = null;
  62.         Properties props = new Properties();
  63.         props.put("mail.smtp.host", smtpHost);
  64.         // props.put("mail.mime.charset", this.smtpCharset);

  65.         if (smtpUserid != null && smtpPassword != null) {
  66.             smtpAuth = new EmailAuthenticator(
  67.                     new PasswordAuthentication(smtpUserid,
  68.                             smtpPassword));
  69.         }
  70.         this.session = Session.getInstance(props, smtpAuth);
  71.     }

  72.     private void initCharset(String smtpCharset) {
  73.         if (null != smtpCharset) {
  74.             try {
  75.                 new String(new byte[0], smtpCharset);
  76.                 this.session.getProperties().put("mail.mime.charset",
  77.                         smtpCharset);
  78.                 logger.info("initCharset: cherset was initialized to "
  79.                         + session.getProperty("mail.mime.charset"));
  80.             } catch (UnsupportedEncodingException use) {
  81.                 logger
  82.                         .warn(
  83.                                 "initCharset: unsupported smtp charset configured, ignoring",
  84.                                 use);
  85.             }
  86.         }
  87.     }

  88.     private void initFrom(String fromAddress, String fromText) {
  89.         if (null != fromAddress) {
  90.             try {
  91.                 this.from = new InternetAddress(fromAddress, fromText, readSmtpCharset(this.session));
  92.                 logger.info("initFrom: initialized from-address: " + this.from);
  93.             } catch (UnsupportedEncodingException e) {
  94.                 logger.warn("initReplyTo: could not initialize reply-to (configured: " +
  95.                         fromText + " <" + fromAddress + ">", e);
  96.             }
  97.         }
  98.     }

  99.     private void initReplyTo(String replyToAddress, String replyToText) {
  100.         try {
  101.             this.replyTo = new InternetAddress(replyToAddress, replyToText, readSmtpCharset(this.session));
  102.             logger.info("initFrom: initialized reply-to: " + this.replyTo);
  103.         } catch (UnsupportedEncodingException e) {
  104.             logger.warn("initReplyTo: could not initialize reply-to (configured: " + replyToText + " <" + replyToAddress + ">", e);
  105.         }
  106.     }


  107.     public void init() {

  108.         if (this.configurationService == null) {
  109.             throw new IllegalStateException("configuration service was not set.");
  110.         }

  111.         String fromAddress = configurationService.getProperty(
  112.                 "notification_from_address", DEFAULT_FROM_ADDRESS);
  113.         String fromText = configurationService.getProperty("notification_from_text",
  114.                 DEFAULT_FROM_TEXT);
  115.         String replyToAddress = configurationService.getProperty(
  116.                 "notification_replyto_address", DEFAULT_REPLYTO_ADDRESS);

  117.         String smtpCharset = configurationService.getProperty(
  118.                 "notification_smtp_charset", DEFAULT_SMTP_CHARSET);

  119.         String mailSessionLookupName = configurationService.getMailSessionLookupName();

  120.         try {
  121.             InitialContext ctx = new InitialContext();
  122.             logger.debug("init: got Mailsession from Naming Context:" + NamingUtilites.lookup(ctx, mailSessionLookupName));


  123.             this.session = (Session) NamingUtilites.lookup(ctx, mailSessionLookupName);
  124.         } catch (NamingException e) {
  125.             logger.warn("init: failed to get Mailsession from initial context.", e);
  126.         }
  127.         if (null == this.session) {
  128.             logger
  129.                     .warn("init: failed to lookup Session from JNDI lookup " + mailSessionLookupName + ", using manual session");
  130.             String smtpHost = configurationService.getProperty(
  131.                     "notification_smtp_host", DEFAULT_SMTP_HOST);
  132.             String smtpUserid = configurationService.getProperty(
  133.                     "notification_smtp_userid", null);
  134.             String smtpPassword = configurationService.getProperty(
  135.                     "notification_smtp_password", null);

  136.             logger
  137.                     .warn("init: setting up SMTP manually, no session-lookup found in configuration!");
  138.             if ("".equals(smtpUserid) || "".equals(smtpPassword)) {
  139.                 smtpUserid = null;
  140.                 smtpPassword = null;
  141.             }
  142.             initMailsession(smtpHost, smtpUserid, smtpPassword);
  143.             initCharset(smtpCharset);
  144.             initFrom(fromAddress, fromText);

  145.             if (logger.isDebugEnabled()) {
  146.                 logger.debug("init: From Address set to: " + fromAddress);
  147.                 logger.debug("init: From Text set to: " + fromText);
  148.                 logger.debug("init: ReplyTo Address set to: " + replyToAddress);
  149.                 logger.debug("init: SMTP server set to: " + smtpHost);
  150.                 logger.debug("init: SMTP userid set to: " + smtpUserid);
  151.                 logger.debug("init: SMTP password set to: " + smtpPassword);
  152.             }
  153.         } else {
  154.             initCharset(smtpCharset);
  155.             // use mailsession to initialize from.
  156.             initFrom(fromAddress, fromText);
  157.         }
  158.         initReplyTo(replyToAddress, fromText);


  159.     }

  160.     /**
  161.      * @param address
  162.      * @param subject
  163.      * @param msgText
  164.      */
  165.     public void sendEmail(String address, String subject, String msgText) {
  166.         try {
  167.             InternetAddress[] recipients = new InternetAddress[1];
  168.             recipients[0] = new InternetAddress(address);

  169.             sendEmail(recipients, subject, msgText);
  170.         } catch (AddressException ex) {
  171.             logger.warn(
  172.                     "AddressException while sending email. caught. address was "
  173.                             + address, ex);
  174.         }
  175.     }

  176.     public void sendEmail(Set<InternetAddress> recipients, String subject,
  177.                           String message) {

  178.         InternetAddress[] recipientsArray = new ArrayList<InternetAddress>(recipients).toArray(new InternetAddress[new ArrayList<InternetAddress>(recipients).size()]);

  179.         if (recipientsArray.length > 0) {
  180.             this.sendEmail(recipientsArray, subject, message);
  181.         }

  182.     }

  183.     /**
  184.      * @deprecated use method with InetAddress[] addresses instead.
  185.      */
  186.     public void sendEmail(HashSet<String> addresses, String subject,
  187.                           String msgText) {

  188.         if (null == addresses || 0 == addresses.size()) {
  189.             throw new IllegalArgumentException(
  190.                     "No addresses in recipients set.");
  191.         }

  192.         try {

  193.             ArrayList<InternetAddress> recipients = new ArrayList<InternetAddress>(
  194.                     addresses.size());

  195.             for (String address : addresses) {
  196.                 recipients.add(new InternetAddress(address));
  197.             }

  198.             sendEmail(recipients.toArray(new InternetAddress[recipients.size()]), subject,
  199.                     msgText);
  200.         } catch (AddressException ex) {
  201.             logger.warn("AddressException while sending email.", ex);
  202.         }
  203.     }

  204.     /**
  205.      * @param address
  206.      * @param subject
  207.      * @param msgText
  208.      */
  209.     public void sendEmail(InternetAddress address, String subject,
  210.                           String msgText) {
  211.         this.sendEmail(new InternetAddress[]{address}, subject, msgText);
  212.     }

  213.     /**
  214.      * @param recipients
  215.      * @param subject
  216.      * @param msgText
  217.      */
  218.     public void sendEmail(InternetAddress[] recipients, String subject,
  219.                           String msgText) {
  220.         try {
  221.             if (logger.isDebugEnabled()) {
  222.                 logger.debug("sendEmail: called with recipients: " + Arrays.asList(recipients) + ", subject: " + subject + ", msgText: " + subject);
  223.             }
  224.             if (null == this.session) {
  225.                 throw new IllegalStateException("session was not initialized.");
  226.             }
  227.             if (null == recipients || recipients.length < 1) {
  228.                 throw new IllegalArgumentException(
  229.                         "at least one recipient must be specified.");
  230.             }
  231.             if (null == subject || subject.length() < 1) {
  232.                 throw new IllegalArgumentException("subject must be specified.");
  233.             }
  234.             if (null == msgText) {
  235.                 msgText = "Empty message";
  236.             }

  237.             MimeMessage msg = new MimeMessage(this.session);

  238.             if (null != this.from) {
  239.                 msg.setFrom(this.from);
  240.             }
  241.             if (null != this.replyTo) {
  242.                 msg.setReplyTo(new InternetAddress[]{this.replyTo});
  243.             }
  244.             for (InternetAddress internetAddress : recipients) {
  245.                 try {
  246.                     internetAddress.setPersonal(internetAddress.getPersonal(), readSmtpCharset(session));
  247.                 } catch (UnsupportedEncodingException e) {
  248.                     logger.info("sendEmail: could not encode " + internetAddress + " using " + readSmtpCharset(session));
  249.                 }
  250.             }
  251.             msg.setRecipients(javax.mail.Message.RecipientType.TO, recipients);
  252.             msg.setSubject(subject, readSmtpCharset(session));

  253.             msg.setSentDate(new Date());

  254.             msg.setContent(msgText, "text/plain; charset=\""
  255.                     + readSmtpCharset(session) + "\"");

  256.             Transport.send(msg);

  257.         } catch (MessagingException me) {
  258.             logger.warn("MessagingException while sending email, caught.", me);
  259.         }
  260.     }

  261.     private String readSmtpCharset(Session session) {
  262.         String charset = null == session ? null : session.getProperty("mail.mime.charset");
  263.         if (null == charset) {
  264.             charset = configurationService.getProperty(
  265.                     "notification_smtp_charset", DEFAULT_SMTP_CHARSET);
  266.         }
  267.         return charset;
  268.     }
  269. }