郵件的傳送

Hanyta發表於2024-05-09
  1. 郵件傳送和接收的協議

    SMTP協議 (Simple Mail Transfer Protocol)

    • 屬於TCP/IP協議族。
    • 控制信件的中轉方式,幫助每臺計算機在傳送或中轉信件時找到下一個目的地。
    • SMTP伺服器是遵循SMTP協議的傳送郵件伺服器。

    POP3協議 (Post Office Protocol - Version 3)

    • 屬於TCP/IP協議族。
    • 用於遠端管理在伺服器上的電子郵件,幫助使用者登入到郵件伺服器上、取郵件、刪郵件等。
    • POP伺服器是遵循POP協議的郵件接收伺服器。
  2. 郵件伺服器

    要在網路上實現郵件功能,要使用專門的郵件伺服器。

    • SMTP伺服器 :一般是smtp.xxx.com。如163郵箱smtp.163.com,QQ郵箱smtp.qq.com。
    • POP伺服器:一般是pop.xxx.com。如163郵箱pop.163.com,QQ郵箱pop.qq.com。
  3. 原理圖

  1. 使用者A透過SMTP協議連線到SMTP伺服器,傳送郵件到QQ郵箱的SMTP伺服器;
  2. QQ郵箱的SMTP伺服器,透過SMTP協議將郵件中轉到網易郵箱的SMTP伺服器;
  3. 網易郵箱的SMTP伺服器,將接收到的郵件儲存在B的郵箱賬號的郵箱空間中;
  4. 使用者B透過POP3協議連線到POP伺服器,請求收取郵件;
  5. POP伺服器從B的郵箱賬號的郵箱空間中取出郵件;
  6. POP伺服器將取出來的郵件給B。
  1. 用java簡單郵件傳送實現(qq郵件)

    需要依賴的jar包:

    • javaMail API
    • java Activation Framework
      package com.email;
    
      import com.sun.mail.util.MailSSLSocketFactory;
      import javax.mail.*;
      import javax.mail.internet.InternetAddress;
      import javax.mail.internet.MimeMessage;
      import java.util.Properties;
    
      public class MailSendDemo {
          public static void main(String[] args) throws Exception {
    
              Properties prop = new Properties();
              prop.setProperty("mail.host","smtp.qq.com"); // 設定qq郵件伺服器
              prop.setProperty("mail.transport.protocol","smtp"); // 郵件傳送協議
              prop.setProperty("mail.smtp.auth","true"); // 需要驗證使用者名稱密碼
    
              //關於QQ郵箱,還要設定ssl加密,加上以下程式碼既可,其他郵箱不需要!
              MailSSLSocketFactory sf = new MailSSLSocketFactory();
              sf.setTrustAllHosts(true);
              prop.put("mail.smtp.ssl.enable", "true");
              prop.put("mail.smtp.ssl.socketFactory", sf);
    
              //1.建立定義整個應用程式所需的環境資訊的session物件
              //只有qq郵箱有
              Session session = Session.getDefaultInstance(prop, new Authenticator() {
                  public PasswordAuthentication getPasswordAuthentication(){
                      return new PasswordAuthentication("xxx@qq.com","授權碼");
                  }
              });
              //開啟session的debug模式,這樣就可以檢視到程式傳送Email的執行狀態
              session.setDebug(true);
    
              //2.透過session得到transport物件(傳送郵件的物件)
              Transport ts = session.getTransport();
    
              //3.使用郵箱的使用者名稱和授權碼連上郵件伺服器
              ts.connect("smtp.qq.com", "發信人郵箱@qq.com", "授權碼");
    
              //4.建立郵件
              //需要傳遞session
              MimeMessage message = new MimeMessage(session);
              //發件人
              message.setFrom(new InternetAddress("發信人郵箱@qq.com"));
              //收件人
              message.setRecipient(Message.RecipientType.TO, new InternetAddress("收信人郵箱@qq.com"));
              //設定郵件的主體
              message.setSubject("簡單郵件");
              //設定郵件的內容
              //同樣可以設定樣式
              message.setContent("你好啊", "text/html;charset=UTF-8");
    
              //5.傳送郵件
              ts.sendMessage(message, message.getAllRecipients());
              //6.關閉連線
              ts.close();
          }
      }
    
    
  2. 用java實現複雜郵件傳送,複雜郵件指的是:郵件內容既有文字,又有圖片還有附件。

      /**
       * 建立複雜郵件
       * 相比普通郵件增加:圖片和附件(需要資料處理,設定CID和附件名)、描述資料關係、設定並儲存修改
       *
       * @param session   Session物件
       * @param addresser 發件人
       * @param addressee 收件人
       * @return 複雜郵件
       */
      private MimeMessage makeMixedMessage(Session session, String addresser, String addressee) throws MessagingException {
          MimeMessage message = new MimeMessage(session);
    
          message.setFrom(new InternetAddress(addresser)); // 發件人
          message.setRecipient(Message.RecipientType.TO, new InternetAddress(addressee)); // 收件人
          message.setSubject("Java實現郵件傳送:複雜郵件"); // 郵件主題
    
          // 郵件內容
          // 1、正文
          MimeBodyPart textPart = new MimeBodyPart();
          textPart.setContent("複雜郵件的正文,<img src='cid:a'>附帶一張圖片", "text/html;charset=utf-8");
    
          // 2、圖片
          MimeBodyPart imgPart = new MimeBodyPart();
          DataHandler dh = new DataHandler(new FileDataSource("src\\main\\resources\\img\\a.jpg"));
          imgPart.setDataHandler(dh); // 需要資料處理
          imgPart.setContentID("a"); // 設定CID
    
          // 3、附件
          MimeBodyPart attachPart = new MimeBodyPart();
          DataHandler dh1 = new DataHandler(new FileDataSource("src\\main\\resources\\test\\test.md"));
          attachPart.setDataHandler(dh1); // 需要資料處理
          attachPart.setFileName("file.md"); // 設定附件名,最好包含字尾名
    
          // 描述資料關係:alternative/related/mixed
          MimeMultipart mm = new MimeMultipart();
          mm.addBodyPart(textPart);
          mm.addBodyPart(imgPart);
          mm.addBodyPart(attachPart);
          mm.setSubType("mixed");
    
          // 設定到訊息中,儲存修改
          message.setContent(mm);
          message.saveChanges();
    
          return message;
      }
    
    
  3. Java Web中的郵件傳送

    //servlet
    public class RegisterServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 獲取引數
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String mail = req.getParameter("mail");
    
            User user = new User(username, password, mail);
    
            // 啟動執行緒來傳送郵件,最佳化註冊等待時間
            MailThread mailThread = new MailThread(user);
            mailThread.start(); // start()才是開啟多執行緒,run()只是呼叫方法
    
            req.setAttribute("msg","註冊成功,稍後會收到一封郵件");
            req.getRequestDispatcher("success.jsp").forward(req,resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    //User類
    public class User {
        private String username; // 賬戶
        private String password; // 密碼
        private String mailAddress; // 郵箱地址
    }
    //多執行緒實現郵件傳送
    /*
    多執行緒實現郵件傳送的意義:
    
    如果不用多執行緒,在郵件成功發出後,程式才會繼續執行;
    使用者體驗差,等待時間長;
    使用多執行緒最佳化,在完成註冊後程式繼續執行(如跳轉頁面等),郵件傳送在單獨的執行緒中完成。
    */
    public class MailThread extends Thread {
        final private String host = "smtp.qq.com"; // 伺服器主機號
        final private String authCode = "xxx"; // 授權碼
        final private String addresser = "xxx@qq.com"; // 發件人郵箱
        final private User user;
    
        public MailThread(User user) {
            this.user = user;
        }
    
        @Override
        public void run() {
    
            try {
                // 配置引數
                Properties prop = new Properties();
                prop.setProperty("mail.host", host);
                prop.setProperty("mail.transport.protocol", "smtp");// 郵件協議
                prop.setProperty("mail.smtp.auth", "true"); // 許可權:驗證使用者名稱、授權碼
    
                // SSL加密:QQ郵箱需要設定,透過以下4行程式碼
                MailSSLSocketFactory mssf = null;
                mssf = new MailSSLSocketFactory();
                mssf.setTrustAllHosts(true);
                prop.put("mail.smtp.ssl.enable", "true");
                prop.put("mail.smtp.ssl.socketFactory", mssf);
    
                // 1、建立Session物件
                Session session = Session.getDefaultInstance(prop, new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(addresser, authCode);
                    }
                });
    
                session.setDebug(true); // 開啟Debug模式
    
                // 2、獲得Transport物件
                Transport transport = session.getTransport();
                transport.connect(host, addresser, authCode);
    
    
                // 3、建立郵件:呼叫相應方法(純文字/內嵌資源/帶附件)
                MimeMessage message = new MimeMessage(session);
    
                message.setFrom(new InternetAddress(addresser)); // 發件人
                message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getMailAddress())); // 收件人
                message.setSubject("使用者註冊郵件"); // 郵件主題
    
                String info = "註冊成功,您的使用者名稱:" + user.getUsername() + ",密碼:" + user.getPassword();
    
    
                // 郵件內容
                message.setContent(info, "text/html;charset=utf-8");
    
                // 4、傳送郵件
                transport.sendMessage(message, new InternetAddress[]{new InternetAddress(user.getMailAddress())});
    
                // 關閉郵件伺服器
                transport.close();
            } catch (GeneralSecurityException | MessagingException e) {
                e.printStackTrace();
            }
        }
    }
    //註冊servlet
    <servlet>
        <servlet-name>RegisterServlet</servlet-name>
        <servlet-class>com.test.mail.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/register.do</url-pattern>
    </servlet-mapping>
    

相關文章