1.使用javax.mail, spring的JavaMailSender,springboot傳送郵件

xiaokantianse發表於2020-11-09

一、java發郵件

  1. 電子郵件伺服器:這些郵件伺服器就類似於郵局,它主要負責接收使用者投遞過來的郵件,並把郵件投遞到郵件接收者的電子郵箱中,按功能劃分有兩種型別
    • SMTP郵件伺服器:使用者替使用者傳送郵件和接收外面傳送給本地使用者的郵件
    • POP3/IMAP郵件伺服器:使用者幫助使用者讀取SMTP郵件伺服器接收進來的郵件
  2. 郵件傳輸協議:電子郵件需要在郵件客戶端和郵件伺服器之間,以及兩個郵件伺服器之間進行郵件傳遞,就需遵守一定的規則
    • SMTP協議:全稱為 Simple Mail Transfer Protocol,簡單郵件傳輸協議。它定義了郵件客戶端軟體和SMTP郵件伺服器之間,以及兩臺SMTP郵件伺服器之間的通訊規則
    • POP3協議:全稱為 Post Office Protocol,郵局協議。它定義了郵件客戶端軟體和POP3郵件伺服器的通訊規則
    • IMAP協議:全稱為 Internet Message Access Protocol,Internet訊息訪問協議,它是對POP3協議的一種擴充套件,也是定義了郵件客戶端軟體和IMAP郵件伺服器的通訊規則
  3. 郵件格式:郵件內容的基本格式和具體細節分別是由 RFC822 文件和 MIME 協議定義的
    • RFC822文件中定義的檔案格式包括兩個部分:郵件頭和郵件體
    • ME協議(Multipurpose Internet Mail Extensions )用於定義複雜郵件體的格式,使郵件的內容更加多樣化
  4. 郵件傳送與接收流程
      • 郵件客戶端軟體寫好一封郵件,交到SMTP的QQ郵件伺服器
      • QQ郵箱會解析使用者傳送的郵件,判斷收件地址是否是自己的賬戶,如果收件也是QQ郵箱,會直接存放到自己的儲存空間。如果不是QQ郵箱,而是163郵箱,那麼QQ郵箱會將郵件轉發到163郵箱伺服器,轉發協議也是SMTP
      • 163郵箱伺服器接收到QQ郵箱轉發過來的郵件,會判斷收件地址是否是自己的,如果是自己的賬戶,就會將QQ郵箱轉發過來的郵件存放到自己的內部儲存空間
      • 使用者A將郵件傳送了之後,通知使用者B去指定的郵箱收取郵件。使用者B會通過郵件客戶端軟體先向163郵箱伺服器請求,要求收取自己的郵件
      • 163郵箱伺服器收到使用者B的請求後,會從自己的儲存空間中取出B未收取的郵件
      • 163郵箱伺服器取出使用者B未收取的郵件後,將郵件發給使用者B,最後三步使用者B收取郵件的過程,使用的協議是POP3

