KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > mail > javamail > JavaMailSenderImpl


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.mail.javamail;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Date JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 import javax.activation.FileTypeMap JavaDoc;
29 import javax.mail.AuthenticationFailedException JavaDoc;
30 import javax.mail.MessagingException JavaDoc;
31 import javax.mail.NoSuchProviderException JavaDoc;
32 import javax.mail.Session JavaDoc;
33 import javax.mail.Transport JavaDoc;
34 import javax.mail.internet.MimeMessage JavaDoc;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38
39 import org.springframework.mail.MailAuthenticationException;
40 import org.springframework.mail.MailException;
41 import org.springframework.mail.MailParseException;
42 import org.springframework.mail.MailPreparationException;
43 import org.springframework.mail.MailSendException;
44 import org.springframework.mail.SimpleMailMessage;
45 import org.springframework.util.Assert;
46
47 /**
48  * Production implementation of the {@link JavaMailSender} interface,
49  * supporting both JavaMail {@link MimeMessage MimeMessages} and Spring
50  * {@link SimpleMailMessage SimpleMailMessages}. Can also be used as a
51  * plain {@link org.springframework.mail.MailSender} implementation.
52  *
53  * <p>Allows for defining all settings locally as bean properties.
54  * Alternatively, a pre-configured JavaMail {@link javax.mail.Session} can be
55  * specified, possibly pulled from an application server's JNDI environment.
56  *
57  * <p>Non-default properties in this object will always override the settings
58  * in the JavaMail <code>Session</code>. Note that if overriding all values locally,
59  * there is no added value in setting a pre-configured <code>Session</code>.
60  *
61  * @author Dmitriy Kopylenko
62  * @author Juergen Hoeller
63  * @since 10.09.2003
64  * @see javax.mail.internet.MimeMessage
65  * @see javax.mail.Session
66  * @see #setSession
67  * @see #setJavaMailProperties
68  * @see #setHost
69  * @see #setPort
70  * @see #setUsername
71  * @see #setPassword
72  */

