Java實現QQ郵件發送客戶端


目錄

一、前言:QQ郵件發送程序

二、封裝SMTP操作

三、實現多線程接收

四、QQ郵件客戶端界面設計

    1、連接按鈕

    2、發送按鈕 

五、QQ郵件發送效果演示

六、總結


一、前言:QQ郵件發送程序

在上一篇《Java網絡編程:實現QQ郵件發送客戶端》,我們解決了telnet終端發送郵件誤操作帶來的麻煩,實現了自己的簡單Java界面進行發送QQ郵件,界面可直接與smtp.qq.com服務器端建立連接,通過命令方式發送郵件信息。

這一篇為QQ郵件發送客戶端程序設計的下篇,將實現更加完善的功能,不用命令發送方式,類似日常發送郵件,直接編寫郵件標題、內容,然后直接發送即可,基本實現了QQ郵件發送客戶端的功能,操作更加簡便,實現自己的QQ郵件發送端,以后就用這個啦。

二、封裝SMTP操作

原來的終端發送逐步操作如下:

HELO hostname   //回車,hostname可以是IP或其他隨意別名
AUTH LOGIN //回車后,先粘貼base64程序編碼的完整郵箱名並回車;再粘貼base64編碼的授權碼並回車
 MAIL FROM:<czh_charzeus@qq.com>   //在這里填寫自己的郵箱地址,用於發送郵件(注意冒號后面別有空格)
RCPT TO:<czh_charzeus@qq.com>  //接收方的郵箱,在這里暫時填寫和上面一樣的郵箱地址,即自己發送郵件給自己,驗證是否成功
DATA       //回車,接下來開始發送郵件頭相關內容
Subject: the simple mail     // 郵件的標題,回車 //在這里再多發送一行空行,來分隔郵件內容,下面就是郵件正文內容
Hello,the mail content! 測試發送郵件! //控制台中中文會變成?的亂碼,但不影響接受者接收到中文內容
.   //在郵件正文發送完畢后,單獨用一行輸入一個小圓點,作為結束標志,然后回車
QUIT   //結束通信(含4次握手斷開)

因此,我們要避免這種繁瑣的命令形式,只需要將每個語句封裝到發送程序里面,在用戶界面則無需進行命令的輸入,只需要輸入內容。

實現的方法很簡單,只需要在發送按鈕中,把命令加進去就可以,如下:

tcpMailClient.send("HELO friend"); tcpMailClient.send("auth login"); String userNameBase64= encode(senderMail); tcpMailClient.send(userNameBase64); String authCode = encode("你的授權碼"); tcpMailClient.send(authCode); String msg = "mail from:<"+senderMail+">"; tcpMailClient.send(msg); msg = "rcpt to:<"+receiverMail+">"; tcpMailClient.send(msg); tcpMailClient.send("data"); msg="from:"+senderMail; tcpMailClient.send(msg); msg="to:"+receiverMail; tcpMailClient.send(msg); msg="subject:"+sub; tcpMailClient.send(msg); tcpMailClient.send("\n"); // tcpMailClient.send("這是一封測試java客戶端自動發送功能的郵件。");
tcpMailClient.send(content); tcpMailClient.send("."); tcpMailClient.send("quit");

從代碼可以看到,當發送按鈕一點擊后,程序會執行所有語句,我們從上一篇知道,郵件服務器也會返回信息,所以QQ客戶端需要使用多線程的技術,來處理返回信息,避免單線程阻塞導致發送不成功。

三、實現多線程接收

根據前面分析,將客戶端接收的功能交給一個線程處理,就能夠達到目的,不會因為接收語句阻塞使得主進程卡住。

所以,將線程放到連接按鈕里面為好,在成功連接服務器之后,程序就啟動線程,時機正好。連接按鈕中的線程代碼如下:

//用於接收服務器信息的單獨線程
readThread = new Thread(()->{ String receiveMsg=null;//從服務器接收一串字符
    while ((receiveMsg=tcpMailClient.receive())!=null){ String msgTemp = receiveMsg; Platform.runLater(()->{ taDisplay.appendText(msgTemp+"\n"); }); } Platform.runLater(()->{ taDisplay.appendText("對話已關閉!\n"); }); }); readThread.start();

程序執行發送每一條命令語句的速度比我們自己輸入發送要快許多,為了避免QQ郵件接收服務器無法及時響應出錯,程序自動發送過程中需要設置一定的睡眠等待時間,在send方法設置等待200ms或者500ms。