二、使用javax.mail傳送郵件(簡單,帶圖片,帶附件,帶圖片和附件)

  • 使用之前應該申請qq郵箱的授權碼(第三方的使用時,替代密碼)

  • qq郵箱郵件伺服器地址和埠(smtp.qq.com 埠465或587)

  • 匯入依賴

  • <!--傳送郵件的jar 1.4 版本會出現javamail.providers 檔案找不見 與其他jar包中檔案衝突-->
    <dependency>
       <groupId>javax.mail</groupId>
       <artifactId>mail</artifactId>
    <version>1.4.4</version>
    </dependency>
    
  1. 郵件的基本資訊類

    @Data
    public class JavaMailInfo {
    
       /**
        * 使用java mail 傳送郵件 郵件的協議有SMTP POP IMAP MIME 等 協議具體內容可自行百度  SMTP 為簡單郵件傳輸協議 比較常用
        */
    
       // 郵件伺服器地址
       private String mailSeverHost;
    
       // 郵件伺服器埠
       private String mailServerPort;
    
       // 郵件傳送者
       private String fromAddress;
    
       // 傳送者使用者名稱
       private String userName;
    
       // 傳送者密碼
       private String password;
    
       // 收件人地址
       private String toAddress;
    
       // 郵件主題
       private String subject;
    
       // 郵件內容
       private String content;
    
       // 圖片地址集合
       private List<String> photoUrlList;
    
       // 附件地址集合
       private List<String> attachList;
    
       /**
        * 獲取郵件會話屬性 ,對郵件Session進行設定 此部分的內容可以通過載入配置檔案的方式進行設定
        * @return
        */
       public Properties getProperties() {
           Properties properties = new Properties();
           properties.put("mail.transport.protocol", "smtp");// 連線協議
           properties.put("mail.smtp.host", this.mailSeverHost);// 主機名
           properties.put("mail.smtp.port", this.mailServerPort);// 埠號
           properties.put("mail.smtp.auth", "true");//設定smtp是否需要認證
           properties.put("mail.smtp.ssl.enable", "true");// 設定是否使用ssl安全連線 ---一般都使用
           properties.put("mail.debug", "true");// 設定是否顯示debug資訊 true 會在控制檯顯示相關資訊
           properties.put("mail.smtp.timeout", 20000);// 超時時間
           return properties;
       }
    
    }
    
  2. 許可權認證類

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class MyJavaMailAuthenticator extends Authenticator {
    
       private String userName = null;
    
       private String password = null;
    
       /**
        * 此類用於儲存授權時使用的使用者名稱和密碼 用於構建郵件Session物件 便於需要認證時郵件Session知道需要使用哪個類驗證
        * 以使用者名稱、密碼的方式訪問那些受到保護的資源,在這裡“資源”就是指郵件伺服器
        * 自定義的類需要繼承Authenticator類 重寫getPasswordAuthentication() 方法 注意導包 需要使用javax.mail包下的相關類
        */
       @Override
       protected PasswordAuthentication getPasswordAuthentication() {
           return new PasswordAuthentication(this.userName, this.password);
       }
    }
    
  3. 傳送郵件工具類

    public class JavaMailSendUtils {
    
       /**
        * 實際使用
        * @param args
        */
       public static void main(String[] args) {
           JavaMailInfo javaMailInfo = new JavaMailInfo();
           javaMailInfo.setMailSeverHost("smtp.qq.com");
           javaMailInfo.setMailServerPort("465");// 465或587(使用ssl)
           javaMailInfo.setFromAddress("發件人");
           javaMailInfo.setUserName("您郵箱使用者名稱");
           javaMailInfo.setPassword("您郵箱授權碼");// 密碼需要使用對應郵箱的授權碼授權碼
           javaMailInfo.setToAddress("收件人");
           javaMailInfo.setSubject("郵件主題");
           javaMailInfo.setContent("郵件內容");
           List<String> photoUrlList = new ArrayList<>();
           photoUrlList.add("圖片1");
           photoUrlList.add("圖片2");
           javaMailInfo.setPhotoUrlList(photoUrlList);
           List<String> attachList = new ArrayList<>();
           attachList.add("附件1");
           attachList.add("附件2");
           javaMailInfo.setAttachList(attachList);
           sendJavaMail(javaMailInfo);
       }
    
       /**
        * 此工具類可根據郵件基本資訊進行郵件的傳送
        */
    
       /**
        * 傳送郵件方法
        * @param javaMailInfo
        * @return
        */
       public static boolean sendJavaMail(JavaMailInfo javaMailInfo) {
           // 獲取郵件session的相關配置引數
           Properties properties = javaMailInfo.getProperties();
           // 建立授權驗證類
           MyJavaMailAuthenticator myJavaMailAuthenticator = new MyJavaMailAuthenticator();
           myJavaMailAuthenticator.setUserName(javaMailInfo.getUserName());
           myJavaMailAuthenticator.setPassword(javaMailInfo.getPassword());
           // 構建郵件Session會話物件 帶不帶default均可 檢視原始碼可知 帶default的是獲取該類的屬性 不帶獲取的是新建立的
           Session mailSession = Session.getDefaultInstance(properties, myJavaMailAuthenticator);
           // 開啟debug properties中設定了此處就無須設定
           // mailSession.setDebug(true);
           // 郵差物件 也可使用靜態方法進行傳送
           Transport transport = null;
           try {
               // 獲取訊息 也就是傳送的內容
               // Message message = createSimpleMail(mailSession, javaMailInfo);
               // Message message = createImageMail(mailSession, javaMailInfo);
               // Message message = createAttachMail(mailSession, javaMailInfo);
               Message message = createPhotoAndAttachMail(mailSession, javaMailInfo);
               // 設定規範 具體是什麼規範呢? 固定寫法
               MailcapCommandMap defaultCommandMap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
               defaultCommandMap.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
               defaultCommandMap.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
               defaultCommandMap.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
               defaultCommandMap.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
               defaultCommandMap.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
               CommandMap.setDefaultCommandMap(defaultCommandMap);
               // 傳送郵件 Transport.send(message); 或者獲取Transport物件傳送
               transport = mailSession.getTransport();
               transport.connect(javaMailInfo.getUserName(), javaMailInfo.getUserName());
               transport.sendMessage(message, message.getAllRecipients());
               System.out.println("郵件傳送成功");
               return true;
           } catch (MessagingException e) {
               e.printStackTrace();
               System.out.println("郵件傳送失敗");
               return false;
           } finally {
               if (null != transport) {
                   try {
                       transport.close();
                   } catch (MessagingException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    
       /**
        * 根據郵件Session和郵件資訊建立郵件內容(文字類 html)
        * @param mailSession
        * @param javaMailInfo
        * @return
        */
       private static Message createSimpleMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
           /**
            * Message是一 個抽象類,我們使用MimeMessage這個子類, 該類是使用MIME型別、MIME資訊頭的 郵箱資訊
            * 資訊頭只能使用US-ASCII字元,而非ASCII字元將通過編碼轉換為ASCII的方式使用
            */
           // 根據郵件session建立訊息物件
           MimeMessage mimeMessage = new MimeMessage(mailSession);
           // 設定發件人 setFrom 和 setReplyTo 均可 有多個發件人使用 addFroms(Address[] addresses)
           mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
           // 設定收件人 收件人型別 Message.RecipientType.TO(接受者) Message.RecipientType.CC(抄送著) Message.RecipientType.BCC(密送者)
           // setRecipients(Message.RecipientType var1, Address[] var2) 設定多個收件人
           mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
           // 設定標題
           mimeMessage.setSubject(javaMailInfo.getSubject(), "text/plain;charset=utf-8");
           // 設定內容 是文字可直接使用setText()
           mimeMessage.setContent(javaMailInfo.getContent(), "text/html;charset=utf-8");
           // 設定傳送時間
           mimeMessage.setSentDate(new Date());
           mimeMessage.saveChanges();
           return mimeMessage;
       }
    
       /**
        * 根據郵件Session和郵件資訊建立郵件內容(圖片類 可多個圖片)
        * @param mailSession
        * @param javaMailInfo
        * @return
        */
       private static Message createImageMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
           /**
            * Message表示一個郵件,messgaes.getContent()返回一個Multipart物件。一個Multipart物件包含一個或多個BodyPart物件,來組成郵件的正文部分(包括附件)
            * Multipart的content-type
            * 總體來說,MIME訊息由訊息頭和訊息體兩大部分組成。現在我們關注的是MIME郵件,因此在以下的討論中姑且稱“訊息”為“郵件”。
            * 郵件頭包含了發件人、收件人、主題、時間、MIME版本、郵件內容的型別等重要資訊。每條資訊稱為一個域,由域名後加“: ”和資訊內容構成,可以是一行,較長的也可以佔用多行。
            * 域的首行必須“頂頭”寫,即左邊不能有空白字元(空格和製表符);續行則必須以空白字元打頭,且第一個空白字元不是資訊本身固有的,解碼時要過濾掉。
            * 郵件體包含郵件的內容,它的型別由郵件頭的“Content-Type”域指出。常見的簡單型別有text/plain(純文字)和text/html(超文字)。有時也會出現的multipart型別,是MIME郵件的精髓。
            * 郵件體被分為多個段,每個段又包含段頭和段體兩部分,這兩部分之間也以空行分隔。常見的multipart型別有三種:multipart/mixed, multipart/related和multipart/alternative。
            * multipart/mixed:附件。
            * multipart/related:內嵌資源。
            * multipart/alternative:純文字與超文字共存。
            */
           MimeMessage mimeMessage = new MimeMessage(mailSession);
           mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
           mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
           mimeMessage.setSubject(javaMailInfo.getSubject(), "text/plain;charset=utf-8");
           List<String> photoUrlList = javaMailInfo.getPhotoUrlList();
           // 建立訊息體 以下方式每個圖片都有一個標題
           MimeMultipart mimeMultipart = new MimeMultipart();
           if (!CollectionUtils.isEmpty(photoUrlList)) {
               for (String photoUrl : photoUrlList) {
                   MimeBodyPart text = new MimeBodyPart();
                   // 設定圖片標題 注意img標籤的引用位置 用cid:開頭
                   String cid = UUID.randomUUID().toString();
                   text.setContent(javaMailInfo.getContent() +"<br/><img src='cid:"+ cid +".jpg'>", "text/html;charset=utf-8");
                   // 使用資料處理器處理圖片
                   MimeBodyPart image = new MimeBodyPart();
                   image.setDataHandler(new DataHandler(new FileDataSource(photoUrl)));
                   image.setContentID(cid);
                   // 描述正文和圖片的關係
                   MimeMultipart photo = new MimeMultipart();
                   photo.addBodyPart(text);
                   photo.addBodyPart(image);
                   photo.setSubType("related");
                   MimeBodyPart mimeBodyPart = new MimeBodyPart();
                   mimeBodyPart.setContent(photo);
                   // 將圖片放入body中
                   mimeMultipart.addBodyPart(mimeBodyPart);
               }
           }
    
           /*// 以下方式所有圖片公用一個標題
           MimeMultipart photo = new MimeMultipart();
           MimeBodyPart text = new MimeBodyPart();
           photo.addBodyPart(text);
           StringBuilder textContent = new StringBuilder(javaMailInfo.getContent());
           if (!CollectionUtils.isEmpty(photoUrlList)) {
               for (String photoUrl : photoUrlList) {
                   // 設定圖片標題 注意img標籤的引用位置 用cid:開頭
                   String cid = UUID.randomUUID().toString();
                   textContent.append("<br/><img src='cid:"+ cid +".jpg'>");
                   // 使用資料處理器處理圖片
                   MimeBodyPart image = new MimeBodyPart();
                   image.setDataHandler(new DataHandler(new FileDataSource(photoUrl)));
                   image.setContentID(cid);
                   // 描述正文和圖片的關係
                   photo.addBodyPart(image);
               }
               photo.setSubType("related");
           }
           text.setContent(textContent.toString(), "text/html;charset=utf-8");*/
           // 設定訊息體
           mimeMessage.setContent(mimeMultipart);
           // mimeMessage.setContent(photo);
           mimeMessage.setSentDate(new Date());
           mimeMessage.saveChanges();
           return mimeMessage;
       }
    
       /**
        * 根據郵件Session和郵件資訊建立郵件內容(附件類 可多個附件)
        * @param mailSession
        * @param javaMailInfo
        * @return
        */
       private static Message createAttachMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
           MimeMessage mimeMessage = new MimeMessage(mailSession);
           mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
           mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
           mimeMessage.setSubject(javaMailInfo.getSubject(), "text/plain;charset=utf-8");
           List<String> attachList = javaMailInfo.getAttachList();
           // 建立訊息體
           MimeMultipart mimeMultipart = new MimeMultipart();
           MimeBodyPart text = new MimeBodyPart();
           text.setContent(javaMailInfo.getSubject(), "text/html;charset=utf-8");
           mimeMultipart.addBodyPart(text);
           if (!CollectionUtils.isEmpty(attachList)) {
               for (String attach : attachList) {
                   // 建立附件
                   MimeBodyPart mimeBodyPart = new MimeBodyPart();
                   DataHandler dataHandler = new DataHandler(new FileDataSource(attach));
                   mimeBodyPart.setDataHandler(dataHandler);
                   mimeBodyPart.setFileName(dataHandler.getName());
                   // 加入最外面的容器
                   mimeMultipart.addBodyPart(mimeBodyPart);
               }
               // 描述關係
               mimeMultipart.setSubType("mixed");
           }
           mimeMessage.setContent(mimeMultipart);
           mimeMessage.setSentDate(new Date());
           mimeMessage.saveChanges();
           return mimeMessage;
       }
    
       /**
        * 根據郵件Session和郵件資訊建立郵件內容(多圖片 多附件)
        * @param mailSession
        * @param javaMailInfo
        * @return
        */
       private static Message createPhotoAndAttachMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
           MimeMessage mimeMessage = new MimeMessage(mailSession);
           mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
           mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
           List<String> photoUrlList = javaMailInfo.getPhotoUrlList();
           // 獲取所有的圖片 公用一個主題
           MimeMultipart photo = new MimeMultipart();
           MimeBodyPart text = new MimeBodyPart();
           photo.addBodyPart(text);
           StringBuilder textContent = new StringBuilder(javaMailInfo.getContent());
           if (!CollectionUtils.isEmpty(photoUrlList)) {
               for (String photoUrl : photoUrlList) {
                   // 設定圖片標題 注意img標籤的引用位置 用cid:開頭
                   String cid = UUID.randomUUID().toString();
                   textContent.append("<br/><img src='cid:"+ cid +".jpg'>");
                   // 使用資料處理器處理圖片
                   MimeBodyPart image = new MimeBodyPart();
                   image.setDataHandler(new DataHandler(new FileDataSource(photoUrl)));
                   image.setContentID(cid);
                   // 描述正文和圖片的關係
                   photo.addBodyPart(image);
               }
               photo.setSubType("related");
           }
           text.setContent(textContent.toString(), "text/html;charset=utf-8");
           // 將圖片包裹成一個body 作為 其內容
           MimeBodyPart content = new MimeBodyPart();
           content.setContent(photo);
           // 獲取所有的附件
           List<String> attachList = javaMailInfo.getAttachList();
           MimeMultipart attach = new MimeMultipart();
           if (!CollectionUtils.isEmpty(attachList)) {
               for (String attachUrl : attachList) {
                   // 建立附件
                   MimeBodyPart mimeBodyPart = new MimeBodyPart();
                   DataHandler dataHandler = new DataHandler(new FileDataSource(attachUrl));
                   mimeBodyPart.setDataHandler(dataHandler);
                   mimeBodyPart.setFileName(dataHandler.getName());
                   // 加入最外面的容器
                   attach.addBodyPart(mimeBodyPart);
               }
           }
           // 將圖片body 和 附件組合
           attach.addBodyPart(content);
           attach.setSubType("mixed");
           mimeMessage.setContent(attach);
           mimeMessage.setSentDate(new Date());
           mimeMessage.saveChanges();
           return mimeMessage;
       }
    }
    

