View Javadoc

1   package org.sourceforge.vlibrary.user.workers;
2   
3   import java.util.Properties;
4   
5   import javax.mail.Message;
6   import javax.mail.MessagingException;
7   import javax.mail.Session;
8   import javax.mail.internet.InternetAddress;
9   import javax.mail.internet.MimeMessage;
10  
11  import com.sun.mail.smtp.SMTPTransport;
12  
13  import org.apache.log4j.Logger;
14  import org.springframework.mail.MailException;
15  import org.springframework.mail.MailSendException;
16  import org.springframework.mail.SimpleMailMessage;
17  
18  /**
19   * Javamail-based {@link MailSender} implementation. 
20   * The mail session is lazy initialized and reinitialized when properties
21   * are changed. 
22   * 
23   * @version $Revision$ $Date$
24   *
25   */
26  public class MailSenderImpl implements MailSender {
27  
28      private Session session = null;
29      private volatile boolean initNeeded = true;
30      private String password = null;
31      private String user = null;
32      private int port = 25;
33      private String host = "localhost";
34      private boolean tls = false;
35      private boolean authenticated = false;
36      
37      private static Logger logger =
38          Logger.getLogger(MailSenderImpl.class.getName());
39      
40      public synchronized boolean isTls() {
41          return tls;
42      }
43      
44      public synchronized void setTls(boolean tls) {
45          this.tls = tls;
46          initNeeded = true;
47      }
48      
49      public synchronized boolean isAuthenticated() {
50          return authenticated;
51      }
52      
53      public synchronized void setAuthenticated(boolean authenticated) {
54          this.authenticated = authenticated;
55          initNeeded = true;
56      }
57      
58      
59      public synchronized String getPassword() {
60          return password;
61      }
62     
63      public synchronized void setPassword(String password) {
64          this.password = password;
65          initNeeded = true;
66      }
67    
68      public synchronized String getUser() {
69          return user;
70      }
71     
72      public synchronized void setUser(String user) {
73          this.user = user;
74          initNeeded = true;
75      }
76      
77      /**
78       * @inheritDoc
79       * <p/>
80       * Creates a session using currently defined properties if one does not
81       * already exist and reinitializes the session if properties have changed.
82       */
83      public synchronized Session getSession() {
84          if (logger.isDebugEnabled()) {
85              logger.debug("Entering");
86          }
87          if (initNeeded) {
88              if (logger.isDebugEnabled()) {
89                  logger.debug("Initializing mail session");
90              }
91              Properties props = new Properties();                
92              if (isTls()) {
93                  props.put("mail.smtp.starttls.enable","true"); 
94                  props.put("mail.smtps.host", getHost()); 
95                  props.put("mail.transport.protocol", "smtps"); 
96                  props.put("mail.smtps.port", Integer.toString(getPort()));
97                  props.put("mail.smtp.socketFactory.port", 
98                          Integer.toString(getPort()));
99                  props.put("mail.smtp.socketFactory.class",
100                         "javax.net.ssl.SSLSocketFactory");
101                 props.put("mail.smtp.socketFactory.fallback", "false");
102             } else {
103                 props.put("mail.transport.protocol", "smtp");
104                 props.put("mail.smtp.host", getHost());
105                 props.put("mail.smtp.port", Integer.toString(getPort()));
106                 if (logger.isDebugEnabled()) {
107                     logger.debug("Set mail session properties "
108                             + props.toString());
109                 }
110             }
111               
112             if (isAuthenticated()) {
113                 props.put("mail.smtp.auth", "true");
114                 props.put("mail.smtps.auth", "true");
115             }
116             if (logger.isDebugEnabled()) {
117                 logger.debug("Creating mail session with properties "
118                         + props.toString());
119             }
120             session = Session.getInstance(props);
121             //session.setDebug(true);
122             initNeeded = false;
123             if (logger.isDebugEnabled()) {
124                 logger.debug("Returning mail session with properties "
125                         + session.getProperties().toString());
126             }
127             return session; 
128             
129         } else {
130             if (logger.isDebugEnabled()) {
131                 logger.debug("Returning previously initialized session");
132             }
133             return this.session;
134         }
135     }
136     
137     /**
138      * @inheritDoc
139      * <p/>
140      * Examines incoming session properties and sets <code>authenticated,
141      * tls, host</code> and <code>port</code> bean properties accordingly.
142      */
143     public synchronized void setSession(Session session) {
144         this.session = session;
145         
146         Properties props = session.getProperties();
147         
148         if (props.containsKey("mail.smtp.auth")) {
149            authenticated = Boolean.parseBoolean(
150                    (String) props.getProperty("mail.smtp.auth"));
151         }
152         if (props.containsKey("mail.smtps.auth")) {
153             authenticated = Boolean.parseBoolean(
154                     (String) props.getProperty("mail.smtps.auth"));
155         }
156         
157         tls = (props.getProperty("mail.transport.protocol", "false") ==
158             "smtps");
159         
160         if (props.containsKey("mail.smtps.host")) {
161             host = props.getProperty("mail.smtps.host");
162         }
163         if (props.containsKey("mail.smtp.host")) {
164             host = props.getProperty("mail.smtp.host");
165         }
166         
167         if (props.containsKey("mail.smtp.socketFactory.port")) {
168             port = Integer.parseInt(
169                     props.getProperty("mail.smtp.socketFactory.port"));
170         }      
171         if (props.containsKey("mail.smtp.port")) {
172             port = Integer.parseInt(
173                     props.getProperty("mail.smtp.port"));
174         }    
175  
176     }
177     
178     public synchronized String getHost() {
179         return host;
180     }
181 
182     public synchronized void setHost(String host) {
183         this.host = host;
184         initNeeded = true;
185     }
186 
187     public synchronized int getPort() {
188         return port;
189     }
190 
191     public synchronized void setPort(int port) {
192         this.port = port;
193         initNeeded = true;
194     }
195     
196     public synchronized void send(SimpleMailMessage message)
197     throws MailException {
198         if (logger.isDebugEnabled()) {
199             logger.debug("Entering with message " + 
200                     message.toString());
201         }
202         session = getSession();
203         if (logger.isDebugEnabled()) {
204             logger.debug("Retrieved session with properties " +
205                     session.getProperties().toString());
206         }
207         try {
208             MimeMessage mimeMessage = new MimeMessage(session);
209             mimeMessage.setFrom(new InternetAddress(message.getFrom()));
210             String[] recipients = message.getTo();
211             for (int i = 0; i < recipients.length; i++) {
212                 mimeMessage.addRecipient(Message.RecipientType.TO,
213                         new InternetAddress(recipients[i]));
214             }
215             mimeMessage.setSubject(message.getSubject());
216             mimeMessage.setText(message.getText());
217             mimeMessage.saveChanges();
218             
219             if (logger.isDebugEnabled()) {
220                 String recips = "";
221                 javax.mail.Address[] addresses = mimeMessage.getAllRecipients();
222                 for (int i = 0; i < addresses.length; i++) {
223                     recips += addresses[i].toString();
224                 }
225                 logger.debug("Created MimeMessage " +
226                         "from: " + mimeMessage.getFrom().toString() + "\n" +
227                         "to: " + recips + "\n" + 
228                         "subject: " + mimeMessage.getSubject() +
229                         "content hash: " + mimeMessage.getContentMD5());
230             }
231             
232             SMTPTransport transport =
233                 (SMTPTransport)session.getTransport(
234                         isTls() ? "smtps" : "smtp");
235             try {
236                 if (isAuthenticated()) {
237                     transport.connect(getHost(), getUser(), getPassword());
238                 } else {
239                     transport.connect();
240                 }
241                 if (logger.isDebugEnabled()) {
242                     logger.debug("Connected to transport: " +
243                             transport.toString());
244                 }
245                 mimeMessage.saveChanges();
246                 transport.sendMessage(mimeMessage,
247                         mimeMessage.getAllRecipients());
248                 if (logger.isDebugEnabled()) {
249                     logger.debug("Sent message.");
250                 }
251             } finally {
252                 transport.close();
253                 if (logger.isDebugEnabled()) {
254                     logger.debug("Closed transport.");
255                 }
256             } 
257             
258         } catch (MessagingException ex) {
259             logger.error(ex);
260             throw new MailSendException(ex.getMessage(), ex);
261         }
262     }
263    
264     /**
265      * @inheritDoc
266      * <p/>
267      * This implementation does not attempt to maintain transaction integrity
268      * over the message set or to catch and rethrow exceptions, so the first
269      * failed send will throw a MailException and no further messages will
270      * be processed.
271      */
272     public synchronized void send(SimpleMailMessage[] messages)
273     throws MailException {
274         for (int i = 0; i < messages.length; i++) {
275             send(messages[i]);
276         }
277     }
278 }