Hello,
After my post about the Fake SMTP Server/SMTP4DEV, today, I would present a solution for the sending of email in your java applications.
So, we will consider sending emails using the Spring framework.
Indeed, Spring provides a number of utility classes that facilitate the integration of your applications with the JavaMail API, especially the classes org.springframework.mail.javamail.JavaMailSenderImpl and org.springframework.mail.javamail.MimeMessageHelper.
To use Spring to integrate JavaMail in your applications, we have obviously the jars spring-2.5.5.jar, mail-1.3.2.jar, junit-4.1.jar, commons-beanutils-1.6.jar, commons-io-1.4.jar, commons-logging-1.1.1.jar.
To check the mail sent by our solution, we will use Fake SMTP Server or the SMTP4DEV software as descried here.
Important note: Some classes in the mail-1.3.2.jar exist also in the library geronimo-javamail_1.4_spec-1.3.jar, so, in order to avoid the conflict, remove the geronimo-javamail library from your project using this solution based on mail-1.3.2.jar.
Configuration
The mail sending is implemented in a main static class named MailSender with the support of message content through a configuration templates. This class is configured in Spring context file spring-mail-config.xml:
01 | <? xml version = "1.0" encoding = "UTF-8" ?> |
02 | < beans ...> |
03 | <!-- |
04 | | Factory bean created in order to use a unique instance of "MailSender" in: |
05 | | + MailSender mailSender = (MailSender) ctx.getBean("mailSender"); |
06 | | OR |
07 | | + MailSender.getInstance().sendMail(emails, templateName, mappingData); |
08 | --> |
09 | < bean id = "mailSenderFactoryBean" class = "com.ho.test.mail.ex1.sending.MailSenderFactoryBean" /> |
10 |
11 | <!-- |
12 | | This bean is used to: |
13 | | + build the message from template; |
14 | | + mapping datas to the template; |
15 | | + send email; |
16 | --> |
17 | < bean id = "mailSender" class = "com.ho.test.mail.ex1.sending.MailSender" |
18 | factory-bean = "mailSenderFactoryBean" |
19 | factory-method = "createInstance" > |
20 | </ bean > |
21 | </ beans > |
… this Spring context will be accessible via the singleton CommonContext:
01 | public class CommonContext { |
02 | private static CommonContext currentInstance = null ; |
03 | |
04 | /** The ctx. */ |
05 | private ApplicationContext ctx; |
06 |
07 | private CommonContext() { |
08 | //load spring bean |
09 | ctx = new ClassPathXmlApplicationContext( new String[] { "spring-mail-config.xml" }); |
10 | } |
11 | |
12 | public static synchronized CommonContext getInstance() { |
13 | if (currentInstance == null ) { |
14 | currentInstance = new CommonContext(); |
15 | } |
16 | return currentInstance; |
17 | } |
18 |
19 | public ApplicationContext getCtx() { |
20 | return ctx; |
21 | } |
22 |
23 | public void setCtx(ApplicationContext ctx) { |
24 | this .ctx = ctx; |
25 | } |
26 | } |
…so, the Spring context contains a factory bean named MailSenderFactoryBean needed only in order to use an unique instance of the MailSender in:
1 | MailSender mailSender = (MailSender) ctx.getBean( "mailSender" ); |
2 | //OR |
3 | MailSender.getInstance().sendMail(emails, templateName, mappingData); |
1 | public class MailSenderFactoryBean{ |
2 | public MailSender createInstance() throws Exception { |
3 | MailSender mailSender = MailSender.getInstance(); |
4 | return mailSender; |
5 | } |
6 | } |
…., here, a part of the main class MailSender which allows:
- the mail sending with the loading of mail session via the class MailSessionLoader,
- the formating of message due to an internal class TemplateMailBean building the message from template and its corresponding datas in the ${parameterName} format,
01 | public class MailSender { |
02 |
03 | private static MailSender singleton = null ; |
04 | private MailSender() {} |
05 | public static synchronized MailSender getInstance() { |
06 | if (singleton == null ){ |
07 | singleton = new MailSender(); |
08 | } |
09 | return singleton; |
10 | } |
11 | |
12 | |
13 | @SuppressWarnings ( "unchecked" ) |
14 | public synchronized void sendMail(String smtpMailFrom, String[] recipientsEmailTo, String[] recipientsEmailCc, String[] recipientsEmailBcc, String templateName, Map<String, String> mappingData, Map<String, InputStreamSource> attachments) throws Throwable{ |
15 | System.out.println( "sendMail()" ); |
16 | |
17 | // MAIL SESSION |
18 | /*javax.mail.Session mailSession = null; |
19 | { |
20 | Hashtable<String,String> env = new Hashtable<String,String> (); |
21 | env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); |
22 | mailSession = (javax.mail.Session) new InitialContext(env).lookup("java:comp/env/mail/Session"); |
23 | }*/ |
24 | // |
25 | MailSessionLoader loader= new MailSessionLoader(); |
26 | Session mailSession=loader.loadJavaMailSession(); |
27 | |
28 | // Build the message |
29 | MimeMessage mailMsg = new MimeMessage(mailSession); |
30 | MimeMessageHelper helper = new MimeMessageHelper(mailMsg, true ); |
31 | // Set the mail sender |
32 | { |
33 | if (smtpMailFrom == null ){ |
34 | smtpMailFrom = SMTPConstant.SMTP_SENDER_EMAIL; |
35 | } |
36 | helper.setFrom( new InternetAddress(smtpMailFrom)); |
37 | } // end-block |
38 |
39 | // Set the recipient To |
40 | { |
41 | if (recipientsEmailTo!= null ){ |
42 | for ( int i = 0 ; i < recipientsEmailTo.length; i++) { |
43 | if (recipientsEmailTo[i]!= null && ! "" .equalsIgnoreCase(recipientsEmailTo[i].trim())){ |
44 | helper.addTo( new InternetAddress(recipientsEmailTo[i].trim())); |
45 | } |
46 | } |
47 | } |
48 | } // end-block |
49 |
50 | .... |
51 |
52 | |
53 | TemplateMailBean bean= null ; |
54 | { |
55 | bean = new TemplateMailBean(templateName, mappingData); |
56 | } |
57 | |
58 | .... |
59 | |
60 | } |
61 | ... |
62 | } |
…this bean TemplateMailBean uses the templates configured in constants of the class SMTPConstant:
TEMPLATE_MAIL_GENERIC
subject=${subject}
body=${htmlBody}
footer=${footer}
TEMPLATE_MAIL_SPECIFIC
subject=JAVABLOG: Error for post ${referencePOST}
body=An error is occured during the treatment of system with the following message: ${htmlMessage}
footer=This is an automatically generated e-mail sent by JAVABLOG, please don’t reply.
Simple Example
Below, a simple example of mail sending using the generic template TEMPLATE_MAIL_GENERIC:
01 | // TemplateName |
02 | String templateName = "TEMPLATE_MAIL_GENERIC" ; |
03 | |
04 | // Recepients To |
05 | String[] recipientsEmailTo = new String[]{ "huseyin.ozveren@javablog.fr" , "ozveren@java.lu" }; |
06 |
07 | // Data to be used |
08 | Map<String, String> mappingData = new HashMap<String, String>(); |
09 | mappingData.put( "subject" , "JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547" ); |
10 | mappingData.put( "htmlBody" , " - Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR" ); |
11 | mappingData.put( "footer" , "- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply." ); |
12 | // |
13 | MailSender.getInstance().sendMail(recipientsEmailTo, templateName, mappingData); |
… traces in the output would be:
1 | sendMail() |
2 | MailSessionLoader.loadJavaMailSession() |
3 | templateName=TEMPLATE_MAIL_GENERIC - mappingData={footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply., subject=JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547, htmlBody= - Generic - An error is occured during the treatment of system with the following message:< br /> < a href = 'http://www.javablog.fr' >clic here</ a > to access to JAVABLOG.FR} |
4 | prop {body=- Generic - An error is occured during the treatment of system with the following message:< br /> < a href = 'http://www.javablog.fr' >clic here</ a > to access to JAVABLOG.FR, subject=JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547, footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.} |
5 | INFO : MAILSENT : Sat Aug 11 01:28:55 CEST 2012 : MailSender : subject : JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547 recipients : huseyin.ozveren@javablog.fr;ozveren@java.lu; |
Advanced Tests
The project in attachement contains a JUNIT TestMailSender with two concrets cases:
- an example of mail sending using the generic template TEMPLATE_MAIL_SPECIFIC containing the parameters referencePOST and htmlMessage:
01
// TemplateName
02
String templateName =
"TEMPLATE_MAIL_SPECIFIC"
;
03
04
// Recepients To
05
String[] recipientsEmailTo =
new
String[]{
"huseyin.ozveren@javablog.fr"
,
"ozveren@java.lu"
};
06
07
// Data to be used
08
Map<String, String> mappingData =
new
HashMap<String, String>();
09
mappingData.put(
"referencePOST"
,
"123456"
);
10
mappingData.put(
"htmlMessage"
,
"..... message error...... "
);
11
12
MailSender.getInstance().sendMail(recipientsEmailTo, templateName, mappingData);
… traces in the output would be:
1
sendMail()
2
MailSessionLoader.loadJavaMailSession()
3
templateName=TEMPLATE_MAIL_SPECIFIC - mappingData={htmlMessage=..... message error...... , referencePOST=123456}
4
prop {body=An error is occured during the treatment of system with the following message: ..... message error...... , subject=JAVABLOG: Error for post 123456, footer=This is an automatically generated e-mail sent by JAVABLOG, please don't reply.}
5
INFO : MAILSENT : Sat Aug 11 01:28:56 CEST 2012 : MailSender : subject : JAVABLOG: Error for post 123456 recipients : huseyin.ozveren@javablog.fr;ozveren@java.lu;
- an example of mail sending using the generic template TEMPLATE_MAIL_GENERIC, with recepients in To, CC and with 2 text files in attachement:
01
// TemplateName
02
String templateName =
"TEMPLATE_MAIL_GENERIC"
;
03
04
// From
05
String smtpMailFrom =
"contact@java.lu"
;
06
07
// Recepients To
08
String[] recipientsEmailTo =
new
String[]{
"huseyin.ozveren@javablog.fr"
,
"ozveren@java.lu"
};
09
10
// Recepients Cc
11
String[] recipientsEmailCc =
new
String[]{
"huseyinCC@javablog.fr"
,
"ozverenCC@java.lu"
};
12
13
// Data to be used
14
Map<String, String> mappingData =
new
HashMap<String, String>();
15
mappingData.put(
"subject"
,
"JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547"
);
16
mappingData.put(
"htmlBody"
,
" - Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR"
);
17
mappingData.put(
"footer"
,
"- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply."
);
18
19
// Attachments
20
Map<String, InputStreamSource> attachments =
new
HashMap<String, InputStreamSource>();
21
{
22
// Creation of a file1
23
{
24
File attachmentFile1 =
null
;
25
attachmentFile1 = File.createTempFile(
"attachment1"
,
".txt"
);
26
attachmentFile1.deleteOnExit();
27
FileOutputStream flout =
new
FileOutputStream(attachmentFile1);
28
flout.write(
"text JAVABLOG.FR JAVA.LU text "
.getBytes(
"UTF-8"
));
29
flout.close();
30
InputStreamSource iss1 =
null
;
31
iss1 =
new
InputStreamResource(
new
FileInputStream(attachmentFile1));
32
attachments.put(
"MyAttachment1.txt"
, iss1);
33
}
34
// Creation of a file2
35
{
36
File attachmentFile2 =
null
;
37
attachmentFile2 = File.createTempFile(
"attachment2"
,
".txt"
);
38
attachmentFile2.deleteOnExit();
39
FileOutputStream flout =
new
FileOutputStream(attachmentFile2);
40
flout.write(
"text JAVABLOG.FR JAVA.LU text "
.getBytes(
"UTF-8"
));
41
flout.close();
42
InputStreamSource iss2 =
null
;
43
iss2 =
new
InputStreamResource(
new
FileInputStream(attachmentFile2));
44
attachments.put(
"MyAttachment2.txt"
, iss2);
45
}
46
}
47
48
MailSender.getInstance().sendMail(smtpMailFrom, recipientsEmailTo, recipientsEmailCc,
null
, templateName, mappingData, attachments);
… traces in the output would be:
1
sendMail()
2
MailSessionLoader.loadJavaMailSession()
3
templateName=TEMPLATE_MAIL_GENERIC - mappingData={footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply., subject=JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547, htmlBody= - Generic - An error is occured during the treatment of system with the following message:<
br
/> <
a
href
=
'http://www.javablog.fr'
>clic here</
a
> to access to JAVABLOG.FR}
4
prop {body=- Generic - An error is occured during the treatment of system with the following message:<
br
/> <
a
href
=
'http://www.javablog.fr'
>clic here</
a
> to access to JAVABLOG.FR, subject=JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547, footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.}
5
INFO : MAILSENT : Sat Aug 11 01:28:56 CEST 2012 : MailSender : subject : JavaBlog.fr: - Generic - Error Notification for the post 123465798012546547 recipients : huseyin.ozveren@javablog.fr;ozveren@java.lu;huseyinCC@javablog.fr;ozverenCC@java.lu;
For more informations, you could contact me.
Download: test_mail1.zip
Best regards,
Huseyin OZVEREN