郵件客戶端
阿新 • • 發佈:2021-01-03
計算機網路課程設計 郵件客戶端
1. 參考部落格
2. 前期準備
- 基於實現的環境為Windows 7,主要是因為Windows 10的Telnet服務端已經被砍掉了,看了別人的部落格說是Win10可以安裝環境,本人僅作課設用,故在虛擬機器上實現,有興趣的可以自行摸索。
- 首先開啟在Windows環境中,開啟控制面板->程式,開啟Telnet客戶端和服務端。
- 然後執行services.msc命令,不會自行百度,開啟Telnet服務,設為自動執行,你可能會遇到一些bug,開啟不了,主要是依賴的問題,自行百度解決。
3. 用命令列的方式進行實現(接收到郵件說明成功)
4. 程式碼實現(Codeblocks環境)
#include <iostream> #include <string> #include <WinSock2.h> #include <stdio.h> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; string base64_encode(string str){ //base64加密演算法 string base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int str_len = str.length(); string res=""; //注意這裡str_len/3*3 //通過字元的ascii二進位制位運算組合成base64編碼二進位制 for (int strp=0; strp<str_len/3*3; strp+=3){ res+=base64_table[str[strp]>>2]; res+=base64_table[(str[strp]&0x3)<<4 | (str[strp+1])>>4]; res+=base64_table[(str[strp+1]&0xf)<<2 | (str[strp+2])>>6]; res+=base64_table[(str[strp+2])&0x3f]; //cout<<res<<endl; } if (str_len%3==1){ int pos=str_len/3 * 3; res += base64_table[str[pos]>>2]; res += base64_table[(str[pos]&0x3)<<4]; res += "="; res += "="; }else if (str_len%3==2){ int pos=str_len/3 * 3; res += base64_table[str[pos]>>2]; res += base64_table[(str[pos]&0x3)<<4 | (str[pos+1])>>4]; res += base64_table[(str[pos+1]&0xf)<<2]; res += "="; } return res; } int main() { char buff[500]; //收到recv函式返回的結果 string message; string info; string subject; WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 2); //WSAStarup,即WSA(Windows SocKNDs Asynchronous,Windows套接字非同步)的啟動命令 int err = WSAStartup(wVersionRequested, &wsaData); if ( err != 0 ) { return 0; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { printf("初始化失敗!"); WSACleanup( ); return 0; } SOCKET sockClient; //客戶端的套接字 sockClient = socket(AF_INET, SOCK_STREAM, 0); //建立socket物件 HOSTENT* pHostent;//hostent是host entry的縮寫,該結構記錄主機的資訊,包括主機名、別名、地址型別、地址長度和地址列表 pHostent = gethostbyname("smtp.qq.com"); //得到有關於域名的資訊,連結到qq郵箱伺服器 SOCKADDR_IN addrServer; //服務端地址 addrServer.sin_addr.S_un.S_addr = *((DWORD *)pHostent->h_addr_list[0]); //得到smtp伺服器的網路位元組序的ip地址 addrServer.sin_family = AF_INET; addrServer.sin_port = htons(25); //連線埠25 err = connect(sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); //向伺服器傳送請求 buff[recv(sockClient, buff, 500, 0)] = '\0'; //printf("%s",buff); /* 登入郵件伺服器 */ cout <<"歡迎登陸QQ郵箱簡易版\n"; string qq,password; cout << "請輸入你的QQ郵箱號碼:\n"; cin>>qq; cout << "請輸入你的郵箱授權碼:\n"; cin >>password; cout << "登陸認證成功,您可以傳送郵件了:\n"; message = "helo qq\r\n"; send(sockClient, message.c_str(), message.length(), 0); //傳送ehlo命令 buff[recv(sockClient, buff, 500, 0)] = '\0'; //接收返回值 message = "auth login\r\n"; send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; /* 傳送base64加密的使用者名稱、密碼 */ message = base64_encode(qq) + "\r\n"; send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; message = base64_encode(password) + "\r\n"; send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; /* 使用 MAIL 命令指定傳送者 使用 RCPT 命令指定接收者,可以重複使用RCPT指定多個接收者 */ // password = "wewqzvbzcfqkdhee"; string mail; cout << "請輸入收件人郵箱:\n"; cin >> mail; message = "mail from:<" + qq + ">\r\n"; send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; message = "rcpt to:<"; message.append(mail); message.append(">\r\n"); send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; /* 使用 DATA 命令告訴伺服器要傳送郵件內容 */ message = "DATA\r\n"; send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; message = "From: " + qq + "\r\nTo: "+mail+"\r\nsubject:"; cout<<"主題:"; cin>>subject; message.append(subject); message.append("\r\n\r"); cout<<"內容:"; cin>>info; message.append(info); message.append("\r\n.\r\n"); //cout<<message.c_str(); send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; message = "QUIT\r\n"; send(sockClient, message.c_str(), message.length(), 0); buff[recv(sockClient, buff, 500, 0)] = '\0'; cout << "郵件傳送成功!"<<endl; system("pause"); return 0; }