📄 client.cpp
字号:
// Client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Client.h"
#include <winsock2.h>
#include <afxsock.h>
#include <assert.H>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <time.h>
#include <algorithm>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
#define BUFFER_BLOCK_SIZE 4096
#define DEAL_SOCK_ERROR(retCode,sock) if((retCode)==SOCKET_ERROR || (retCode)==0)\
{ \
cout<<"Sock error: "<<GetLastError()<<endl;\
closesocket(sock); \
return -1; \
}
#define DEAL_RETURN_CODE(c) if((c)!='+' && (c)!=0) { return 1; }
//Command line scan
int ClientCommandResolve();
void InputLine(string & str);
//Local mailbox management
void MailBoxName(const string& username, const string& server, string& mailBoxName);
void GivenUniqueFileName(const string& dir,const string& subject, string& name,
string postfix=".eml");
//Analysisist of mail struct
void DecodingBase64(const char* src, char* des);
void DecodingBase64Adv(const char* src, int length, char* des);
UCHAR SixBitDecodeIndex(char a);
BOOL FilterHead(ifstream& file, BOOL& bBase64,int& contentType,string& tagStr,
string majorSplitPart="");
BOOL SimpleMail(ifstream& file, BOOL bBase64, string& text);
void SubResolve(ifstream& file,BOOL bBase64, string& splitTag,string& text);
void SubResolveAdv(ifstream& file,BOOL bBase64, string& splitTag,char** result, int& length);
void WriteAttachmentToFile(const string& dir,
const string& filename,
const char* content,
int length,
string& newfilename);
BOOL ResolveMail(const string& mailboxname,
const string& filename,
string& senderAddr,
string& date,
string& from, //for most mail server, it only support youself address
string& to,
string& cc,
string & subject,
string & bodytext,
string & bodyhtml,
map<string, string> & attachmentNames);
int DataHead(ifstream& file,
string& senderAddr,
string& date,
string& from, //for most mail server, it only support youself address
string& to,
string& cc,
string& subject,
string& tagStr, //majorSplitTag or filename
int& contentType,
BOOL& bBase64); //this parameters make effect only when contentType is 0,1,2
void DataBody( ifstream& file,
const string& mailbox,
BOOL bBase64,
int contentType,
string& tagStr, //if content==2 , it standards the filename else majorSplitTag
string& bodytext,
string& bodytexthtml,
map<string, string> & attachmentNames);
//POP3 Client Agent Application Functions
int ReceiveMail(const string& serverHostName,
UINT serverPort,
const string& username,
const string& pass,
const string& mailboxname);
int RetrieveAllEmail(SOCKET& sock, const string& mailboxname, BOOL bDel);
//Login
int Login(const string& proxyServerName, u_int proxyPort,
const string& proxyUser, const string& proxyPass,
const string& serverHostName, UINT serverPort,
const string& username, const string& pass,
SOCKET& sock, string& mailboxname);
//Command
int STAT(SOCKET sock,int& numOfMails);
int RETR(SOCKET sock,int mailID, string& content);
int DELE(SOCKET sock,int mailID);
int LIST(SOCKET sock,int mailID, int& length);
int RSET(SOCKET sock);
int QUIT(SOCKET sock);
//mail's UID related
int GetAllNewMailsID(SOCKET sock, const string& mailboxname, vector<int>& newMailID, vector<string>& newMailUID);
void WriteMailToFile(const string& mailboxname, const string& content, string& filename);
void PrintMail(const string& mailboxname, const string& filename);
void RenameFileName(string& filename);
void UTF8Decode(const std::string& src, std::string& des);
void GetMailsUIDList(const string& mailboxname, vector<string>& uniqueIDArray);
void WriteDownloadMailUID(const string& mailboxname, const string& UID);
//Socks5 proxy related
u_long ConvertHostnameToLongHostAddress(const char * destAddress);
int Socks5StartIPv4(const string& proxyServerHostName,
u_int proxyServerPort,
const string& username,
const string& pass,
u_long destAddress,
u_int destPort,
SOCKET& sock);
BOOL ReceiveMessage(SOCKET sock, char* buffer, int bufferLen);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
ClientCommandResolve();
return 0;
}
void InputLine(string & str)
{
char ch;
str="";
while((ch = getchar())!= '\n')
str+=ch;
}
int ClientCommandResolve()
{
string serverHostName;
UINT serverPort=0;
string senderAddr;
vector<string> recptAddrs;
string username;
string pass;
string date;
vector<string> from;
vector<string> to;
vector<string> cc;
vector<string> bcc;
string subject;
string bodytext;
string bodyhtml;
map<string, string>attachments;
string mailboxname;
string proxyServerName;
u_int proxyPort;
string proxyUser;
string proxyPass;
serverPort=110;
// serverHostName="";
// username="";
// pass="";
// proxyServerName="10.214.50.251";
// proxyPort=1080;
// proxyUser="";
// proxyPass="";
char paraCommand[BUFFER_BLOCK_SIZE];
int pos=0;
int iResult;
string str;
WSADATA wsaData;
if(WSAStartup(MAKEWORD( 2, 2 ), &wsaData)!=0)
{
cerr<<"socket init error"<<endl;
return -1;
}
while(1)
{
//POP3 Server host name
if(serverHostName.length()==0) //for testing
while(1)
{
cout<<"POP3 Server Host Name:";
cout.flush();
InputLine(str);
iResult=sscanf(str.c_str(),"%s",paraCommand);
if(iResult==EOF)
{
cout<<"Input server host name"<<endl;
continue;
}
serverHostName=paraCommand;
break;
}
//POP3 Server Port
if(serverPort==0) //for testing
while(1)
{
cout<<"POP3 Server Port:";
cout.flush();
InputLine(str);
iResult=sscanf(str.c_str(),"%s",paraCommand);
if(iResult!=EOF)
{
serverPort=atoi(paraCommand);
if(serverPort<=0)
{
cout<<"Invalid port."<<endl;
continue;
}
}
break;
}
//USER NAME
if(username.length()==0) //for testing
while(1)
{
cout<<"USER NAME:";
cout.flush();
InputLine(str);
iResult=sscanf(str.c_str(),"%s",paraCommand);
if(iResult==EOF)
{
cout<<"Input user name for authentication."<<endl;
continue;
}
username=paraCommand;
break;
}
//PASS
if(pass.length()==0) //for testing
while(1)
{
cout<<"PASSWORD:";
cout.flush();
InputLine(str);
iResult=sscanf(str.c_str(),"%s",paraCommand);
if(iResult==EOF)
{
cout<<"Input password."<<endl;
continue;
}
pass=paraCommand;
break;
}
//Proxy
if(proxyServerName.length()==0) //for testing
{
cout<<"Proxy?";
cout.flush();
InputLine(str);
if(str=="y" || str=="Y")
{
cout<<"Proxy Server Addr:";
InputLine(proxyServerName);
cout<<"Proxy Server Port:";
InputLine(str);
sscanf(str.c_str(),"%d",&proxyPort);
cout<<"Proxy Server Username:";
InputLine(proxyUser);
cout<<"Proxy Server Pass:";
InputLine(proxyPass);
}
}
cout<<"Receiving Mail....."<<endl;
//define mail box
SOCKET sock;
int retCode;
retCode=Login(proxyServerName, proxyPort, proxyUser, proxyPass, serverHostName,serverPort,username,pass,sock,mailboxname);
DEAL_RETURN_CODE(retCode);
retCode=RetrieveAllEmail(sock,mailboxname,FALSE);
DEAL_RETURN_CODE(retCode);
cout<<"QUIT?";
cout.flush();
InputLine(str);
if(str=="y"||str=="Y")
{
cout<<"Bye!"<<endl;
return -1;
}
}
return 0;
}
//write all mail's UID into mailboxname.log file
void GetMailsUIDList(const string& mailboxname,
vector<string>& uniqueIDArray)
{
char buffer[BUFFER_BLOCK_SIZE];
string filename;
ifstream file;
uniqueIDArray.clear();
filename= string(".\\")+mailboxname+"\\UID.log";
file.open(filename.c_str());
if(file.fail())
{
file.close();
ofstream nfile(filename.c_str());
assert(!nfile.fail());
nfile.close();
return;
}
while(!file.eof())
{
file>>buffer;
uniqueIDArray.push_back(buffer);
}
file.close();
}
void WriteDownloadMailUID(const string& mailboxname, const string& UID)
{
string filename;
ofstream file;
filename= ".\\"+mailboxname+"\\UID.log";
file.open(filename.c_str(),(ios::app|ios::out)&(~ios::trunc));
if(file.fail())
{
file.close();
file.open(filename.c_str());
if(file.fail())
{
cerr<<"Fail opening file "<<filename.c_str()<<endl;
return;
}
file<<UID.c_str()<<endl;
return;
}
file.seekp(0,ios::end);
file<<UID.c_str()<<endl;
file.close();
}
int ReceiveMail(const string& serverHostName,
UINT serverPort,
const string& username,
const string& pass,
const string& mailboxname)
{
sockaddr_in serverAddr;
int retCode;
SOCKET sock;
hostent * host;
char buffer[BUFFER_BLOCK_SIZE];
host=gethostbyname(serverHostName.c_str());
if(host==NULL)
{
cout<<"Cann't resolve this host name: "<<GetLastError()<<endl;
return -1;
}
sock=socket(AF_INET, SOCK_STREAM,0);
serverAddr.sin_addr=*(struct in_addr*)host->h_addr;
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=htons(serverPort);
cout<<"Connecting to "<<inet_ntoa(serverAddr.sin_addr)<<endl;
cout.flush();
if(connect(sock,(const sockaddr*)&serverAddr,sizeof(sockaddr))==SOCKET_ERROR)
{
cout<<"Cannot connect to Server: "<<serverHostName.c_str()<<endl;
cout.flush();
closesocket(sock);
return -1;
}
//1. welcome words
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
DEAL_SOCK_ERROR(retCode,sock);
buffer[retCode]='\0';
cout<<buffer;
DEAL_RETURN_CODE(buffer[0]);
//2. USER NAME
sprintf(buffer,"USER %s\r\n",username.c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
DEAL_SOCK_ERROR(retCode,sock);
buffer[retCode]='\0';
cout<<buffer;
DEAL_RETURN_CODE(buffer[0]);
//2. password
sprintf(buffer,"PASS %s\r\n",username.c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
DEAL_SOCK_ERROR(retCode,sock);
buffer[retCode]='\0';
cout<<buffer;
DEAL_RETURN_CODE(buffer[0]);
RetrieveAllEmail(sock,mailboxname,FALSE);
//2. QUIT
if(QUIT(sock)==-1)
return -1;
closesocket(sock);
return 0;
}
int Login(const string& proxyServerName,
u_int proxyPort,
const string& proxyUser,
const string& proxyPass,
const string& serverHostName,
UINT serverPort,
const string& username,
const string& pass,
SOCKET& sock,
string& mailboxname)
{
sockaddr_in serverAddr;
int retCode;
hostent * host;
char buffer[BUFFER_BLOCK_SIZE];
//create an user mailbox
MailBoxName(username,serverHostName,mailboxname);
if(proxyServerName.length())
{
u_long addr=ConvertHostnameToLongHostAddress(serverHostName.c_str());
if(Socks5StartIPv4(proxyServerName,proxyPort,proxyUser,proxyPass,addr,serverPort,sock)!=0)
return 1;
}
else
{
host=gethostbyname(serverHostName.c_str());
if(host==NULL)
{
cout<<"Cann't resolve this host name: "<<GetLastError()<<endl;
return -1;
}
sock=socket(AF_INET, SOCK_STREAM,0);
serverAddr.sin_addr=*(struct in_addr*)host->h_addr;
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=htons(serverPort);
cout<<"Connecting to "<<inet_ntoa(serverAddr.sin_addr)<<endl;
cout.flush();
if(connect(sock,(const sockaddr*)&serverAddr,sizeof(sockaddr))==SOCKET_ERROR)
{
cout<<"Cannot connect to Server: "<<serverHostName.c_str()<<endl;
cout.flush();
closesocket(sock);
return -1;
}
}
//1. welcome words
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
DEAL_SOCK_ERROR(retCode,sock);
buffer[retCode]='\0';
cout<<buffer;
DEAL_RETURN_CODE(buffer[0]);
//2. USER NAME
sprintf(buffer,"USER %s\r\n",username.c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
DEAL_SOCK_ERROR(retCode,sock);
buffer[retCode]='\0';
cout<<buffer;
DEAL_RETURN_CODE(buffer[0]);
//2. Password
sprintf(buffer,"PASS %s\r\n",pass.c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
DEAL_SOCK_ERROR(retCode,sock);
buffer[retCode]='\0';
cout<<buffer;
DEAL_RETURN_CODE(buffer[0]);
return 0;
}
void MailBoxName(const string& username,
const string& server,
string& mailBoxName)
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
mailBoxName=username+"."+server;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -