8.1. Sending E-mail (SMTP)¶
Index
8.1.1. Overview¶
This chapter explains how to send an E-mail using SMTP.
In this guideline, it is assumed that a component for email coordination offered by API and Spring Framework of JavaMail is used.
Note
The description covers only the part related to sending an email. The processing method related to sending an email is not mentioned. (An example is introduced for Processing method.)
8.1.1.1. Regarding JavaMail¶
JavaMail offers an API to send and receive emails in Java. Although it is included in Java EE, it can also be used in Java SE as an add-on package. By using JavaMail, the email function can be easily incorporated in Java application.
Also, since it is assumed that an email coordination component of Spring Framework is used in this guideline, the details related to JavaMail API are not covered. Refer JavaMail API Design Specification for JavaMail API specifications.
Note
Mail Session
A mail session (Session) manages the information required for connecting to a mail server.
Following methods are used to fetch a mail session.
- Fetch the mail session managed by Java EE container through JNDI for a typical enterprise application.
- Fetch the mail session defined by resource factory through JNDI in case of Tomcat.
- Fetch the mail session for which a Bean is defined, from DI container using a static factory method.
- Fetch directly from Java source using static factory method of
Session
.
Note that, if JavaMailSenderImpl
of Spring described later is used, it is possible to connect to a mail server without handling a mail session directly.
Implementation examples using two methods given below are introduced in this guideline.
- A method wherein a mail session is fetched through JNDI
- A method wherein connection information is specified in
JavaMailSenderImpl
property without handling a session directly
8.1.1.2. Regarding component of Spring Framework for email coordination¶
Spring Framework offers a component (org.springframework.mail
package) for sending an email.
The component included in the package conceals the detail logic related to sending an email and carry out low level API handling (API calling of JavaMail).
The method by which the component offered by Spring Framework for email transmission sends an email is explained before the explanation of basic implementation methods.
Sr. No. | Component | Description |
---|---|---|
(1)
|
Application
|
Call
JavaMailSender method and request to send an email.* While sending a simple message, an email can also be sent by generating
SimpleMailMessage and specifying address and body text. |
(2)
|
JavaMailSender |
Call
MimeMessagePreparator (callback interface to create MimeMessage of JavaMail) specified by the application and request to create a message for sending an email (MimeMessage ).This process is not called while sending the message using *
SimpleMailMessage . |
(3)
|
Application
(
MimeMessagePreparator ) |
Create a message (
MimeMessage ) for sending the email using MimeMessageHelper method.This process is not called while sending the message using *
SimpleMailMessage . |
(4)
|
JavaMailSender |
Request to send the email using API of JavaMail.
|
(5)
|
JavaMail
|
Send a message to the email server.
|
The method to implement a process for sending an email using interface and class below is explained in this guideline.
JavaMailSender
- An interface for JavaMail to send an email.It supports both MimeMessage of JavaMail and
SimpleMailMessage
of Spring.Further, sinceSession
of JavaMail is managed by implementation class ofJavaMailSender
, it is not necessary to handleSession
directly while writing the code for the process to send an email.
JavaMailSenderImpl
- An implementation class of
JavaMailSender
interface.This class supports a method wherein DI is applied to configuredSession
and a method whereinSession
is created from connection information specified in property.
MimeMessagePreparator
- A callback interface for creating
MimeMessage
of JavaMail.It is called fromsend
method ofJavaMailSender
.The exception generated inprepare
method ofMimeMessagePreparator
is wrapped inMailPreparationException
(runtime exception) and thrown again.
MimeMessageHelper
- A helper class to facilitate creation of
MimeMessage
of JavaMail.MimeMessageHelper
provides a number of convenient methods to specify a value inMimeMessage
.
SimpleMailMessage
- A class to create a simple email message.It can be used to create a plain text email in English.A
MimeMessage
of JavaMail must be used for creating rich messages such as specifying specific encoding like UTF-8, sending HTML emails and emails with attachments or associating personal names with email addresses.
8.1.2. How to use¶
8.1.2.1. Regarding dependent library¶
When a component of Spring Framework for email coordination is used, following libraries must be added.
pom.xml
.pom.xml
(projectName-domain/pom.xml
) of domain project.<dependencies>
<!-- (1) -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
</dependency>
</dependencies>
Sr. No. | Description |
---|---|
(1)
|
Add JavaMail libraries to dependencies.
Set
<scope> to provided while using a mail session offered by application server. |
Note
In the above setting example, since it is assumed that the dependent library version is managed by the parent project terasoluna-gfw-parent, specifying the version in pom.xml is not necessary. The above dependent library used by terasoluna-gfw-parent is defined by Spring IO Platform.
8.1.2.2. How to configure JavaMailSender¶
Define a Bean for applying DI to JavaMailSender
.
Note
In case of a multi-project configuration, it is recommended to set in projectName-env.xml
of env project.
Note that, in this guideline, it is recommended to adopt a multi-project configuration.
8.1.2.2.1. When a mail session offered by application server is used¶
A configuration example while using a mail session offered by application server is given below.
¶ Sr. No. Application server Refer page
Apache Tomcat 8.5 Refer Apache Tomcat 8.5 User Guide(JNDI Resources HOW-TO) (JavaMail Sessions).
Apache Tomcat 8.0 Refer Apache Tomcat 8.0 User Guide(JNDI Resources HOW-TO)(JavaMail Sessions).
Oracle WebLogic Server 12c Refer Oracle WebLogic Server 12.2.1.0 Documentation.
IBM WebSphere Application Server Version 9.0 Refer WebSphere Application Server Version 9.0.0 documentation.
Red Hat JBoss Enterprise Application Platform Version 7.0 Refer JBoss Enterprise Application Platform 7.0 Product Documentation.
Red Hat JBoss Enterprise Application Platform Version 6.4 Refer JBoss Enterprise Application Platform 6.4 Product Documentation.
Carry out setup for registering a mail session fetched through JNDI, as a Bean.
<jee:jndi-lookup id="mailSession" jndi-name="mail/Session" /> <!-- (1) -->
Sr. No. | Description |
---|---|
(1)
|
Specify JNDI name of mail session offered by application server in
jndi-name attribute of <jee:jndi-lookup> element. |
Next, define a Bean for JavaMailSender
.
<!-- (1) -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="session" ref="mailSession" /> <!-- (2) -->
</bean>
Sr. No. | Description |
---|---|
(1)
|
Define a Bean for
JavaMailSenderImpl . |
(2)
|
Specify a Bean of configured mail session in
session property. |
8.1.2.2.2. When a mail session offered by application server is not used (no authentication)¶
A configuration example wherein authentication is not required is given below.
Define a Bean for JavaMailSender
.
<!-- (1) -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.smtp.host}"/> <!-- (2) -->
<property name="port" value="${mail.smtp.port}"/> <!-- (3) -->
</bean>
Sr. No. | Description |
---|---|
(1)
|
Define a Bean for
JavaMailSenderImpl . |
(2)
|
Specify a host name of SMTP server in
host property.In this example, a value defined in the property file (value corresponding to key “
mail.smtp.host ”) is specified. |
(3)
|
Specify a port number of SMTP server in
port property.In this example, a value defined in the property file (value corresponding to key “
mail.smtp.port ”) is specified. |
Note
Refer Properties Management for details of property file.
8.1.2.2.3. When a mail session offered by application server is not used (authenticated)¶
A configuration example wherein authentication is required is given below.
Define a Bean for JavaMailSender
.
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.smtp.host}"/>
<property name="port" value="${mail.smtp.port}"/>
<property name="username" value="${mail.smtp.user}"/> <!-- (1) -->
<property name="password" value="${mail.smtp.password}"/> <!-- (2) -->
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop> <!-- (3) -->
</props>
</property>
</bean>
Sr. No. | Description |
---|---|
(1)
|
Specify a user name of SMTP server in
username property.In this example, a value defined in property file (value corresponding to key “
mail.smtp.user ”) is specified. |
(2)
|
Specify a password of SMTP server in
password property.In this example, a value defined in the property file (value corresponding to key “
mail.smtp.password ”) is specified. |
(3)
|
Set
true in javaMailProperties property as a key “mail.smtp.auth ”. |
Note
Refer Properties Management for details of property file.
Tip
When the connection using TLS is necessary, set true
in javaMailProperties
property as a key “mail.smtp.starttls.enable
”.
Note that, when SMTP server does not support STARTTLS even when specified as below, plain text is used for communication.
When true
is set in javaMailProperties
property as a key “mail.smtp.starttls.required
” whenever required, an error can occur if it is not possible to use STARTTLS.
8.1.2.3. How to send an email using SimpleMailMessage¶
When a plain text email (an email which does not require encode specification or attachments) is to be sent in English, SimpleMailMessage
class offered by Spring is used.
A method to send an email using SimpleMailMessage
class is explained below.
Example of Bean definition
<!-- (1) -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="info@example.com" /> <!-- (2) -->
<property name="subject" value="Registration confirmation." /> <!-- (3) -->
</bean>
Sr. No. | Description |
---|---|
(1)
|
Define a Bean for
SimpleMailMessage as a template.Although it is not mandatory to use
SimpleMailMessage of template, if a fixed location is specified (for e.g. sender email address etc) in the email message as a template, it is not necessary to individually specify it later in the email message. |
(2)
|
Specify details of From header in
from property. |
(3)
|
Specify details of Subject header in
subject property. |
Implementation example of Java class
@Inject
JavaMailSender mailSender; // (1)
@Inject
SimpleMailMessage templateMessage; // (2)
public void register(User user) {
// omitted
// (3)
SimpleMailMessage message = new SimpleMailMessage(templateMessage);
message.setTo(user.getEmailAddress());
String text = "Hi "
+ user.getUserName()
+ ", welcome to EXAMPLE.COM!\r\n"
+ "If you were not an intended recipient, Please notify the sender.";
message.setText(text);
mailSender.send(message);
// omitted
}
Sr. No. | Description |
---|---|
(1)
|
Inject
JavaMailSender . |
(2)
|
Inject
SimpleMailMessage as a template for which a Bean is defined. |
(3)
|
Generate a
SimpleMailMessage instance by using Bean of template, specify To header and body text, and send the message. |
Note
¶ Sr. No. Property Description 1.from
Specify From header. 2.to
Specify To header. 3.cc
Specify Cc header. 4.bcc
Specify Bcc header. 5.subject
Specify Subject header. 6.replyTo
Specify Reply-To header. 7.sentDate
Specify Date header.Note that, if it is not explicitly set, system time (new Date()
)is set automatically at the time of sending an email. 8.text
Specify body text.
When multiple addresses are to be specified in To, Cc and Bcc, specify addresses in an array.
Warning
While setting an email header, an email header injection must be considered. Refer Email header injection countermeasures for details.
8.1.2.4. How to send an email using MimeMessage¶
When a non-English text email, HTML email and attachments are to be sent,
javax.mail.internet.MimeMessage
class is used.
In this guideline, a method to create MimeMessage
by using MimeMessageHelper
class is recommended.
In this section, the methods to send an email using MimeMessageHelper
class are explained below.
- Sending a text email
- Sending a HTML email
- Sending an email with attachment
- Sending an email with inline resource
8.1.2.4.1. Sending a text email¶
An implementation example wherein a text email is sent using MimeMessageHelper
class is given below.
Implementation example of Java class
@Inject
JavaMailSender mailSender; // (1)
public void register(User user) {
// omitted
// (2)
mailSender.send(new MimeMessagePreparator() {
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,
StandardCharsets.UTF_8.name()); // (3)
helper.setFrom("EXAMPLE.COM <info@example.com>"); // (4)
helper.setTo(user.getEmailAddress()); // (5)
helper.setSubject("Registration confirmation."); // (6)
String text = "Hi "
+ user.getUserName()
+ ", welcome to EXAMPLE.COM!\r\n"
+ "If you were not an intended recipient, Please notify the sender.";
helper.setText(text); // (7)
}
});
// omitted
}
Sr. No. | Description |
---|---|
(1)
|
Inject
JavaMailSender . |
(2)
|
Send an email using
send method of JavaMailSender .Define an anonymous inner class that implements
MimeMessagePreparator , in the argument. |
(3)
|
Specify character code and generate
MimeMessageHelper instance.In this example, UTF-8 is specified in the character code.
|
(4)
|
Specify details of From header.
In this example, it is set in “Name <Address>” format.
|
(5)
|
Specify details of To header.
|
(6)
|
Specify details of Subject header.
|
(7)
|
Specify details of body text.
|
Warning
While setting an email header, an email header injection must be considered. Refer Email header injection countermeasures for details.
Note
While sending an email in Japanese, ISO-2022-JP can also be used in encoding if it is also necessary to support a mail client which does not support UTF-8. Refer Considerations for ISO-2022-JP encoding for the points that should be considered while using ISO-2022-JP in encoding.
8.1.2.4.2. Sending a HTML email¶
An implementation example wherein a HTML email is sent using MimeMessageHelper
class is shown below.
Implementation example of Java class
@Inject
JavaMailSender mailSender; // (1)
public void register(User user) {
// omitted
// (2)
mailSender.send(new MimeMessagePreparator() {
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,
StandardCharsets.UTF_8.name()); // (3)
helper.setFrom("EXAMPLE.COM <info@example.com>"); // (4)
helper.setTo(user.getEmailAddress()); // (5)
helper.setSubject("Registration confirmation."); // (6)
String text = "<html><body><h3>Hi "
+ user.getUserName()
+ ", welcome to EXAMPLE.COM!</h3>"
+ "If you were not an intended recipient, Please notify the sender.</body></html>";
helper.setText(text, true); // (7)
}
});
// omitted
}
Sr. No. | Description |
---|---|
(1)
|
Inject
JavaMailSender . |
(2)
|
Send an email using
send method of JavaMailSender .Define an anonymous inner class that implements
MimeMessagePreparator , in the argument. |
(3)
|
Specify character code and generate
MimeMessageHelper instance.In this example, UTF-8 is specified in the character code.
|
(4)
|
Specify details of From header.
In this example, it is set in the “Name <Address>” format.
|
(5)
|
Specify details of To header.
|
(6)
|
Specify details of Subject header.
|
(7)
|
Specify details of body text. Content-Type changes to text/html by specifying
true in the second argument of setText method. |
Warning
When a value entered externally is used while generating HTML for email text, countermeasures for XSS attack should be employed.
8.1.2.4.3. Sending an email with attachment¶
An implementation example wherein an email with the attachment is sent using MimeMessageHelper
class is shown below.
Implementation example of Java class
@Inject
JavaMailSender mailSender; // (1)
public void register(User user) {
// omitted
// (2)
mailSender.send(new MimeMessagePreparator() {
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,
true, StandardCharsets.UTF_8.name()); // (3)
helper.setFrom("EXAMPLE.COM <info@example.com>"); // (4)
helper.setTo(user.getEmailAddress()); // (5)
helper.setSubject("Registration confirmation."); // (6)
String text = "Hi "
+ user.getUserName()
+ ", welcome to EXAMPLE.COM!\r\n"
+ "Please find attached the file.\r\n\r\n"
+ "If you were not an intended recipient, Please notify the sender.";
helper.setText(text); // (7)
ClassPathResource file = new ClassPathResource("doc/quickstart.pdf");
helper.addAttachment("QuickStart.pdf", file); // (8)
}
});
// omitted
}
Sr. No. | Description |
---|---|
(1)
|
Inject
JavaMailSender . |
(2)
|
Send an email using
send method of JavaMailSender .Define an anonymous inner class that implements
MimeMessagePreparator , in the argument. |
(3)
|
Specify character code and generate
MimeMessageHelper instance.In this example, UTF-8 is specified in the character code.
It becomes multi-part mode (default
MULTIPART_MODE_MIXED_RELATED ) by specifying true in the second argument of the constructor of MimeMessageHelper . |
(4)
|
Specify details of From header.
|
(5)
|
Specify details of To header.
|
(6)
|
Specify details of Subject header.
|
(7)
|
Specify details of body text.
|
(8)
|
Specify attachment name and identify file to be attached.
In this example,
"QuickStart.pdf" denotes the file name and doc/quickstart.pdf file on the class path is attached. |
8.1.2.4.4. Sending an email with inline resource¶
An implementation example wherein an email with inline resource is sent using MimeMessageHelper
class is shown below.
Implementation example of Java class
@Inject
JavaMailSender mailSender; // (1)
public void register(User user) {
// omitted
// (2)
mailSender.send(new MimeMessagePreparator() {
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,
true, StandardCharsets.UTF_8.name()); // (3)
helper.setFrom("EXAMPLE.COM <info@example.com>"); // (4)
helper.setTo(user.getEmailAddress()); // (5)
helper.setSubject("Registration confirmation."); // (6)
String cid = "identifier1234";
String text = "<html><body><img src='cid:"
+ cid
+ "' /><h3>Hi "
+ user.getUserName()
+ ", welcome to EXAMPLE.COM!\r\n</h3>"
+ "If you were not an intended recipient, Please notify the sender.</body></html>";
helper.setText(text, true); // (7)
ClassPathResource res = new ClassPathResource("image/logo.jpg");
helper.addInline(cid, res); // (8)
}
});
// omitted
}
Sr. No. | Description |
---|---|
(1)
|
Inject
JavaMailSender . |
(2)
|
Send an email using
send method of JavaMailSender .Define an anonymous inner class that implements
MimeMessagePreparator , in the argument. |
(3)
|
Specify character code and generate
MimeMessageHelper instance.In this example, UTF-8 is specified in the character code.
It becomes a multi-part mode by specifying
true in the second argument of constructor of MimeMessageHelper . |
(4)
|
Specify details of From header.
|
(5)
|
Specify details of To header.
|
(6)
|
Specify details of Subject header.
|
(7)
|
Specify details of body text. Content-Type changes to text/html by specifying
true in the second argument of setText method. |
(8)
|
Specify inline resource contents ID and set inline resource.
In this example,
"identifier1234" denotes a content ID and image/logo.jpg file on the class path is set. |
Note
addInline
method should be called after setText
method.
If done otherwise, a mail client cannot view the inline resource correctly.
8.1.2.5. Regarding exceptions while sending an email¶
The exception that occurs while sending an email using send
method of JavaMailSender
is an exception which inherits org.springframework.mail.MailException
.
The exception class that inherits MailException
and occurrence conditions of respective exceptions are shown in the table below.
¶ Sr. No. Exception class Occurrence conditions
MailAuthenticationException Occurs during authentication failure.
MailParseException Occurs when an invalid value is set in the properties of email message.
MailPreparationException Occurs if an unexpected error occurs while creating an email message. Unexpected errors, for example, are the errors that occur in the template library.Exceptions occurring inMimeMessagePreparator
are wrapped inMailPreparationException
and thrown.
MailSendException Occurs when an error occurs while sending an email.
Note
Refer Exception Handling for transition to error screen corresponding to specific exceptions.
8.1.3. How to extend¶
8.1.3.1. How to create an email text using a template¶
It is not recommended to build an email text directly in Java source as shown in the implementation examples above for the reasons given below.
- Building the email text in Java source causes poor readability and it may cause an error.
- Boundary between display logic and business logic become ambiguous.
- It becomes necessary to modify, compile and deploy Java source in order to change the email text design.
Hence, it is recommended to use a template library to define an email text design. A template library must especially be used when the email text is particularly complex.
8.1.3.1.1. Creating the email text using FreeMarker¶
In this guideline, a method that uses FreeMarker as a template library is described.
Set a dependent library for using FreeMarker.
Configuration example of pom.xml
<dependencies> <!-- (1) --> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> </dependency> </dependencies>
Sr. No. Description (1)Add a FreeMarker library to dependencies.
Note
In the above setting example, since it is assumed that the dependent library version is managed by the parent project terasoluna-gfw-parent , specifying the version in pom.xml is not necessary. The above dependent library used by terasoluna-gfw-parent is defined by Spring IO Platform.
Define a Bean for FactoryBean to generate
freemarker.template.Configuration
.Configuration example of Bean definition file
<!-- (1) --> <bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean"> <property name="templateLoaderPath" value="classpath:/META-INF/freemarker/" /> <!-- (2) --> <property name="defaultEncoding" value="UTF-8" /> <!-- (3) --> </bean>
Sr. No. Description (1)Define a Bean forFreeMarkerConfigurationFactoryBean
.(2)Specify the location of template file storage intemplateLoaderPath
property.In this example,META-INF/freemarker/
directory on the class path is specified.(3)Specify default encoding indefaultEncoding
property.In this example, UTF-8 is specified.Note
Refer to JavaDoc of FreeMarkerConfigurationFactoryBean for the setup other than mentioned above. Also, refer FreeMarker Manual (Programmer’s Guide / The Configuration) for setup of FreeMarker itself.
Create a template file for email text.
Configuration example of template file
<#escape x as x?html> <#-- (1) --> <html> <body> <h3>Hi ${userName}, welcome to TERASOLUNA.ORG!</h3> <#-- (2) --> <div> If you were not an intended recipient, Please notify the sender. </div> </body> </html> </#escape>
Sr. No. Description (1)Specify to apply HTML escape as a countermeasure for XSS attack.(2)Embed the value ofuserName
specified in the data model.Note
Refer FreeMarker Manual (Template Language Reference) for details of template language (FIL).
Generate an email text using a template and send email.
Implementation example of Java class
@Inject JavaMailSender mailSender; @Inject Configuration freemarkerConfiguration; // (1) public void register(User user) { // omitted mailSender.send(new MimeMessagePreparator() { @Override public void prepare(MimeMessage mimeMessage) throws Exception { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, StandardCharsets.UTF_8.name()); helper.setFrom("EXAMPLE.COM <info@example.com>"); helper.setTo(user.getEmailAddress()); helper.setSubject("Registration confirmation."); Template template = freemarkerConfiguration .getTemplate("registration-confirmation.ftl"); // (2) String text = FreeMarkerTemplateUtils .processTemplateIntoString(template, user); // (3) helper.setText(text, true); } }); // omitted }
Sr. No. Description (1)Inject Configuration.(2)In this example, “registration-confirmation.ftl” is specified as a template file.(3)Based on fetchedTemplate
, generate a string from the template usingprocessTemplateIntoString
method oforg.springframework.ui.freemarker.FreeMarkerTemplateUtils
.In this example,User
object (JavaBeans) consisting ofuserName
property is specified as a data model. Accordingly, value ofuserName
property is embedded in the location of${userName}
of template file.
8.1.4. Appendix¶
8.1.4.1. Considerations for ISO-2022-JP encoding¶
When sending an email in Japanese, if the email client that receives the sent mail cannot be restricted, it is necessary to consider use of ISO-2022-JP in encoding. This is because the legacy email client does not support UTF-8.
When encoding based on character set of JIS X 0208 including ISO-2022-JP is set for the string entered by MS932, garbling occurs for seven characters described in the table below.
Before conversion | After conversion | ||||
---|---|---|---|---|---|
MS932
Input character
|
Input value
(SJIS)
|
Unicode
(UTF-16)
|
Unicode
(UTF-16)
|
ISO-2022-JP
(JIS)
|
JIS X 0208
Alternative character
|
―(Double byte hyphen)
|
815D
|
U+2015
|
U+2014
|
213E
|
—(EM dash)
|
-(Hyphen-minus)
|
817C
|
U+FF0D
|
U+2212
|
215D
|
−(Double byte minus)
|
~(Double byte tilde)
|
8160
|
U+FF5E
|
U+301C
|
2141
|
〜(Tilde)
|
∥(Parallel symbol)
|
8161
|
U+2225
|
U+2016
|
2142
|
‖(Pipe sumbol)
|
¢(Double byte cent symbol)
|
8191
|
U+FFE0
|
U+00A2
|
2171
|
¢(Cent symbol)
|
£(Double byte pound symbol)
|
8192
|
U+FFE1
|
U+00A3
|
2172
|
£(Pound symbol)
|
¬(Double byte negation symbol)
|
81CA
|
U+FFE2
|
U+00AC
|
224C
|
¬(Negation symbol)
|
This issue occurs during character code conversion through Unicode due to the presence of characters that exist in MS932 but do not exist in JIS X 0208. In order to avoid garbling, the measures such as replacing character codes for the garbled characters with alternate characters must be employed. Note that, conversion process is not necessary while using x-windows-iso2022jp described later.
Implementation example of conversion process is shown below.
public static String convertISO2022JPCharacters(String targetStr) {
if (targetStr == null) {
return null;
}
char[] ch = targetStr.toCharArray();
for (int i = 0; i < ch.length; i++) {
switch (ch[i]) {
// '-'(Double byte hyphen)
case '\u2015':
ch[i] = '\u2014';
break;
// '-'(Double byte minus)
case '\uff0d':
ch[i] = '\u2212';
break;
// '~'(Tilde)
case '\uff5e':
ch[i] = '\u301c';
break;
// '∥'(Pipe)
case '\u2225':
ch[i] = '\u2016';
break;
// '¢'(Cent symbol)
case '\uffe0':
ch[i] = '\u00A2';
break;
// '£'(Pound symbol)
case '\uffe1':
ch[i] = '\u00A3';
break;
// '¬' (Negation symbol)
case '\uffe2':
ch[i] = '\u00AC';
break;
default:
break;
}
}
return String.valueOf(ch);
}
Note
Since it is an issue that occurs during mapping in Unicode, conversion is necessary regardless of the character code of input value. Header and body text which may contain strings with Japanese text are used for conversion. From, To, Cc, Bcc, Reply-To, Subject etc are examples of the header that may contain Japanese text and are frequently used in general.
Also, when ISO-2-22-JP is set as encoding, extended characters which are not in scope are garbled.
These characters essentially should not be used. If it is necessary to use these characters, settings can be done as follows as JVM start-up options. Moreover, when ISO-2022-JP encoding is set, these characters can be replaced so that they can be mapped with x-windows-iso2022jp.
-Dsun.nio.cs.map=x-windows-iso2022jp/ISO-2022-JP
Warning
x-windows-iso2022jp is a ISO-2022-JP implementation which includes mapping (MS932 base) that is different from ISO-2022-JP standards. When ISO-2022-JP encoding is specified in the email header, whether the out-of-scope extension characters are handled in the implementation will depend on the email client. Hence it cannot be guaranteed that there will not be any garbling in all email clients even though mapping is done using x-windows-iso2022jp.
When extension characters can also be converted to alternate characters, a method wherein conversion is done in the application independently should also be reviewed similar to seven characters described earlier.
8.1.4.2. Precautions while using multibyte characters in JavaMail¶
In JavaMail, body text of mail to be sent ends with multibyte characters, additional characters (“?”, “w” etc) are likely to be output. Following methods can be used to avoid these occurrences.
- Change end character of mail body text to single byte character.
- Change end of mail body text to linefeed code (CRLF)
8.1.4.3. Email header injection countermeasures¶
If email header injection attack is successful, an email is sent to an unintended address and thus can end up as “junk mail”. When a string that has been entered externally is used in the email header (Subject etc) contents, it becomes necessary to take countermeasures against email header injection attack.
For example, if the following string is set by setSubject
method of MimeMessageHelper
, the text can be manipulated by adding a Bcc header.
Notification\r\nBcc: attacker@exapmle.com\r\n\r\nManipulated body.
Following methods can be considered as countermeasures for email header injection attack.
- Set contents to be specified in email header as a fixed value and output entire string that has been entered externally in the email body text.
- Check that no linefeed character is included in the contents specified in the email header.
8.1.4.4. Processing method¶
Since sending an email is a time consuming process, response time can become longer if an email is sent during a web application request. Hence, an email is usually not sent during a web application request and a method is adopted wherein an email is sent asynchronously. Although a process to send the email is not described here in detail, the example is given below which can be used as a reference.
8.1.4.4.1. Send an email based on the email information stored in database or message queue¶
Incorporate the functions given below in the application when you want to send an email based on the email information stored in database or message queue.
- Register the information of the email to be sent (address, body text, attachment etc) in the database (or message queue).
- Fetch the email information that has not been sent from database (or message queue) periodically and send the email through SMTP.
- Register the transmission results in database (or message queue).
Note that, following points must be taken into consideration during review.
- How to check registered email information and email sending results
- Handling in case of an error while sending an email
Tip
When an email is sent continuously by a mailing service, it is determined as spam mail. A method can be considered as a countermeasure wherein the sending sequence is set as random so that emails are not sent continuously for the same domain.
8.1.4.5. Test using GreenMail¶
A method wherein GreenMail is used as a fake server to test the email sending function is introduced. GreenMail can also be used by deploying war file besides using it as a library.
Implementation example of test code using GreenMail is shown below.
Configuration example of pom.xml
<dependencies>
<!-- (1) -->
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>1.4.1</version>
<scope>test</scope>
</dependency>
</dependencies>
Sr.No. | Description |
---|---|
(1)
|
Add GreenMail library to dependencies.
|
Implementation example of JUnit source
@Inject
EmailService emailService;
@Rule
public final GreenMailRule greenMail = new GreenMailRule(
ServerSetupTest.SMTP); // (1)
@Test
public void testSend() {
String from = "info@example.com";
String to = "foo@example.com";
String subject = "Registration confirmation.";
String text = "Hi "
+ to
+ ", welcome to EXAMPLE.COM!\r\n"
+ "If you were not an intended recipient, Please notify the sender.";
emailService.send(from, to, subject, text);
assertTrue(greenMail.waitForIncomingEmail(3000, 1)); // (2)
Message[] messages = greenMail.getReceivedMessages(); // (3)
assertNotNull(messages);
assertEquals(1, messages.length);
// omitted
}
Sr. No. | Description |
---|---|
(1)
|
Set
GreenMailRule as a rule which specifies ServerSetupTest.SMTP .SMTP port number is set to
3025 as a default. |
(2)
|
Wait for arrival of email by using
waitForIncomingEmail method.It is used when an email is sent asynchronously by another thread.
In this example, it is assumed that the email is sent asynchronously and waiting time for an email arrival is maximum 3 seconds.
|
(3)
|
Fetch all received emails by using
getReceivedMessages method.Emails sent by GreenMail are all received by GreenMail regardless of the address.
|