Java中使用Java?Mail實現(xiàn)郵件服務(wù)功能示例
前言
Java Mail是一個處理郵件服務(wù)的編程接口,提供給開發(fā)者處理電子郵件相關(guān)的編程接口。它是Sun發(fā)布的用來處理email的API,支持多種協(xié)議,如 SMTP、POP3 和 IMAP。它可以方便地執(zhí)行一些常用的郵件傳輸。最近項目中剛好有郵件服務(wù)的需求,之前有用過但是一直沒有總結(jié),借此機會正好總結(jié)一下郵件服務(wù)的實現(xiàn),如果大家項目中有郵件需求可以直接看本篇文章,后面有例子可以直接復(fù)制使用。
一、歷史背景
Java Mail早期api是javax.mail,而現(xiàn)在新版本的api是jakarta.mail,jakarta.mail 旨在與 javax.mail 保持向后兼容,但是會有一些api不同,如果你的新項目或現(xiàn)有項目需要最新的功能和改進,建議使用 jakarta.mail,關(guān)于兩者的區(qū)別如下:
(1)javax.mail 是 JavaMail API 的早期版本,由 Oracle 維護。
(2)jakarta.mail 是 JavaMail API 的新版本,由 Eclipse Foundation 維護。
(3)javax.mail 使用 javax.mail 命名空間,jakarta.mail 使用 jakarta.mail 命名空間。
(4)jakarta.mail是javax.mail的替代品,大部分功能和api是一致的
二、pom依賴
javax.mail依賴
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
jakarta.mail依賴,在處理附件時候還需要多引入一個依賴jakarta.activation
<dependency> <groupId>com.sun.mail</groupId> <artifactId>jakarta.mail</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>com.sun.activation</groupId> <artifactId>jakarta.activation</artifactId> <version>2.0.1</version> </dependency>
Java Mail發(fā)送郵件的核心類是Transport,其中封裝了發(fā)送郵件的多個靜態(tài)重載方法,如send(Message msg)、send(Message msg, Address[] addresses)、send(Message msg, String user, String password)、send(Message msg, Address[] addresses, String user, String password)、
三、API說明
(一)Session (會話)
Session用于創(chuàng)建和管理郵件會話。Session.getInstance() 方法用于獲取一個 Session 實例,該實例可以用來發(fā)送和接收電子郵件。Session.getInstance() 方法接受兩個參數(shù):
Properties props:一個包含郵件會話配置屬性的 Properties 對象。
Authenticator authenticator:一個 Authenticator 對象,用于提供郵件服務(wù)器的身份驗證信息(可選)。
參數(shù)詳解
1. Properties props
Properties 對象用于設(shè)置郵件會話的各種屬性。這些屬性通常包括郵件服務(wù)器的主機名、端口號、是否啟用身份驗證等。以下是一些常用的屬性:
mail.smtp.host:SMTP 服務(wù)器的主機名。
mail.smtp.port:SMTP 服務(wù)器的端口號。
mail.smtp.auth:是否需要身份驗證,值為 true 或 false。
mail.smtp.starttls.enable:是否啟用 STARTTLS 安全連接,值為 true 或 false。
mail.smtp.socketFactory.class:用于創(chuàng)建套接字的類,通常設(shè)置為 javax.net.ssl.SSLSocketFactory。
mail.smtp.socketFactory.fallback:是否允許回退到非安全連接,值為 true 或 false。
mail.smtp.socketFactory.port:用于 SSL 連接的端口號。
2. Authenticator authenticator
Authenticator 對象用于提供郵件服務(wù)器的身份驗證信息。如果需要身份驗證,可以創(chuàng)建一個 Authenticator 子類并重寫 getPasswordAuthentication 方法。
(二)Message(消息)
1.通過session創(chuàng)建消息
Message message = new MimeMessage(session)
2.消息發(fā)送的主題
message.setSubject(郵件標(biāo)題);
3.消息的發(fā)送者
message.setFrom(new InternetAddress(發(fā)件人地址,發(fā)件人名稱));
4.設(shè)置回復(fù)郵件地址,一般是發(fā)件人
message.setReplyTo(InternetAddress.parse(發(fā)件人地址));
5.創(chuàng)建郵件的接收者地址,并設(shè)置到郵件消息中。其中Message.RecipientType.TO 主送,Message.RecipientType.BCC 密送,Message.RecipientType.CC 抄送
message.addRecipient(Message.RecipientType.TO, 收件人地址);
6.消息發(fā)送的時間,一般new Date()取當(dāng)前時間
message.setSentDate(new Date());
7.將MiniMultipart對象設(shè)置為郵件內(nèi)容
message.setContent(multipart對象);
(三)Multipart(容器類)
1.MiniMultipart類是一個容器類,包含MimeBodyPart類型的對象 Multipart multipart = new MimeMultipart(); 2.創(chuàng)建一個包含HTML內(nèi)容的MimeBodyPart設(shè)置HTML內(nèi)容 BodyPart html = new MimeBodyPart(); html.setContent(info.getContent(), "text/html; charset=utf-8"); multipart.addBodyPart(html);
(四)Transport(發(fā)送電子郵件)
1.通過session創(chuàng)建Transport對象 Transport transport = session.getTransport("smtp"); 2.連接郵件服務(wù)器 transport.connect(host, user, password);
(五)TransportListener(郵件監(jiān)聽)
1.通過transport添加郵件監(jiān)聽器,內(nèi)置三種監(jiān)聽方式 transport.addTransportListener(new TransportListener() { @Override public void messageDelivered(TransportEvent transportEvent) {//全部成功 System.out.println("消息全部發(fā)送成功"); } @Override public void messageNotDelivered(TransportEvent transportEvent) {//全部失敗 System.out.println("消息全部發(fā)送失敗"); } @Override public void messagePartiallyDelivered(TransportEvent transportEvent) {//部分成功 System.out.println("消息部分發(fā)送成功"); } }); 2.發(fā)送郵件 Address[] allRecipients = message.getAllRecipients(); transport.sendMessage(message, message.getAllRecipients());
四、示例
以下示例大家可以直接復(fù)制到項目中使用,其中注釋寫的也很明白,一看就懂
(一)創(chuàng)建一個參數(shù)類
import lombok.Data; @Data public class MailInfo { //發(fā)送地址 private String toAddress ; //郵件主題 private String subject ; //郵件內(nèi)容 private String content ; //附件地址 private String fileUrl ; //附件名稱 private String fileName ; }
(二)郵件類
import jakarta.activation.DataHandler; import jakarta.activation.URLDataSource; import jakarta.mail.*; import jakarta.mail.event.TransportEvent; import jakarta.mail.event.TransportListener; import jakarta.mail.internet.*; import lombok.extern.slf4j.Slf4j; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; import java.util.Date; import java.util.Properties; /** * @Author: 你住過的屋檐 * @Date: 2024/11/12 * @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself */ @Slf4j public class MailUtils { private final static String host = "smtp.exmail.qq.com"; //主機名,根據(jù)所選郵件服務(wù)定 private final static String user = "替換成你們發(fā)件用戶郵箱";//發(fā)件用戶郵箱 private final static String password = "替換成你們的授權(quán)碼"; //授權(quán)碼 private final static String personal = "XXX責(zé)任有限公司"; //授權(quán)碼 public static void sendMail(MailInfo info)throws Exception{ Properties p = System.getProperties() ; p.setProperty("mail.smtp.host", host);//主機名 p.setProperty("mail.smtp.auth", "true");//是否需要身份驗證 // 根據(jù)郵件會話屬性和密碼驗證器構(gòu)造一個發(fā)送郵件的session Session session = Session.getInstance(p, new Authenticator(){ protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user,password);//身份信息 } }); // 設(shè)置是否 debug //session.setDebug(true); //創(chuàng)建消息 Message message = new MimeMessage(session); //消息發(fā)送的主題 message.setSubject(info.getSubject()); //消息的發(fā)送者 message.setFrom(new InternetAddress(user,personal)); // 解析多個密送收件地址 InternetAddress[] toAddresses = InternetAddress.parse(info.getToAddress()); //設(shè)置回復(fù)郵件地址,一般是發(fā)件人 message.setReplyTo(InternetAddress.parse(user)); // 創(chuàng)建郵件的接收者地址,并設(shè)置到郵件消息中。 // Message.RecipientType.TO 主送,Message.RecipientType.BCC 密送,Message.RecipientType.CC 抄送 for (InternetAddress address : toAddresses) { message.addRecipient(Message.RecipientType.TO, address); } // 消息發(fā)送的時間 message.setSentDate(new Date()); // MiniMultipart類是一個容器類,包含MimeBodyPart類型的對象 Multipart multipart = new MimeMultipart(); // 創(chuàng)建一個包含HTML內(nèi)容的MimeBodyPart BodyPart html = new MimeBodyPart(); // 設(shè)置HTML內(nèi)容 html.setContent(info.getContent(), "text/html; charset=utf-8"); multipart.addBodyPart(html); // 驗證鏈接是否有效獲取文件流 InputStream attachmentInputStream = downloadAttachment(info.getFileUrl()); //流存在,驗證通過,添加附件 if (attachmentInputStream != null) { // 創(chuàng)建附件部分 MimeBodyPart attachmentPart = new MimeBodyPart(); //通過鏈接生成URLDataSource URLDataSource dataSource = new URLDataSource(new URL(info.getFileUrl())); //添加數(shù)據(jù)處理器 attachmentPart.setDataHandler(new DataHandler(dataSource)); //附件名稱編碼 String fileName = MimeUtility.encodeText(info.getFileName()+new URL(info.getFileUrl()).getPath().substring(new URL(info.getFileUrl()).getPath().lastIndexOf('.') ), "UTF-8", "B");//B:base64 //設(shè)置附件名稱 attachmentPart.setFileName(fileName); //添加附件 multipart.addBodyPart(attachmentPart); } //將MiniMultipart對象設(shè)置為郵件內(nèi)容 message.setContent(multipart); Transport transport = session.getTransport("smtp"); transport.connect(host, user, password); //添加郵件監(jiān)聽器,內(nèi)置三種監(jiān)聽方式 transport.addTransportListener(new TransportListener() { @Override public void messageDelivered(TransportEvent transportEvent) {//全部成功 Address[] validSentAddresses = transportEvent.getValidSentAddresses(); System.out.println("有效發(fā)送成功的郵件:"+ Arrays.toString(validSentAddresses)); Address[] validUnsentAddresses = transportEvent.getValidUnsentAddresses(); System.out.println("有效未發(fā)送成功的郵件:"+ Arrays.toString(validUnsentAddresses)); Address[] invalidAddresses = transportEvent.getInvalidAddresses(); System.out.println("無效的郵件"+ Arrays.toString(invalidAddresses)); System.out.println("消息全部發(fā)送成功"); } @Override public void messageNotDelivered(TransportEvent transportEvent) {//全部失敗 Address[] validSentAddresses = transportEvent.getValidSentAddresses(); System.out.println("有效發(fā)送成功的郵件:"+ Arrays.toString(validSentAddresses)); Address[] validUnsentAddresses = transportEvent.getValidUnsentAddresses(); System.out.println("有效未發(fā)送成功的郵件:"+ Arrays.toString(validUnsentAddresses)); Address[] invalidAddresses = transportEvent.getInvalidAddresses(); System.out.println("無效的郵件"+ Arrays.toString(invalidAddresses)); System.out.println("消息全部發(fā)送失敗"); } @Override public void messagePartiallyDelivered(TransportEvent transportEvent) {//部分成功 Address[] validSentAddresses = transportEvent.getValidSentAddresses(); System.out.println("有效發(fā)送成功的郵件:"+ Arrays.toString(validSentAddresses)); Address[] validUnsentAddresses = transportEvent.getValidUnsentAddresses(); System.out.println("有效未發(fā)送成功的郵件:"+ Arrays.toString(validUnsentAddresses)); Address[] invalidAddresses = transportEvent.getInvalidAddresses(); System.out.println("無效的郵件"+ Arrays.toString(invalidAddresses)); System.out.println("消息部分發(fā)送成功"); } }); Address[] allRecipients = message.getAllRecipients(); transport.sendMessage(message, message.getAllRecipients()); System.out.println("收件人:"+ Arrays.toString(allRecipients)); } /** * 獲取文件輸入流 * @param url * @return * @throws Exception */ private static InputStream downloadAttachment(String url) throws Exception { URL urlObj = new URL(url); HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { return connection.getInputStream(); } else { throw new RuntimeException("文件地址異常,code碼: " + responseCode); } } public static void main(String[] args) { String mail = "xxx@qq.com"; //收件人地址,多個按照英文逗號分割就是群發(fā) String title = "一封有技術(shù)的郵件"; String fileUrl="https://xxx.pdf"; String fileName="附件"; String content ="<!DOCTYPE html>\n" + "<html lang=\"zh-CN\">\n" + "<head>\n" + " <meta charset=\"UTF-8\">\n" + " <style> \n" + "\t\tbody {\n" + " font-family: Arial;\n" + " line-height: 1.5;\n" + " margin: 0;\n" + " }\n" + " .container {\n" + " margin: auto;\n" + "\t\t\tfont-size:12px;\n" + " }\n" + " .signature {\n" + " margin-top: 20px;\n" + " }\n" + " .date {\n" + " text-align: right;\n" + " margin-top: 20px;\n" + " }\n" + "\t\t.content{text-indent: 2em;}\n" + " </style>\n" + "</head>\n" + "<body>\n" + " <div class=\"container\">\n" + " <p>尊敬的先生:</p>\n" + " <p class='content'>您好!</p>\n" + " <p class='content'>我代表XXX公司,給您發(fā)送一封郵件。希望您開心。</p>\n" + " <div class=\"signature\">\n" + " <p class='content'>敬請查收,恭祝商祺。</p>\n" + " <p style='text-align: right;'>XXX有限公司</p>\n" + " </div>\n" + " <div class=\"date\">\n" + " <p>2024-11-12</p>\n" + " </div>\n" + " </div>\n" + "</body>\n" + "</html>"; MailInfo info = new MailInfo(); info.setToAddress(mail); info.setSubject(title); info.setContent(content); info.setFileUrl(fileUrl); info.setFileName(fileName); try { MailUtils.sendMail(info); } catch (Exception e) { System.out.print("'"+title+"'的郵件發(fā)送失??!"); e.printStackTrace(); } } }
(三)main執(zhí)行結(jié)果
收件人:[xxx@qq.com] 有效發(fā)送成功的郵件:[xxx@qq.com] 有效未發(fā)送成功的郵件:null 無效的郵件null 消息全部發(fā)送成功 進程已結(jié)束,退出代碼為 0
(四)收件結(jié)果
總結(jié)
到此這篇關(guān)于Java中使用Java Mail實現(xiàn)郵件服務(wù)功能示例的文章就介紹到這了,更多相關(guān)Java Mail實現(xiàn)郵件服務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot打包無法讀取yml、properties等配置文件的解決
這篇文章主要介紹了springboot打包無法讀取yml、properties等配置文件的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04解決Callable的對象中,用@Autowired注入別的對象失敗問題
這篇文章主要介紹了解決Callable的對象中,用@Autowired注入別的對象失敗問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07基于idea操作hbase數(shù)據(jù)庫并映射到hive表
這篇文章主要介紹了用idea操作hbase數(shù)據(jù)庫,并映射到hive,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03MyBatis?Plus實現(xiàn)中文排序的兩種有效方法
在MyBatis?Plus項目開發(fā)中,針對中文數(shù)據(jù)的排序需求是一個常見的挑戰(zhàn),尤其是在需要按照拼音或特定語言邏輯排序時,本文整合了兩種有效的方法,旨在幫助開發(fā)者克服MyBatis?Plus在處理中文排序時遇到的障礙,需要的朋友可以參考下2024-08-08JavaWeb實戰(zhàn)之編寫單元測試類測試數(shù)據(jù)庫操作
這篇文章主要介紹了JavaWeb實戰(zhàn)之編寫單元測試類測試數(shù)據(jù)庫操作,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)javaweb的小伙伴們有很大的幫助,需要的朋友可以參考下2021-04-04