73 public class JavaMailSenderImpl implements JavaMailSender {
74
75     /**
76      * The default protocol: 'smtp'.
77      */

78     public static final String JavaDoc DEFAULT_PROTOCOL = "smtp";
79
80     /**
81      * The default port: -1.
82      */

83     public static final int DEFAULT_PORT = -1;
84
85     /** Logger available to subclasses */
86     protected final Log logger = LogFactory.getLog(getClass());
87
88     private Session JavaDoc session = Session.getInstance(new Properties JavaDoc(), null);
89
90     private String JavaDoc protocol = DEFAULT_PROTOCOL;
91
92     private String JavaDoc host;
93
94     private int port = DEFAULT_PORT;
95
96     private String JavaDoc username;
97
98     private String JavaDoc password;
99
100     private String JavaDoc defaultEncoding;
101
102     private FileTypeMap JavaDoc defaultFileTypeMap;
103
104
105     /**
106      * Create a new instance of the <code>JavaMailSenderImpl</code> class.
107      * <p>Initializes the {@link #setDefaultFileTypeMap "defaultFileTypeMap"}
108      * property with a default {@link ConfigurableMimeFileTypeMap}.
109      */

110     public JavaMailSenderImpl() {
111         ConfigurableMimeFileTypeMap fileTypeMap = new ConfigurableMimeFileTypeMap();
112         fileTypeMap.afterPropertiesSet();
113         this.defaultFileTypeMap = fileTypeMap;
114     }
115
116     /**
117      * Set JavaMail properties for the <code>Session</code>.
118      * <p>A new <code>Session</code> will be created with those properties.
119      * Use either this method or {@link #setSession}, but not both.
120      * <p>Non-default properties in this instance will override given
121      * JavaMail properties.
122      */

123     public void setJavaMailProperties(Properties JavaDoc javaMailProperties) {
124         this.session = Session.getInstance(javaMailProperties, null);
125     }
126
127     /**
128      * Set the JavaMail <code>Session</code>, possibly pulled from JNDI.
129      * <p>Default is a new <code>Session</code> without defaults, that is
130      * completely configured via this instance's properties.
131      * <p>If using a pre-configured <code>Session</code>, non-default properties
132      * in this instance will override the settings in the <code>Session</code>.
133      * @see #setJavaMailProperties
134      */

135     public void setSession(Session JavaDoc session) {
136         Assert.notNull(session, "Session must not be null");
137         this.session = session;
138     }
139
140     /**
141      * Return the JavaMail <code>Session</code>.
142      */

143     public Session JavaDoc getSession() {
144         return this.session;
145     }
146
147     /**
148      * Set the mail protocol. Default is "smtp".
149      */

150     public void setProtocol(String JavaDoc protocol) {
151         this.protocol = protocol;
152     }
153
154     /**
155      * Return the mail protocol.
156      */

157     public String JavaDoc getProtocol() {
158         return this.protocol;
159     }
160
161     /**
162      * Set the mail server host, typically an SMTP host.
163      * <p>Default is the default host of the underlying JavaMail Session.
164      */

165     public void setHost(String JavaDoc host) {
166         this.host = host;
167     }
168
169     /**
170      * Return the mail server host.
171      */

172     public String JavaDoc getHost() {
173         return this.host;
174     }
175
176     /**
177      * Set the mail server port.
178      * <p>Default is {@link #DEFAULT_PORT}, letting JavaMail use the default
179      * SMTP port (25).
180     */

181     public void setPort(int port) {
182         this.port = port;
183     }
184
185     /**
186      * Return the mail server port.
187      */

188     public int getPort() {
189         return this.port;
190     }
191
192     /**
193      * Set the username for the account at the mail host, if any.
194      * <p>Note that the underlying JavaMail <code>Session</code> has to be
195      * configured with the property <code>"mail.smtp.auth"</code> set to
196      * <code>true</code>, else the specified username will not be sent to the
197      * mail server by the JavaMail runtime. If you are not explicitly passing
198      * in a <code>Session</code> to use, simply specify this setting via
199      * {@link #setJavaMailProperties}.
200      * @see #setSession
201      * @see #setPassword
202      */

203     public void setUsername(String JavaDoc username) {
204         this.username = username;
205     }
206
207     /**
208      * Return the username for the account at the mail host.
209      */

210     public String JavaDoc getUsername() {
211         return this.username;
212     }
213
214     /**
215      * Set the password for the account at the mail host, if any.
216      * <p>Note that the underlying JavaMail <code>Session</code> has to be
217      * configured with the property <code>"mail.smtp.auth"</code> set to
218      * <code>true</code>, else the specified password will not be sent to the
219      * mail server by the JavaMail runtime. If you are not explicitly passing
220      * in a <code>Session</code> to use, simply specify this setting via
221      * {@link #setJavaMailProperties}.
222      * @see #setSession
223      * @see #setUsername
224      */

225     public void setPassword(String JavaDoc password) {
226         this.password = password;
227     }
228
229     /**
230      * Return the password for the account at the mail host.
231      */

232     public String JavaDoc getPassword() {
233         return this.password;
234     }
235
236     /**
237      * Set the default encoding to use for {@link MimeMessage MimeMessages}
238      * created by this instance.
239      * <p>Such an encoding will be auto-detected by {@link MimeMessageHelper}.
240      */

241     public void setDefaultEncoding(String JavaDoc defaultEncoding) {
242         this.defaultEncoding = defaultEncoding;
243     }
244
245     /**
246      * Return the default encoding for {@link MimeMessage MimeMessages},
247      * or <code>null</code> if none.
248      */

249     public String JavaDoc getDefaultEncoding() {
250         return this.defaultEncoding;
251     }
252
253     /**
254      * Set the default Java Activation {@link FileTypeMap} to use for
255      * {@link MimeMessage MimeMessages} created by this instance.
256      * <p>A <code>FileTypeMap</code> specified here will be autodetected by
257      * {@link MimeMessageHelper}, avoiding the need to specify the
258      * <code>FileTypeMap</code> for each <code>MimeMessageHelper</code> instance.
259      * <p>For example, you can specify a custom instance of Spring's
260      * {@link ConfigurableMimeFileTypeMap} here. If not explicitly specified,
261      * a default <code>ConfigurableMimeFileTypeMap</code> will be used, containing
262      * an extended set of MIME type mappings (as defined by the
263      * <code>mime.types</code> file contained in the Spring jar).
264      * @see MimeMessageHelper#setFileTypeMap
265      */

266     public void setDefaultFileTypeMap(FileTypeMap JavaDoc defaultFileTypeMap) {
267         this.defaultFileTypeMap = defaultFileTypeMap;
268     }
269
270     /**
271      * Return the default Java Activation {@link FileTypeMap} for
272      * {@link MimeMessage MimeMessages}, or <code>null</code> if none.
273      */

274     public FileTypeMap JavaDoc getDefaultFileTypeMap() {
275         return this.defaultFileTypeMap;
276     }
277
278
279     //---------------------------------------------------------------------
280
// Implementation of MailSender
281
//---------------------------------------------------------------------
282

283     public void send(SimpleMailMessage simpleMessage) throws MailException {
284         send(new SimpleMailMessage[] { simpleMessage });
285     }
286
287     public void send(SimpleMailMessage[] simpleMessages) throws MailException {
288         List JavaDoc mimeMessages = new ArrayList JavaDoc(simpleMessages.length);
289         for (int i = 0; i < simpleMessages.length; i++) {
290             SimpleMailMessage simpleMessage = simpleMessages[i];
291             if (logger.isDebugEnabled()) {
292                 logger.debug("Creating new MIME message using the following mail properties: " + simpleMessage);
293             }
294             MimeMailMessage message = new MimeMailMessage(createMimeMessage());
295             simpleMessage.copyTo(message);
296             mimeMessages.add(message.getMimeMessage());
297         }
298         doSend((MimeMessage JavaDoc[]) mimeMessages.toArray(new MimeMessage JavaDoc[mimeMessages.size()]), simpleMessages);
299     }
300
301
302     //---------------------------------------------------------------------
303
// Implementation of JavaMailSender
304
//---------------------------------------------------------------------
305

306     /**
307      * This implementation creates a SmartMimeMessage, holding the specified
308      * default encoding and default FileTypeMap. This special defaults-carrying
309      * message will be autodetected by {@link MimeMessageHelper}, which will use
310      * the carried encoding and FileTypeMap unless explicitly overridden.
311      * @see #setDefaultEncoding
312      * @see #setDefaultFileTypeMap
313      */

314     public MimeMessage JavaDoc createMimeMessage() {
315         return new SmartMimeMessage(getSession(), getDefaultEncoding(), getDefaultFileTypeMap());
316     }
317
318     public MimeMessage JavaDoc createMimeMessage(InputStream JavaDoc contentStream) throws MailException {
319         try {
320             return new MimeMessage JavaDoc(getSession(), contentStream);
321         }
322         catch (MessagingException JavaDoc ex) {
323             throw new MailParseException("Could not parse raw MIME content", ex);
324         }
325     }
326
327     public void send(MimeMessage JavaDoc mimeMessage) throws MailException {
328         send(new MimeMessage JavaDoc[] { mimeMessage });
329     }
330
331     public void send(MimeMessage JavaDoc[] mimeMessages) throws MailException {
332         doSend(mimeMessages, null);
333     }
334
335     public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException {
336         send(new MimeMessagePreparator[] { mimeMessagePreparator });
337     }
338
339     public void send(MimeMessagePreparator[] mimeMessagePreparators) throws MailException {
340         try {
341             List JavaDoc mimeMessages = new ArrayList JavaDoc(mimeMessagePreparators.length);
342             for (int i = 0; i < mimeMessagePreparators.length; i++) {
343                 MimeMessage JavaDoc mimeMessage = createMimeMessage();
344                 mimeMessagePreparators[i].prepare(mimeMessage);
345                 mimeMessages.add(mimeMessage);
346             }
347             send((MimeMessage JavaDoc[]) mimeMessages.toArray(new MimeMessage JavaDoc[mimeMessages.size()]));
348         }
349         catch (MailException ex) {
350             throw ex;
351         }
352         catch (MessagingException JavaDoc ex) {
353             throw new MailParseException(ex);
354         }
355         catch (IOException JavaDoc ex) {
356             throw new MailPreparationException(ex);
357         }
358         catch (Exception JavaDoc ex) {
359             throw new MailPreparationException(ex);
360         }
361     }
362
363
364     /**
365      * Actually send the given array of MimeMessages via JavaMail.
366      * @param mimeMessages MimeMessage objects to send
367      * @param originalMessages corresponding original message objects
368      * that the MimeMessages have been created from (with same array
369      * length and indices as the "mimeMessages" array), if any
370      * @throws org.springframework.mail.MailAuthenticationException
371      * in case of authentication failure
372      * @throws org.springframework.mail.MailSendException
373      * in case of failure when sending a message
374      */

375     protected void doSend(MimeMessage JavaDoc[] mimeMessages, Object JavaDoc[] originalMessages) throws MailException {
376         Map JavaDoc failedMessages = new HashMap JavaDoc();
377         try {
378             Transport JavaDoc transport = getTransport(getSession());
379             transport.connect(getHost(), getPort(), getUsername(), getPassword());
380             try {
381                 for (int i = 0; i < mimeMessages.length; i++) {
382                     MimeMessage JavaDoc mimeMessage = mimeMessages[i];
383                     try {
384                         if (mimeMessage.getSentDate() == null) {
385                             mimeMessage.setSentDate(new Date JavaDoc());
386                         }
387                         mimeMessage.saveChanges();
388                         transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
389                     }
390                     catch (MessagingException JavaDoc ex) {
391                         Object JavaDoc original = (originalMessages != null ? originalMessages[i] : mimeMessage);
392                         failedMessages.put(original, ex);
393                     }
394                 }
395             }
396             finally {
397                 transport.close();
398             }
399         }
400         catch (AuthenticationFailedException JavaDoc ex) {
401             throw new MailAuthenticationException(ex);
402         }
403         catch (MessagingException JavaDoc ex) {
404             throw new MailSendException("Mail server connection failed", ex);
405         }
406         if (!failedMessages.isEmpty()) {
407             throw new MailSendException(failedMessages);
408         }
409     }
410
411     /**
412      * Obtain a Transport object from the given JavaMail Session,
413      * using the configured protocol.
414      * <p>Can be overridden in subclasses, e.g. to return a mock Transport object.
415      * @see javax.mail.Session#getTransport(String)
416      * @see #getProtocol()
417      */

418     protected Transport JavaDoc getTransport(Session JavaDoc session) throws NoSuchProviderException JavaDoc {
419         return session.getTransport(getProtocol());
420     }
421
422 }
423
Popular Tags