You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SendingEmailFromJavaApplications.asciidoc 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. ---
  2. title: Sending Email From Java Applications
  3. order: 12
  4. layout: page
  5. ---
  6. [[sending-email-from-java-applications]]
  7. Sending email from Java Applications
  8. ------------------------------------
  9. [[introduction]]
  10. Introduction
  11. ^^^^^^^^^^^^
  12. Sending email is a common feature required in many business applications.
  13. From simple notifications containing plain text to complex reports with
  14. links and multiple attachments, email is a common way of asynchronous
  15. communication with end users.
  16. This tutorial shows how to send email messages in two different ways:
  17. 1. Using the Apache Commons Email library which offers a simplified API on top of the JavaMail API.
  18. 2. Using Spring Mail Support, a utility library that encapsulates the specifics of the mailing system, also implemented on top of the JavaMail API. 
  19. Although
  20. email operations include sending, receiving, deleting, setting flags,
  21. and others depending on the specific email server in use, this tutorial
  22. only discusses email sending through SMTP.
  23. [[how-does-email-work]]
  24. How does Email Work?
  25. ~~~~~~~~~~~~~~~~~~~~
  26. Let’s start
  27. with a quick overview of the email communication process. It all begins
  28. with the end user composing a message using a client desktop or web
  29. application. The message is sent through multiple networking devices
  30. until it reaches its destination at the recipient’s machine. The
  31. relevant elements of this process are depicted in the following figure:
  32. image:https://lh5.googleusercontent.com/GbbTWnXnPml4ijiQU1mMO8tkmGSGAcmpXEGwHQJwGOFGGI3zD98_rgYaGi-0OX18M9iTtkHyif8FnJNdKX1ubdE8MXIQ4k-Ww5qu0-MC4aoOhiqjKz56p8KLyN-QdonMZzSKEEGS[javamail-tutorial]
  33. Once the end
  34. user has triggered the action to send the email, the client application
  35. connects to its configured email server, the SMTP Server, which can be
  36. described as a program capable of communicating with other SMTP Servers
  37. using the Simple Mail Transfer Protocol (SMTP). This SMTP Server can be
  38. your own server running software, such as Apache James Server, Postfix,
  39. Sendmail, qmail, or a server managed by a third party, such as Gmail,
  40. Outlook, and Yahoo Mail. 
  41. Your SMTP
  42. Server (managed by yourself or by a third party) sends the email message
  43. to the recipient’s SMTP Server. Once the message reaches its
  44. destination, it is stored in the recipient’s inbox at the recipient’s
  45. SMTP Server. Finally, the recipient can read the message by requesting
  46. it from the SMTP Server.
  47. Nowadays,
  48. SMTP is used to send email messages and IMAP (Internet Message Access
  49. Protocol) or POP (Post Office Protocol) to receive messages. In this
  50. case, your client application will use SMTP to send the message and the
  51. recipient’s SMTP Server will use SMTP to receive the message and IMAP or
  52. POP to serve the message when the recipient requests it. You don’t need
  53. to understand the specifics of these protocols in order to send email
  54. from a Java application but you might want to understand them deeper, if
  55. you are planning to implement operations such as receiving, deleting,
  56. and setting flags, or if your applications require sending zillions of
  57. emails in a batch.
  58. [[configuring-a-test-smtp-server]]
  59. Configuring a Test SMTP Server
  60. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  61. For the
  62. purposes of this tutorial, we are going to use FakeSMTP, a free email
  63. server that offers a convenient GUI for testing email sending. You can
  64. download it from the following website: https://nilhcem.github.io/FakeSMTP/download.html[https://nilhcem.github.io/FakeSMTP/download.html]
  65. Extract the
  66. content of the downloaded zip file and execute the extracted jar. You
  67. can configure a port in the Listening port option (we will use 9090 in
  68. this tutorial). Once ready, click the Start server button to start
  69. getting emails.
  70. Please note
  71. that with FakeSMTP you don’t need to provide any authentication values
  72. (they will be ignored).
  73. [[javamail-api]]
  74. JavaMail API
  75. ~~~~~~~~~~~~
  76. The JavaMail
  77. API is defined by the JSR 919 and is included in Java EE (but not in EJB
  78. Lite nor Java EE Web Profile). It provides an abstraction over mail
  79. systems which makes its API more verbose than those of Apache Commons
  80. Email and Spring Mail Support. We are not covering JavaMail in this
  81. tutorial. However, we provide an example application that uses JavaMail
  82. to send emails. You can get the code from the following link: https://github.com/alejandro-du/java-email-tutorial/blob/master/javamail-example/src/main/java/com/example/javamail/JavaMailService.java[https://github.com/alejandro-du/java-email-tutorial/blob/master/javamail-example/src/main/java/com/example/javamail/JavaMailService.java]
  83. [[apache-commons-email]]
  84. Apache Commons Email
  85. ~~~~~~~~~~~~~~~~~~~~
  86. Apache
  87. Commons Email is built on top of JavaMail and hides much of its
  88. complexity. Therefore, it offers an API that simplifies the code to
  89. implement email sending from Java applications.
  90. You must
  91. download the Commons Email jar file from the following link:
  92. https://commons.apache.org/proper/commons-email/download_email.cgi[https://commons.apache.org/proper/commons-email/download_email.cgi],
  93. or add the dependency using a dependency management system. For example,
  94. if you are using Maven, you can add the following to your pom.xml:
  95. [source, xml]
  96. ....
  97. <dependency>
  98. <groupId>org.apache.commons</groupId>
  99. <artifactId>commons-email</artifactId>
  100. <version>1.4</version>
  101. </dependency>
  102. ....
  103.  
  104. With Commons
  105. Email, you can send emails with HTML content using the `HtmlEmail` class.
  106. This class offers an abstraction to send emails with attachments. For
  107. example, during testing you can configure the `HtmlEmail` instance as
  108. follows:
  109. [source,java]
  110. ....
  111. HtmlEmail email = new HtmlEmail();
  112. email.setHostName("localhost");
  113. email.setSmtpPort(9090);
  114. email.setAuthentication()"sender@test.com", "password");
  115. ....
  116.  
  117. Or if you want to use Gmail:
  118. [source,java]
  119. ....
  120. HtmlEmail email = new HtmlEmail();
  121. email.setHostName("smtp.gmail.com");
  122. email.setSmtpPort(465);
  123. email.setSSLOnConnect(true);
  124. email.setAuthentication("your-account-name@gmail.com", "your-password");
  125. ....
  126. Keep in mind
  127. that hard-coding connection parameters like this is not good practice.
  128. Instead, you should read the values from an external source (such as a
  129. properties file) so that you can use different configurations for
  130. different environments (development, testing, production). 
  131. You can use
  132. the email instance to set the sender’s email address, add recipients,
  133. and set the subject and the text of the message:
  134. [source,java]
  135. ....
  136. email.setFrom("sender@test.com");
  137. email.addTo("recipient1@test.com", "recipient2@test.com");
  138. email.setSubject("The subject");
  139. email.setHtmlMsg("This is the message.");
  140. ....
  141. The `HtmlEmail`
  142. class also exposes the attach method to add attachments to the message.
  143. You can provide these attachments as an `InputStream` so that its content
  144. can be dynamically generated at runtime if required (`FileInputStream` is
  145. always an option in case you have `File` instances instead):
  146. [source,java]
  147. ....
  148. ByteArrayDataSource dataSource = new ByteArrayDataSource(inputStream, "text/plain");
  149. DataHandler dataHandler = new DataHandler(dataSource);
  150. email.attach(dataSource, "attachment.txt", "description");
  151. ....
  152.  
  153. The `attach`
  154. method is overloaded with multiple implementations offering different
  155. ways to attach files. The one used in the previous example requires to
  156. specify a description for the attachment.
  157. You can find
  158. a complete implementation of a utility class that implements email
  159. sending using the Commons Email in the following link: https://github.com/alejandro-du/java-email-tutorial/blob/master/commons-email-example/src/main/java/com/example/javamail/CommonsEmailService.java[https://github.com/alejandro-du/java-email-tutorial/blob/master/commons-email-example/src/main/java/com/example/javamail/CommonsEmailService.java]
  160. [[spring-email-support]]
  161. Spring Email Support
  162. ~~~~~~~~~~~~~~~~~~~~
  163. Similarly to
  164. the Apache Commons Email library, Spring offers an API on top of
  165. JavaMail which abstracts away the details of the mailing system. You
  166. need to add the `spring-context-support` dependency using Maven or Gradle.
  167. There is no official download site for this dependency, but you can
  168. download it directly from the following link if required: http://mvnrepository.com/artifact/org.springframework/spring-context-support/4.2.4.RELEASE[http://mvnrepository.com/artifact/org.springframework/spring-context-support/4.2.4.RELEASE].
  169. If you are
  170. using Maven you can add the following dependency to your pom.xml:
  171. [source,xml]
  172. ....
  173. <dependency>
  174. <groupId>org.springframework</groupId>
  175. <artifactId>spring-context-support</artifactId>
  176. <version>4.2.4.RELEASE</version>
  177. </dependency>
  178. ....
  179. You start by
  180. obtaining an implementation of the `MailSender` interface. Spring provides
  181. the `JavaMailSenderImpl` class that implements `MailSender`. You can obtain
  182. an instance of this class either by configuring and injecting a bean, if
  183. you are already using Spring Framework and have configured an
  184. application context, or by direct instantiation: 
  185. [source,java]
  186. ....
  187. JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
  188. ....
  189. The
  190. connection to the SMTP server is configured using properties. The
  191. following example shows how to configure the `mailSender` to connect to
  192. Gmail’s SMTP server:
  193. [source,java]
  194. ....
  195. Properties properties = new Properties();
  196. properties.put("mail.smtp.host", "smtp.gmail.com");
  197. properties.put("mail.smtp.port", "465");
  198. properties.put("mail.smtp.ssl.enable", "true");
  199. mailSender.setJavaMailProperties(properties);
  200. ....
  201.  
  202. Alternatively,
  203. you can use methods defined in the `MailSender` interface to configure the
  204. host and port, but in the case of SMTP servers using SSL, you will have
  205. to provide at least the `mail.smtp.ssl.enable` property through a
  206. `Properties` object. For this reason, we prefer to configure all the
  207. settings using properties in this example.
  208. The authentication credentials are configured using the `MailSender` instance
  209. as follows:
  210. [source,java]
  211. ....
  212. mailSender.setUsername("sender@test.com");
  213. mailSender.setPassword("password");
  214. ....
  215. The next step is to create a `MimeMessage` and a `MimeMessageHelper`:
  216. [source,java]
  217. ....
  218. MimeMessage message = mailSender.createMimeMessage();
  219. MimeMessageHelper helper = new MimeMessageHelper("The message body", true);
  220. ....
  221. The second
  222. parameter is set to true to create a multipart message that will allow
  223. us to add attachments later. The `MimeMessageHelper` exposes a handful of
  224. methods to directly set up the message:
  225. [source,java]
  226. ....
  227. helper.setFrom("sender@test.com");
  228. helper.setSubject("subject");
  229. helper.setText(text, true); // true to activate multipart
  230. helper.addTo("recipient@test.com");
  231. ....
  232. There are
  233. several overloaded methods in the `MimeMessageHelper` that provide
  234. different ways to attach files. The following example uses the
  235. `ByteArrayDataSource` class to provide an attachment from an `InputStream`:
  236. [source,java]
  237. ....
  238. ByteArrayDataSource dataSource = new ByteArrayDataSource(inputStream, "text/plain");
  239. helper.addAttachment("file.txt", dataSource);
  240. ....
  241. Finally, you can send the email using the `MailSender` instance:
  242. [source,java]
  243. ....
  244. mailSender.send(message);
  245. ....
  246.  
  247. You can find
  248. a complete implementation of a utility class that implements email
  249. sending using Spring Email Support in the following link: https://github.com/alejandro-du/java-email-tutorial/blob/master/spring-mail-example/src/main/java/com/example/javamail/SpringEmailService.java[https://github.com/alejandro-du/java-email-tutorial/blob/master/spring-mail-example/src/main/java/com/example/javamail/SpringEmailService.java]
  250. [[an-example-web-application]]
  251. An Example Web Application
  252. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  253. Let’s create
  254. a Java web application to test this functionality. The application
  255. consists of a text field where users can type an email address and a
  256. button that will send an email with an attachment to the specified
  257. address.
  258. We are going
  259. to use the https://vaadin.com[Vaadin Framework] which allows us to quickly create a web
  260. application by using only the Java Programming Language. This way, we
  261. don’t need to worry about writing any HTML or JavaScript at all.
  262. Although most
  263. IDEs have plugins to easily generate a new Vaadin project, we are going
  264. to use a Maven archetype to generate the project that you can later
  265. import into your favorite IDE. You can create a new Vaadin project with
  266. Maven using the following command line: 
  267. [source]
  268. ....
  269. mvn archetype:generate -DarchetypeGroupId=com.vaadin -DarchetypeArtifactId=vaadin-archetype-application -DarchetypeVersion=7.6.2
  270. ....
  271. After
  272. specifying a group and artifact id, you can run `mvn clean install` to
  273. compile the project and `mvn jetty:run` to deploy and run the application.
  274. Open your browser and navigate to http://localhost:8080[http://localhost:8080] to see the application
  275. running.
  276. Open the `MyUI.java` file (it should be the only Java file in the project) and change the `init` method to the following:
  277. [source,java]
  278. ....
  279. //... imports mostly from com.vaadin package
  280. public class MyUI extends UI {
  281.    @Override
  282.    protected void init(VaadinRequest vaadinRequest) {
  283.        // the text field where users will specify their email address
  284.        TextField textField = new TextField("Your email:");
  285.        // a button with a click listener that sends the email
  286.        Button button = new Button("Send me the PDF", e -> sendEmail(textField.getValue()));
  287.        // a layout containing the previous components
  288.        VerticalLayout layout = new VerticalLayout(textField, button);
  289.        layout.setMargin(true);
  290.        layout.setSpacing(true);
  291.        setContent(layout); // sets the content for this UI
  292.    }
  293.    ...
  294. }
  295. ....
  296. Add the missing `sendEmail` method and implement it as follows:
  297. [source,java]
  298. ....
  299. private void sendEmail(String to) {
  300.     try {
  301.         // all values as variables to clarify its usage
  302.         InputStream inputStream = getClass().getResourceAsStream("/dock-magazine.pdf");
  303. String from = "sender@test.com";
  304.        String subject = "Your PDF";
  305.         String text = "Here there is your <b>PDF</b> file!";
  306.         String fileName = "file.pdf";
  307.         String mimeType = "application/pdf";
  308.         CommonsEmailService.send(from, to, subject, text, inputStream, fileName, mimeType);
  309.         Notification.show("Email sent");
  310.     } catch (MessagingException | IOException e) {
  311.         e.printStackTrace();
  312.         Notification.show("Error sending the email", Notification.Type.ERROR_MESSAGE);
  313.     }
  314. }
  315. ....
  316.  
  317. At this point
  318. you might want to create the missing `CommonsEmailService` class (or
  319. `SpringMailService` class) and implement the send method as an exercise.
  320. But if you prefer, you can take the example implementation from the
  321. following link: https://github.com/alejandro-du/java-email-tutorial/blob/master/commons-email-example/src/main/java/com/example/javamail/CommonsEmailService.java[https://github.com/alejandro-du/java-email-tutorial/blob/master/commons-email-example/src/main/java/com/example/javamail/CommonsEmailService.java]
  322. Finally, add
  323. a PDF file with the name file.pdf in the resources directory of your
  324. Maven project. You may want to use a small file so that SMTP servers
  325. would be able to accept it.
  326. Stop the
  327. Jetty server if necessary, run `mvn clean install` again, and reload the
  328. web page in the browser. The following is a screenshot of the web
  329. application: image:https://lh5.googleusercontent.com/zcy_LwtCa9TW-sP3phTlczRP9lBvE9ozaxd0Ae4yJghOjQnAjxOlhYp2n5ruLiLlroZ9HW_LEoJN-5qPJI60rXMiFvGuHcibvP5txCMhiS9ZPn1wCMYkN43Zkjqbuw1kTi0nXn_v[screenshot.png,width=622,height=433]
  330. If you have
  331. FakeSMTP running, you should be able to see the email messages sent
  332. through the web application.
  333. [[which-approach-to-use]]
  334. Which Approach to Use?
  335. ~~~~~~~~~~~~~~~~~~~~~~
  336. Choosing an
  337. option depends on different factors. However, I would recommend to use
  338. Spring Email Support if you are developing a Spring application. If not,
  339. go with Apache Commons Email, it offers the most intuitive API. Also,
  340. Apache Commons Email jar is lighter than the spring-context-support jar,
  341. as the later includes more than just the email support classes. Using
  342. the JavaMail API directly may be convenient only when you need lower
  343. level interaction with the mailing system.
  344. You can experiment with the code by downloading the example web applications
  345. from GitHub:
  346. [source]
  347. ....
  348. $ git clone https://github.com/alejandro-du/java-email-tutorial
  349. $ cd java-email-tutorial
  350. $ cd commons-email-example
  351. # (Or cd spring-mail-example)
  352. $ mvn clean install
  353. $ mvn jetty:run
  354. ....
  355.  
  356. Don’t forget to configure run FakeSMTP before using the web application deployed at
  357. http://localhost:8080[http://localhost:8080].