三、使用spring的JavaMailSender傳送郵件(簡單,帶圖片,帶附件,帶圖片和附件,freemarker模板)

  • spring提供的JavaMailSender是對原始的javax.mail進行了簡化

  • 再其使用過程中可以註冊到spring容器中,也可不用註冊

  • 匯入依賴

  • javax.mail的依賴包
    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context-support</artifactId>
    </dependency>
    
  1. 郵件的基本資訊類

    @Data
    public class JavaMailSenderInfo {
    
       // 收件人地址
       private String toAddress;
    
       // 郵件主題
       private String subject;
    
       // 郵件內容
       private String content;
    
       // 是否是html 注意欄位boolean型別 不要用is開頭 idea會生成get,set方法會進行優化 isHtml -> isHtml(),getHtml() -- html -> isHtml(),getHtml()
       private boolean html = false;
    
       // 圖片地址集合
       private List<String> photoList;
    
       // 附件地址集合
       private List<String> attachList;
    
    }
    
  2. 準備mail.propertise配置檔案(也就是設定會話的屬性),檔案放在resource目錄下

    #傳輸協議
    mail.transport.protocol=smtp
    #伺服器主機名
    mail.smtp.host=smtp.qq.com
    #伺服器埠號 465或587(使用ssl)
    mail.smtp.port=465
    #是否進行使用者名稱密碼校驗 配置了否 就不能配置 使用者名稱和密碼 否則會去獲取使用者名稱密碼進行驗證
    mail.smtp.auth=true
    #設定是否使用ssl安全連線 ---一般都使用
    mail.smtp.ssl.enable=true
    #設定是否顯示debug資訊 true 會在控制檯顯示相關資訊
    mail.debug=true
    #設定超時時間
    mail.smtp.timeout=20000
    #編碼格式
    mail.smtp.defaultEncoding=utf-8
    #你的郵箱地址
    mail.smtp.username=xxxxxx@qq.com
    #你的授權碼(第三方使用時代替密碼)
    mail.smtp.password=xxxxxx
    
  3. 載入配置檔案,初始化JavaMailSender

    public class InitJavaMailSender {
       /**
        * 此類的作用是載入配置檔案來建立JavaMailSender物件  JavaMailSenderImpl是該介面的實現類
        * 因此我們需要對JavaMailSenderImpl進行配置 在spring的環境下 我們可以使用載入配置檔案的方式 或者
        * 在spring配置檔案中直接配置該bean(由spring託管)使用時@Autowired直接注入即可
        * <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        * 		<property name="host" value="${mail.smtp.host}" />
        * 		<property name="username" value="${mail.smtp.username}" />
        * 		<property name="password" value="${mail.smtp.password}" />
        * 		<property name="defaultEncoding" value="${mail.smtp.defaultEncoding}" />
        * 		<property name="javaMailProperties">
        * 			<props>
        * 				<prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
        * 				<prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop>
        * 			    ...
        * 			</props>
        * 		</property>
        * 	</bean>
        * 本次採用載入配置檔案的方式
        * 由spring提供 其底層使用的仍然是javax.mail進行郵件的傳送
        * JavaMailSenderImpl 依賴javax.mail 和 spring-context-support包
        */
       // 傳輸協議
       private static String protocol;
       // 伺服器主機名
       private static String host;
       // 伺服器埠號
       private static String port;
       // 是否進行使用者名稱密碼校驗
       private static String auth;
       // 設定是否使用ssl安全連線
       private static String enableSSL;
       // 設定是否顯示debug資訊
       private static String debug;
       // 超時時間
       private static String timeout;
       // 編碼格式
       private static String defaultEncoding;
       // 郵箱地址
       public static String username;
       // 授權碼
       private static String password;
    
       private static JavaMailSenderImpl javaMailSenderImpl;
    
       static {
           init();
       }
    
       private static void init() {
           // 載入配置檔案
           Properties properties = new Properties();
           InputStream resourceAsStream = JavaMailSender.class.getClassLoader().getResourceAsStream("mail.properties");
           try {
               properties.load(resourceAsStream);
               protocol = properties.getProperty("mail.transport.protocol");
               host = properties.getProperty("mail.smtp.host");
               port = properties.getProperty("mail.smtp.port");
               auth = properties.getProperty("mail.smtp.auth");
               enableSSL = properties.getProperty("mail.smtp.ssl.enable");
               debug = properties.getProperty("mail.debug");
               timeout = properties.getProperty("mail.smtp.timeout");
               defaultEncoding = properties.getProperty("mail.smtp.defaultEncoding");
               username = properties.getProperty("mail.smtp.username");
               password = properties.getProperty("mail.smtp.password");
               System.out.println("mail.properties載入成功");
           } catch (IOException e) {
               e.printStackTrace();
               System.out.println("mail.properties載入失敗");
           } finally {
               if (null != resourceAsStream) {
                   try {
                       resourceAsStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    
       /**
        * 使用單例獲取JavaMailSender 雙重檢查既保證的執行緒安全 又保證了效率 又能起到延遲載入的作用
        * @return
        */
       public static JavaMailSender getJavaMailSender() {
           if (null == javaMailSenderImpl) {
               synchronized (InitJavaMailSender.class) {
                   if (null == javaMailSenderImpl) {
                       javaMailSenderImpl = new JavaMailSenderImpl();
                       javaMailSenderImpl.setProtocol(protocol);
                       javaMailSenderImpl.setHost(host);
                       javaMailSenderImpl.setPort(Integer.parseInt(port));
                       javaMailSenderImpl.setDefaultEncoding(defaultEncoding);
                       javaMailSenderImpl.setUsername(username);
                       javaMailSenderImpl.setPassword(password);
                       Properties properties = new Properties();
                       properties.setProperty("mail.smtp.auth", auth);
                       properties.setProperty("mail.smtp.ssl.enable", enableSSL);
                       properties.setProperty("mail.debug", debug);
                       properties.setProperty("mail.smtp.timeout", timeout);
                       javaMailSenderImpl.setJavaMailProperties(properties);
                   }
               }
           }
           return javaMailSenderImpl;
       }
    
    }
    
    
  4. 郵件傳送工具類

    public class JavaMailSenderUtils {
    
       /**
        * 測試傳送郵件 實際中可以在service中使用(若使用的spring配置的方式建立JavaMailSender,則需注入使用)
        * 此處為方便使用main方法
        * @param args
        */
       public static void main(String[] args) {
           JavaMailSenderInfo javaMailSenderInfo = new JavaMailSenderInfo();
           javaMailSenderInfo.setToAddress("發件人");
           javaMailSenderInfo.setSubject("郵件主題");
           javaMailSenderInfo.setContent("郵件內容");
           javaMailSenderInfo.setHtml(true);
           List<String> list = new ArrayList<>();
           list.add("圖片1");
           // list.add("圖片2");
           // list.add("圖片3");
           // list.add("圖片4");
           javaMailSenderInfo.setPhotoList(list);
           javaMailSenderInfo.setAttachList(list);
           // JavaMailSenderUtils.sendSimpleMail(javaMailSenderInfo);
           JavaMailSenderUtils.sendPhotoMail(javaMailSenderInfo);
           // JavaMailSenderUtils.sendAttacheMail(javaMailSenderInfo);
           // JavaMailSenderUtils.sendPhotoAndAttacheMail(javaMailSenderInfo);
    
       }
    
       private static final JavaMailSender javaMailSender = InitJavaMailSender.getJavaMailSender();
    
       private static final String htmlStartStr = "<html><body>";
    
       private static final String htmlEndStr = "</body></html>";
    
       /**
        * 傳送簡單郵件 文字 html
        * @param javaMailSenderInfo
        * @return
        */
       public static boolean sendSimpleMail(JavaMailSenderInfo javaMailSenderInfo) {
           // 建立郵件訊息 簡單郵件可直接使用SimpleMailMessage
           MimeMessage mimeMessage = javaMailSender.createMimeMessage();
           MimeMessageHelper mimeMessageHelper = null;
           try {
               // 建立訊息輔助器 引數二 為true時為多元件 html 等
               mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
               // 設定公共欄位
               setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
               // 文字內容 可指定是否是html
               mimeMessageHelper.setText(javaMailSenderInfo.getContent(), javaMailSenderInfo.isHtml());
               javaMailSender.send(mimeMessage);
               System.out.println("簡單郵件傳送成功");
               return true;
           } catch (MessagingException e) {
               e.printStackTrace();
               System.out.println("簡單郵件傳送失敗");
               return false;
           }
       }
    
       /**
        * 傳送帶圖片的郵件
        * @param javaMailSenderInfo
        * @return
        */
       public static boolean sendPhotoMail(JavaMailSenderInfo javaMailSenderInfo) {
           // 建立郵件訊息 簡單郵件可直接使用SimpleMailMessage
           MimeMessage mimeMessage = javaMailSender.createMimeMessage();
           MimeMessageHelper mimeMessageHelper = null;
           try {
               mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
               setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
               List<String> photoList = javaMailSenderInfo.getPhotoList();
               // html內容
               StringBuilder text = new StringBuilder(htmlStartStr);
               text.append(javaMailSenderInfo.getContent());
               if (!CollectionUtils.isEmpty(photoList)) {
                   for (String photo : photoList) {
                       // 每個圖片建立一個標題吧 每個圖片關聯一個cid
                       String cid = UUID.randomUUID().toString();
                       text.append("<br/><h1>"+ javaMailSenderInfo.getSubject() +"</h1><br/><img src='cid:"+ cid +"'/>");
                       mimeMessageHelper.addInline(cid, new File(photo));
                   }
               }
               // 為什麼會有最後一個圖片圖裂不顯示的問題(求大佬指點)
               // String cid = UUID.randomUUID().toString();
               // mimeMessageHelper.addInline(cid, new File(""));
               text.append(htmlEndStr);
               mimeMessageHelper.setText(text.toString(),true);
               javaMailSender.send(mimeMessage);
               System.out.println("帶圖片的郵件傳送成功");
               return true;
           } catch (MessagingException e) {
               e.printStackTrace();
               System.out.println("帶圖片的郵件傳送失敗");
               return false;
           }
       }
    
       /**
        * 傳送帶附件的郵件
        * @param javaMailSenderInfo
        * @return
        */
       public static boolean sendAttacheMail(JavaMailSenderInfo javaMailSenderInfo) {
           // 建立郵件訊息 簡單郵件可直接使用SimpleMailMessage
           MimeMessage mimeMessage = javaMailSender.createMimeMessage();
           MimeMessageHelper mimeMessageHelper = null;
           try {
               mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
               setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
               List<String> attachList = javaMailSenderInfo.getAttachList();
               // 郵件文字
               mimeMessageHelper.setText(javaMailSenderInfo.getContent(), javaMailSenderInfo.isHtml());
               if (!CollectionUtils.isEmpty(attachList)) {
                   for (String attach : attachList) {
                       // 新增附件(最後一個附件是圖片也存在圖裂的問題,但可下載使用,求大佬指點)
                       FileSystemResource fileSystemResource = new FileSystemResource(attach);
                       // 引數一為附件名稱
                       mimeMessageHelper.addAttachment(fileSystemResource.getFilename(), fileSystemResource);
                   }
               }
               javaMailSender.send(mimeMessage);
               System.out.println("帶附件的郵件傳送成功");
               return true;
           } catch (MessagingException e) {
               e.printStackTrace();
               System.out.println("帶附件的郵件傳送失敗");
               return false;
           }
       }
    
       /**
        * 傳送帶圖片和附件的郵件
        * @param javaMailSenderInfo
        * @return
        */
       public static boolean sendPhotoAndAttacheMail(JavaMailSenderInfo javaMailSenderInfo) {
           // 建立郵件訊息 簡單郵件可直接使用SimpleMailMessage
           MimeMessage mimeMessage = javaMailSender.createMimeMessage();
           MimeMessageHelper mimeMessageHelper = null;
           try {
               mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
               setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
               List<String> photoList = javaMailSenderInfo.getPhotoList();
               // 放入圖片和內容
               StringBuilder text = new StringBuilder(htmlStartStr + javaMailSenderInfo.getContent());
               if (!CollectionUtils.isEmpty(photoList)) {
                   for (String photo : photoList) {
                       String cid = UUID.randomUUID().toString();
                       text.append("<br/><img src='cid:"+ cid +"'>");
                       mimeMessageHelper.addInline(cid, new File(photo));
                   }
               }
               text.append(htmlEndStr);
               mimeMessageHelper.setText(text.toString(),true);
               // 放入附件
               List<String> attachList = javaMailSenderInfo.getAttachList();
               if (!CollectionUtils.isEmpty(attachList)) {
                   for (String attach : attachList) {
                       // 新增附件
                       FileSystemResource fileSystemResource = new FileSystemResource(attach);
                       // 引數一為附件名稱
                       mimeMessageHelper.addAttachment(fileSystemResource.getFilename(), fileSystemResource);
                   }
               }
               javaMailSender.send(mimeMessage);
               System.out.println("帶圖片和附件的郵件傳送成功");
               return true;
           } catch (MessagingException e) {
               e.printStackTrace();
               System.out.println("帶圖片和附件郵件傳送失敗");
               return false;
           }
       }
    
       /**
        * 傳送由freemarker模板技術生成的郵件
        * @param javaMailSenderInfo
        * @return
        */
       public static boolean sendFreemarkerMail(JavaMailSenderInfo javaMailSenderInfo) {
           // 建立郵件訊息 簡單郵件可直接使用SimpleMailMessage
           MimeMessage mimeMessage = javaMailSender.createMimeMessage();
           MimeMessageHelper mimeMessageHelper = null;
           try {
               mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
               setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
               /**
                * 此處沒有實現採用模板技術(可自行探索)
                * 封裝模板所需要的資料
                * 讀取freemarker的模板檔案 xxx.ftl 進行靜態化,生成html形式的字串
                * 將生成好的html字串設定到郵件的正文中
                */
               javaMailSender.send(mimeMessage);
               System.out.println("freemarker模板技術生成的郵件傳送成功");
               return true;
           } catch (MessagingException e) {
               e.printStackTrace();
               System.out.println("freemarker模板技術生成的郵件傳送失敗");
               return false;
           }
       }
    
       /**
        * 設定郵件的公共欄位
        * @param mimeMessageHelper
        * @param javaMailSenderInfo
        * @throws MessagingException
        */
       private static void setMailCommonField(MimeMessageHelper mimeMessageHelper, JavaMailSenderInfo javaMailSenderInfo) throws MessagingException {
           // 發件人
           mimeMessageHelper.setFrom(InitJavaMailSender.username);
           // 收件人 多人用陣列
           mimeMessageHelper.setTo(javaMailSenderInfo.getToAddress());
           // 主題
           mimeMessageHelper.setSubject(javaMailSenderInfo.getSubject());
           // 日期
           mimeMessageHelper.setSentDate(new Date());
       }
    
    }
    
    

四、使用springboot傳送郵件

  • 使用springboot傳送郵件和使用spring提供的JavaMailSender傳送郵件的方式一樣

  • 在yml配置檔案中配置相關的會話資訊後

  • 在service層中直接注入使用即可

  • 匯入依賴

  • <!--springboot整合mail-->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    
  1. 修改配置

    # 郵件的設定 匯入mail啟動包 使用時注入直接JavaMailSender即可
    spring:
       mail:
           protocol: smtp
           host: smtp.qq.com
           port: 465
           default-encoding: utf-8
           username: 郵箱使用者名稱
           password: 郵箱授權碼
           test-connection: true
           properties:
             mail:
               debug: true
               smtp:
                 auth: true
                 timeout: 20000
                 ssl:
                   enable: true
    
  2. 直接在service層中使用即可

    public MailServiceImpl {
       
       @Autowired
       private JavaMailSender javaMailSender;
       
       // 以下程式碼使用即可
       ...
    }
    

相關文章