QQ郵件客戶端實現代碼可見上一篇Java網絡編程:實現QQ郵件發送客戶端,這里不再重復介紹。

public void send(String msg){ //輸出字符流,由socket調用系統底層函數,經網卡發送字節流
 pw.println(msg); try { //進行郵件交互,發送smtp指令之間應該暫停一段時間
        Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }

四、QQ郵件客戶端界面設計

界面的設計與以往類似,可以根據自己的需求設計不同的界面風格,可參考本文前言或者總結部分的系列文章進行實現。這里給出關鍵按鈕的完整代碼。

1、連接按鈕

//連接按鈕
btConn.setOnAction(event -> {
    String ip=ipAddress.getText().trim();
    String port=tfport.getText().trim();
    try {
 
        tcpMailClient = new TCPMailClient(ip, port);
 
 
        //成功連接服務器,接受服務器發來的第一條歡迎信息
        String firstMsg=tcpMailClient.receive();
        taDisplay.appendText(firstMsg+"\n");
                //用於接收服務器信息的單獨線程
                readThread = new Thread(()->{
                    String receiveMsg=null;//從服務器接收一串字符
                    while ((receiveMsg=tcpMailClient.receive())!=null){
                        //lambda表達式不能直接訪問外部非final類型局部變量,需要定義一個臨時變量
                        //若將receiveMsg定義為類成員變量,則無需臨時變量
                        String msgTemp = receiveMsg;
                        Platform.runLater(()->{
                            taDisplay.appendText(msgTemp+"\n");
                        });
                    }
                    Platform.runLater(()->{
                        taDisplay.appendText("對話已關閉!\n");
                    });
                });
 
                readThread.start();
    } catch (IOException e) {
        e.printStackTrace();
    }
 
});
View Code

2、發送按鈕 

//發送按鈕
btnSend.setOnAction(event -> {
    String senderMail = mail.getText().trim();
    String receiverMail = toMail.getText().trim();
    String sub = subject.getText();
    String content = tfSend.getText();
    try {
 
        tcpMailClient.send("HELO friend");
        tcpMailClient.send("auth login");
 
        String userNameBase64= encode(senderMail);
        tcpMailClient.send(userNameBase64);
        String authCode = encode("你的授權碼");
        tcpMailClient.send(authCode);
        String msg = "mail from:<"+senderMail+">";
        tcpMailClient.send(msg);
 
        msg = "rcpt to:<"+receiverMail+">";
        tcpMailClient.send(msg);
 
        tcpMailClient.send("data");
 
        msg="from:"+senderMail;
        tcpMailClient.send(msg);
 
        msg="to:"+receiverMail;
        tcpMailClient.send(msg);
 
        msg="subject:"+sub;
        tcpMailClient.send(msg);
 
        tcpMailClient.send("\n");
//      tcpMailClient.send("這是一封測試java客戶端自動發送功能的郵件。");
        tcpMailClient.send(content);
 
        tcpMailClient.send(".");
 
        tcpMailClient.send("quit");
 
 
    }catch (Exception e){
        taDisplay.appendText("服務器連接失敗!"+e.getMessage()+"\n");
    }
});
View Code

QQ客戶端的程序可以沿用之前的內容,詳見這篇:基於TCP協議網絡socket編程(java實現C/S通信)

五、QQ郵件發送效果演示

 細心的讀者可以發現,在我點擊發送之后,程序卡斷了一會,其實就是因為我設置發送睡眠1000ms,實際可以發送成功,建議設置200ms或以上!

 發送到自己QQ郵箱:

 

發送到自己的126郵箱進行測試:

六、總結

這一篇為QQ郵件發送客戶端程序設計的下篇,記錄了實現的關鍵部分,不用命令發送方式,類似日常發送郵件,直接編寫郵件標題、內容,然后直接發送即可,基本實現了QQ郵件發送客戶端的功能,操作更加簡便。根據本篇的知識內容,后面可以實現更加完善的QQ郵件發送小程序,增加一系列小功能!

如果覺得不錯歡迎“一鍵三連”哦,點贊收藏關注,有問題直接評論,交流學習!


我的博客園:https://www.cnblogs.com/chenzhenhong/p/14331829.html

我的CSDN博客:https://blog.csdn.net/Charzous/article/details/111148425

版權聲明:本文為博主原創文章,遵循  CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接: https://blog.csdn.net/Charzous/article/details/111148425


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM