Trong bài này tôi sẽ hướng dẫn các bạn gửi email sử dụng JavaMail API (javax.mail) và thư viện Apache commons mail.
Nội dung
Gửi mail sử dụng JavaMail API của thư viện javax.mail
Giới thiệu
JavaMail là một API được sử dụng để soạn, gửi và đọc các tin điện tử (email).
JavaMail API cung cấp độc lập về giao thức và độc lập với nền tảng cho việc gửi và nhận email. Nghĩa là bạn không cần bận tâm về giao thức gửi nhận mail là SMTP, POP, IMAP, …
Các gói javax.mail và javax.mail.activation là 2 lớp lõi JavaMail API, nó cung cấp các phương thức hỗ trợ việc gởi và nhận mail.
Có nhiều cách để gửi email sử dụng JavaMail API, trong phần tiếp theo của bài viết này, tôi hướng dẫn các bạn gửi mail thông qua giao thức SMTP.
Chúng ta cần một SMTP Server chịu trách nhiệm gửi mail. Có thể sử dụng một trong các kỹ thuật sau để có được máy chủ SMTP:
- Cài đặt và sử dụng bất kỳ máy chủ SMTP như: MailCatcher, Postcast server, Apache James server, cmail server, …
- Sử dụng máy chủ SMTP được cung cấp bởi nhà cung cấp máy chủ lưu trữ, ví dụ: stablehost, Hostinger, …
- Sử dụng Máy chủ SMTP được cung cấp bởi các công ty khác ví dụ: máy chủ SMTP của Google (Gmail), Yandex, …
Trong bài này, chúng ta sẽ học 2 cách tiếp cận để gửi email sử dụng JavaMail API là: giả lập SMTP sử dụng MailCatcher và sử dụng SMTP Server được cung cấp bởi Google. Xem phần phục lục ở phần cuối của bài viết.
Để gửi mail sử dụng JavaMail API, chúng ta cần thêm 2 thư viện sau vào project:
- mail.jar
- activation.jar
Nếu bạn khai báo thư viện Apache commons mail trong file pom.xml thì không cần add 2 thư viện này bằng tay.
Cấu trúc của một email
Thông thường một email có cấu trúc như sau:
- To : địa chỉ email người nhận, có thể gửi cho nhiều người.
- Cc: Người nhận Cc thường thêm vào tin nhắn cho mục đích thông báo. Ví dụ, nếu dự án ABC ảnh hưởng đến dự án của bạn, bạn có thể nhận Cc thư về dự án ABC thậm chí khi không cần thiết cho bạn để phản hồi những tin nhắn này.
- Bcc: Bcc là sao chép ẩn danh. Khi bạn một người nhận ẩn danh vào tin nhắn, sẽ không ai có thể biết rằng họ đang nhận được một bản sao của tin nhắn nhưng bạn và người đó.
- Subject : tiêu đề của email.
- Content : Nội dung thư. Nội dung này có thể bao gồm: văn bản, html, image, …
- Attachment : tập tin sẽ được gửi kèm theo email.
- Ngoài ra còn có ReplyTo : email người nhận mặc định khi người dùng Nhấn Reply.
Ví dụ gửi mail sử dụng JavaMail API
Trong các ví dụ gửi mail bên dưới, chúng ta sẽ sử dụng SMTP Server được cung cấp bởi google.
Sau khi bạn đăng ký tài khoản Gmail và tạo mật khẩu ứng dụng. Chúng ta thiết lập thông tin cấu hình như sau:
package com.gpcoder; public class MailConfig { public static final String HOST_NAME = "smtp.gmail.com"; public static final int SSL_PORT = 465; // Port for SSL public static final int TSL_PORT = 587; // Port for TLS/STARTTLS public static final String APP_EMAIL = "gpcodervn@gmail.com"; // your email public static final String APP_PASSWORD = "ihzgdgiy3udgemdjhhw"; // your password public static final String RECEIVE_EMAIL = "gpcodervn@gmail.com"; }
Gửi mail đơn giản sử dụng SMTP của Gmail với kết nối SSL (Secure Sockets Layer)
package com.gpcoder.javaxmail; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.gpcoder.MailConfig; public class SendMailSSL { public static void main(String[] args) { // Get properties object Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", MailConfig.HOST_NAME); props.put("mail.smtp.socketFactory.port", MailConfig.SSL_PORT); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.port", MailConfig.SSL_PORT); // get Session Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD); } }); // compose message try { MimeMessage message = new MimeMessage(session); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(MailConfig.RECEIVE_EMAIL)); message.setSubject("Testing Subject"); message.setText("Welcome to gpcoder.com"); // send message Transport.send(message); System.out.println("Message sent successfully"); } catch (MessagingException e) { throw new RuntimeException(e); } } }
Thực thi chương trình trên, bạn sẽ nhận được email với nội dung như sau:
Lưu ý: nếu bạn không gửi mail được, hãy kiểm tra chương trình diệt virus hay firewall có chặn không.
Gửi mail đơn giản sử dụng SMTP của Gmail với kết nối TSL (Transport Layer Security)
Việc gửi mail sử dụng kết nối TSL tương tự như kết nối SSL, chỉ khác biệt ở thông tin kết nối như sau:
package com.gpcoder.javaxmail; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.gpcoder.MailConfig; public class SendMailTLS { public static void main(String[] args) { // Get properties object Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", MailConfig.HOST_NAME); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.port", MailConfig.TSL_PORT); // get Session Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD); } }); // compose message try { MimeMessage message = new MimeMessage(session); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(MailConfig.RECEIVE_EMAIL)); message.setSubject("Testing Subject"); message.setText("Welcome to gpcoder.com"); // send message Transport.send(message); System.out.println("Message sent successfully"); } catch (MessagingException e) { throw new RuntimeException(e); } } }
Thực thi chương trình trên, ta có cùng kết quả như gửi mail theo kết nối SSL.
Gửi mail có đính kèm tập tin
package com.gpcoder.javaxmail; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import com.gpcoder.MailConfig; public class SendAttachment { public static void main(String[] args) { // 1) get the session object Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", MailConfig.HOST_NAME); props.put("mail.smtp.socketFactory.port", MailConfig.SSL_PORT); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.port", MailConfig.SSL_PORT); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD); } }); // 2) compose message try { MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(MailConfig.APP_EMAIL)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(MailConfig.RECEIVE_EMAIL)); message.setSubject("Sending email with attachment"); // 3) create MimeBodyPart object and set your message text BodyPart messageBodyPart1 = new MimeBodyPart(); messageBodyPart1.setText("Welcome to gpcoder.com"); // 4) create new MimeBodyPart object and set DataHandler object to this object MimeBodyPart messageBodyPart2 = new MimeBodyPart(); String filename = "data/myfile.txt"; DataSource source = new FileDataSource(filename); messageBodyPart2.setDataHandler(new DataHandler(source)); messageBodyPart2.setFileName(filename); // 5) create Multipart object and add MimeBodyPart objects to this object Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart1); multipart.addBodyPart(messageBodyPart2); // 6) set the multiplart object to the message object message.setContent(multipart); // 7) send message Transport.send(message); System.out.println("Message sent successfully"); } catch (MessagingException ex) { ex.printStackTrace(); } } }
Thực thi chương trình trên, ta có kết quả như sau:
Gửi mail có định dạng HTML
package com.gpcoder.javaxmail; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.gpcoder.MailConfig; public class SendHtmlEmail { public static void main(String[] args) { // 1) get the session object Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", MailConfig.HOST_NAME); props.put("mail.smtp.socketFactory.port", MailConfig.SSL_PORT); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.port", MailConfig.SSL_PORT); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD); } }); // 2) compose message try { MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(MailConfig.APP_EMAIL)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(MailConfig.RECEIVE_EMAIL)); // 3) create HTML content message.setSubject("HTML Message"); String htmlContent = " <h1>Welcome to <a href=\"gpcoder.com\">GP Coder</a></h1> " + "<img src=\"https://gpcoder.com/wp-content/uploads/2017/10/Facebook_Icon_GP_2-300x180.png\" " + " width=\"300\" " + " height=\"180\" " + " border=\"0\" " + " alt=\"gpcoder.com\" />"; message.setContent(htmlContent, "text/html"); // 4) send message Transport.send(message); System.out.println("Message sent successfully"); } catch (MessagingException ex) { ex.printStackTrace(); } } }
Thực thi chương trình trên, ta có kết quả như sau:
Gửi mail sử dụng thư viện Commons mail
Giới thiệu
Commons Email là một thư viện Java của Apache liên quan tới Email. Trong thực tế, để làm việc với Email trong Java bạn có thể sử dụng gói JavaMail API đã được tích hợp sẵn trong JDK6. Commons Email giúp bạn làm việc với JavaMail API dễ dàng hơn, nó không thay thế cho JavaMail API.
Trước khi đi vào phần vào ví dụ, bạn cần tạo project maven và thêm thư viện Apache Commons Email vào project như sau:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-email --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-email</artifactId> <version>1.5</version> </dependency>
Ví dụ gửi mail sử dụng thư viện Commons mail
Gửi mail đơn giản sử dụng SMTP của Gmail với kết nối SSL (Secure Sockets Layer)
package com.gpcoder.apache_common; import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail; import com.gpcoder.MailConfig; public class SendMailSSL { public static void main(String[] args) throws EmailException { // Tạo đối tượng Email Email email = new SimpleEmail(); // Cấu hình thông tin Email Server email.setHostName(MailConfig.HOST_NAME); email.setSmtpPort(MailConfig.SSL_PORT); email.setAuthenticator(new DefaultAuthenticator(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD)); email.setSSLOnConnect(true); // Người gửi email.setFrom(MailConfig.APP_EMAIL); // Người nhận email.addTo(MailConfig.RECEIVE_EMAIL); // Tiêu đề email.setSubject("Testing Subject"); // Nội dung email email.setMsg("Welcome to gpcoder.com"); // send message email.send(); System.out.println("Message sent successfully"); } }
Thực thi chương trình trên, ta có kết quả tương tự như việc gửi mail thông qua JavaMail API.
Gửi mail đơn giản sử dụng SMTP của Gmail với kết nối TSL (Transport Layer Security)
package com.gpcoder.apache_common; import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail; import com.gpcoder.MailConfig; public class SendMailTLS { public static void main(String[] args) throws EmailException { // Tạo đối tượng Email Email email = new SimpleEmail(); // Cấu hình thông tin Email Server email.setHostName(MailConfig.HOST_NAME); email.setSmtpPort(MailConfig.TSL_PORT); email.setAuthenticator(new DefaultAuthenticator(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD)); email.setTLS(true); // Người gửi email.setFrom(MailConfig.APP_EMAIL); // Người nhận email.addTo(MailConfig.RECEIVE_EMAIL); // Tiêu đề email.setSubject("Testing Subject"); // Nội dung email email.setMsg("Welcome to gpcoder.com"); // send message email.send(); System.out.println("Message sent successfully"); } }
Thực thi chương trình trên, ta có kết quả tương tự như việc gửi mail thông qua JavaMail API.
Gửi mail có đính kèm tập tin
package com.gpcoder.apache_common; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.EmailAttachment; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.MultiPartEmail; import com.gpcoder.MailConfig; public class SendAttachment { public static void main(String[] args) throws EmailException, MalformedURLException { // Tạo một đối tượng đính kèm String filename = "data/myfile.txt"; EmailAttachment attachment = new EmailAttachment(); attachment.setPath(filename); attachment.setURL(new URL("https://gpcoder.com")); attachment.setDisposition(EmailAttachment.ATTACHMENT); attachment.setDescription("Gp coder"); attachment.setName("gpcoder"); // Tạo đối tượng Email MultiPartEmail email = new MultiPartEmail(); // Cấu hình email.setHostName(MailConfig.HOST_NAME); email.setSmtpPort(MailConfig.SSL_PORT); email.setAuthenticator(new DefaultAuthenticator(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD)); email.setSSLOnConnect(true); // Người gửi email.setFrom(MailConfig.APP_EMAIL); // Người nhận email.addTo(MailConfig.RECEIVE_EMAIL); // Tiêu đề email.setSubject("Testing Subject"); // Nội dung email email.setMsg("Welcome to gpcoder.com"); // Thêm đính kèm email.attach(attachment); // Gửi email email.send(); System.out.println("Sent!"); } }
Thực thi chương trình trên, ta có kết quả tương tự như việc gửi mail thông qua JavaMail API.
Gửi mail có định dạng HTML
package com.gpcoder.apache_common; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.ImageHtmlEmail; import org.apache.commons.mail.resolver.DataSourceUrlResolver; import com.gpcoder.MailConfig; public class SendHtmlEmail { public static void main(String[] args) throws EmailException, MalformedURLException { // Tạo đối tượng Email ImageHtmlEmail email = new ImageHtmlEmail(); // Cấu hình thông tin Email Server email.setHostName(MailConfig.HOST_NAME); email.setSmtpPort(MailConfig.SSL_PORT); email.setAuthenticator(new DefaultAuthenticator(MailConfig.APP_EMAIL, MailConfig.APP_PASSWORD)); email.setSSLOnConnect(true); // Người gửi email.setFrom(MailConfig.APP_EMAIL); // Người nhận email.addTo(MailConfig.RECEIVE_EMAIL); // Tiêu đề email.setSubject("Testing Subject"); // Định nghĩa URL cơ sở để xác định đúng vị trí nguồn dữ liệu (img,..) // (Trong trường hợp nó có đường dẫn tương đối, ví dụ thẻ img như bên dưới) URL url = new URL("https://gpcoder.com"); email.setDataSourceResolver(new DataSourceUrlResolver(url)); // Nội dung email String htmlContent = " <h1>Welcome to <a href=\"gpcoder.com\">GP Coder</a></h1> " + "<img src=\"wp-content/uploads/2017/10/Facebook_Icon_GP_2-300x180.png\"" + " width=\"300\" " + " height=\"180\" " + " border=\"0\" " + " alt=\"gpcoder.com\" />"; email.setHtmlMsg(htmlContent); // Nội dung thay thế: // Trong trường hợp chương trình đọc email của người nhận ko hỗ trợ HTML email.setTextMsg("Your email client does not support HTML messages"); // send message email.send(); System.out.println("Message sent successfully"); } }
Thực thi chương trình trên, ta có kết quả tương tự như việc gửi mail thông qua JavaMail API.
Phụ lục
Sử dụng SMTP Server được cung cấp bởi Google
Để sử dụng SMTP Server được cung cấp bởi Google, trước hết bạn phải có tài khoản Gmail, nếu chưa có hãy đăng ký tại đây.
Tiếp theo sẽ thiết lập để lấy mật khẩu ứng của Google. Bạn cần bật tính năng bảo vệ 2 lớp của Google (2-Step Verification) tại trang https://myaccount.google.com/, bạn có thể bỏ qua bước này nếu tài khoản Gmail của bạn đã bật tính năng này.
Bạn nên bật tính năng bảo vệ 2 lớp để tránh mất thông tin tài khoản, có thể cấp cho mỗi ứng dụng một mật khẩu riêng để truy cập gmail, khi không cần sử dụng bạn dễ dàng hủy bỏ, …
Tại đây, bạn vào phần Đăng nhập vào Google (Signing in to Google) -> chọn bật chức năng bảo mật hai lớp.
Sau khi bật xong, vào lại phần Đăng nhập vào Google (Signing in to Google) như ở trên và chọn Mật khẩu ứng dụng.
Sau đó chọn Select app là Mail và Select device chọn bất kỳ, rồi ấn Generate.
Sau đó google sẽ sinh ra một dãy ký tự ngẫu nhiên, đây chính là mật khẩu SMTP của bạn. Hãy copy nó và sử dụng trong ứng dụng của bạn.
Giả lập SMTP Server với MailCatcher cho việc test gửi và nhận email
MailCatcher là gì ?
MailCatcher là một Ruby Gem chạy một SMTP Server đơn giản, có thể bắt bất kỳ message nào được gửi đi trên máy local và hiển thị nó trên giao diện web.
Bạn chỉ cần chạy MailCatcher, sau đó cấu hình gửi email thông qua địa chỉ smtp://127.0.0.1:1025 thay cho SMTP server, sau đó có thể xem các thư được gửi đi tại địa chỉ http://127.0.0.1:1080. Mặc định, MailCatcher sẽ sử dụng 2 địa chỉ này, tuy nhiên bạn có thể thay đổi chúng.
Trong quá trình phát triển, bạn chỉ cần thử các chức năng và email gửi đi sẽ xem được nội dung trưc tiếp trên nền web (email chỉ hỗ sợ một số css, trên browser thì email được hiển thị dưới dạng HTML và CSS nên giao diện có thể khác với email được gửi đi).
Cài đặt MailCatcher
Cài đặt ruby và rubygems: Truy cập vào địa chỉ https://rubyinstaller.org/ -> chọn Download -> cài đặt Ruby trên Window.
Sau khi cài xong Ruby, một cửa sổ CMD được mở ra -> bạn cài đặt lần lượt các Option từ 1-3.
MSYS2 là một development kit của Ruby, dung lượng khoảng 200MB, bạn có thể download và cài riêng.
Cài đặt MailCatcher:
- Mở cmd lên và gõ lệnh : gem install mailcatcher
- Sau khi cài xong, chạy mailcatcher bằng lệnh: mailcatcher
- Xem danh sách mail đã gửi: mở web browser -> truy cập vào địa chỉ http://localhost:1080/ -> bạn sẽ thấy giao diện đọc thư của MailCatcher.
Bây giờ bạn có thể gửi email thông qua địa chỉ smtp://127.0.0.1:1025. Mỗi khi email được gửi, bạn sẽ thấy email gửi đi sẽ hiện trên địa chỉ trên giao diện đọc thư của MailCatcher ở trên.
Có thể xem thêm các lệnh liên quan tới Mailcatcher bằng cách gõ mailcatcher –help trên cmd.
Cú pháp đầy đủ của MailCatcher: mailcatcher [options]
- –ip IP : Gán địa chỉ IP cho cả 2 server SMTP và HTTP.
- –smtp-ip IP : Gán địa chỉ IP cho SMTP server.
- –smtp-port PORT : Gán cổng cho SMTP server.
- –http-ip IP : Gán địa chỉ IP cho HTTP server.
- –http-port PORT : Gán cổng cho HTTP server.
- -f, –foreground : Run in foreground. Bạn có thể thoát khỏi bằng lệnh Ctrl+C.
- -v, –verbose : Be more verbose.
- -h, –help : Hiển thị thông tin trợ giúp.
Ví dụ: nếu muốn start server HTTP ở cổng 8080, chúng ta sẽ gõ lệnh sau: mailcatcher –http-port 8080
Sử dụng MailCatcher
Start server MailCatcher: mailcatcher
Ví dụ gửi mail đến địa chỉ SMTP Server của MailCatcher 127.0.0.1:1025.
package com.gpcoder.mail_catcher; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail; import com.gpcoder.MailConfig; public class SendToMailCatcher { public static void main(String[] args) throws EmailException { // Tạo đối tượng Email Email email = new SimpleEmail(); // Cấu hình thông tin Email Server email.setHostName("127.0.0.1"); email.setSmtpPort(1025); // Người gửi email.setFrom(MailConfig.APP_EMAIL); // Người nhận email.addTo(MailConfig.RECEIVE_EMAIL); // Tiêu đề email.setSubject("Testing Subject"); // Nội dung email email.setMsg("Welcome to gpcoder.com"); // send message email.send(); System.out.println("Message sent successfully"); } }
Thực thi chương trình trên. Sau đó, mở web browser và truy cập địa chỉ http://localhost:1080/. Ta có kết quả như sau:
Bạn hãy thay đổi địa chỉ SMTP ở các ví dụ trên và chạy thử để kiểm tra kết quả nhé.
Source code
Source code sử dụng trong bài viết, các bạn xem trên github nhé:
https://github.com/gpcodervn/Java-Tutorial/tree/master/JavaMailTutorial
Tài liệu tham khảo:
- https://www.javatpoint.com/java-mail-api-tutorial
- https://www.tutorialspoint.com/javamail_api/index.htm
- https://o7planning.org/vi/10147/huong-dan-su-dung-java-commons-email
- Mail Catcher
- Commons Email