📄 client.cpp
字号:
//unfinished. Here should save the transaction into file.
}
cout<<"QUIT?";
cout.flush();
InputLine(str);
if(str=="y"||str=="Y")
{
cout<<"Bye!"<<endl;
return -1;
}
recptAddrs.clear();
from.clear();
to.clear();
cc.clear();
bcc.clear();
subject="";
bodytext="";
bodytexthtml="";
attachments.clear();
}
return 0;
}
//for multiple response code
int GetResponseCode(SOCKET sock,int correctCode,string& str)
{
int retCode;
char buffer[BUFFER_BLOCK_SIZE+1];
str="";
while(1)
{
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
if(retCode==SOCKET_ERROR || retCode==0)
return -1;
buffer[retCode]='\0';
cout<<buffer;
cout.flush();
str+=buffer;
if(ResponsedCodeFinished(str))
{
if(atoi(str.c_str())==correctCode)
return 0;
else
return 1;
}
}
}
BOOL ResponsedCodeFinished(const string& str)
{
if(str[str.length()-2]!='\r' || str[str.length()-1]!='\n')
return FALSE;
if(str[3]!='-')
return TRUE;
char code[4];
int beginCode=atoi(str.c_str());
itoa(beginCode,code,10);
std::string::size_type pos=str.rfind(code,str.length()-1);
return str[pos+3]==' ';
}
int SendMail(const string& proxyServerName,
UINT proxyServerPort,
const string& proxyUser,
const string& proxyPass,
const string& serverHostName,
UINT serverPort,
const string& username,
const string pass,
const string& senderAddr,
const vector<string >& recptAddress,
const vector<string >& from, //for most mail server, it only support youself address
const vector<string >& to,
const vector<string >& cc,
const vector<string >& bcc,
const string & subject,
const string & bodytext,
const string & bodyhtml,
const vector<string >&attachments)
{
sockaddr_in serverAddr;
SOCKET sock;
hostent * host;
char buffer[BUFFER_BLOCK_SIZE];
int i;
BOOL bHtml,bAttachment;
string str;
if(bodyhtml.length()==0)
bHtml=FALSE;
else
bHtml=TRUE;
if(attachments.size()==0)
bAttachment=FALSE;
else
bAttachment=TRUE;
if(proxyServerName.length()!=0)//using socks5 proxy
{
u_long addr=ConvertHostnameToLongHostAddress(serverHostName.c_str());
if(Socks5StartIPv4(proxyServerName,proxyServerPort,proxyUser,proxyPass,addr,serverPort,sock)!=0)
{
cerr<<"Proxy server error!"<<endl;
}
}
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
DEAL_RETURN_CODE(GetResponseCode(sock,220,str));
//2. HELO.
//We omit HELO, because most Email Server needs authentication.
//3. EHLO
sprintf(buffer,"EHLO %s\r\n",senderAddr.c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,250,str));
//4. AUTH LOGIN.
//Most authentication takes AUTH LOGIN and AUTH PLAIN. Here we take AUTH LOGIN by default.
sprintf(buffer,"AUTH LOGIN\r\n");
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,334,str));
//2. USER NAME
//User name is coded by base64.
EncodingBase64(username.c_str(),buffer);
strcat(buffer,"\r\n");
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,334,str));
//2. password coded by base64
EncodingBase64(pass.c_str(),buffer);
strcat(buffer,"\r\n");
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,235,str));
//2. MAIL FROM
sprintf(buffer,"MAIL FROM:<%s>\r\n",senderAddr.c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,250,str));
//2. RCPT
for(i=0;i<recptAddress.size();i++)
{
sprintf(buffer,"RCPT TO: <%s>\r\n",recptAddress[i].c_str());
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,250,str));
}
//2. DATA
sprintf(buffer,"DATA\r\n");
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,354,str));
string majorSplitTag;
//DATA head
DataHead(from[0],to,cc,bcc,subject,bodytext,bodyhtml,bHtml,bAttachment,majorSplitTag,str);
cout<<str.c_str();
cout.flush();
//send(sock,str.c_str(),str.length(),0);
SendMessage(sock,str.c_str(),str.length());
//DATA body
DataBody(bHtml,bAttachment,majorSplitTag,bodytext,bodyhtml,attachments,str);
cout<<str.c_str();
cout.flush();
// send(sock,str.c_str(),str.length(),0);
SendMessage(sock,str.c_str(),str.length());
DEAL_RETURN_CODE(GetResponseCode(sock,250,str));
//2. QUIT
strcpy(buffer,"QUIT\r\n");
cout<<buffer;
send(sock,buffer,strlen(buffer),0);
DEAL_RETURN_CODE(GetResponseCode(sock,221,str));
closesocket(sock);
return 0;
}
//we donnot want to allocate another buffer for src, so we write this encoding
void EncodingBase64(const char* src, char* des)
{
assert(src&&des);
char sixbit_encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while(*src!=NULL)
{
*des++=sixbit_encoding[(UCHAR)*src++>>2]; //6
if(*src==NULL)
{
*des++=sixbit_encoding[(*(src-1)&0x3)<<4];//2+4
*des++='=';
*des++='=';
break;
}
else
{
*des++=sixbit_encoding[(*(src-1)&0x3)<<4 | UCHAR(*src)>>4];//2+4
src++;
}
if(*src==NULL)
{
*des++=sixbit_encoding[(*(src-1)&0xF)<<2];//4+2
*des++='=';
}
else
{
*des++=sixbit_encoding[(*(src-1)&0xF)<<2 | UCHAR(*src)>>6];//4+2
*des++=sixbit_encoding[*src&0x3F];//6
src++;
}
}
*des=NULL;
}
void EncodingBase64Adv(const char* src, int length,char* des)
{
int i=0;
char sixbit_encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
assert(des);
while(i<length)
{
*des++=sixbit_encoding[(UCHAR)src[i++]>>2]; //6
if(i==length)
{
*des++=sixbit_encoding[(src[i-1]&0x3)<<4];//2+4
*des++='=';
*des++='=';
break;
}
else
{
*des++=sixbit_encoding[(src[i-1]&0x3)<<4 | UCHAR(src[i])>>4];//2+4
i++;
}
if(i==length)
{
*des++=sixbit_encoding[(src[i-1]&0xF)<<2];//4+2
*des++='=';
}
else
{
*des++=sixbit_encoding[(src[i-1]&0xF)<<2 | UCHAR(src[i])>>6];//4+2
*des++=sixbit_encoding[src[i]&0x3F];//6
i++;
}
}
*des=NULL;
}
//For high efficient, pls rewrite it using looking-up table
UCHAR SixBitDecodeIndex(char a)
{
if(a>='A'&&a<='Z')
return a-'A';
else if(a>='a'&&a<='z')
return 26+a-'a';
else if(a>='0'&&a<='9')
return 52+a-'0';
else if(a=='+')
return 62;
else if(a=='/')
return 63;
else if(a=='=')
return 0;
else
{
assert(FALSE);
return -1;
}
}
void DecodingBase64(const char* src, char* des)
{
assert(src&&des);
assert(strlen(src)%4==0);
while(*src!=NULL)
{
*des++=SixBitDecodeIndex(*src)<<2 | SixBitDecodeIndex(*(src+1))>>4; //6+2
src++;
*des++=SixBitDecodeIndex(*src)<<4 | SixBitDecodeIndex(*(src+1))>>2;//4+4
src++;
*des++=SixBitDecodeIndex(*src)<<6 | SixBitDecodeIndex(*(src+1)); //2+6
src+=2;
}
*des=NULL;
}
void DecodingBase64Adv(const char* src, int length, char* des)
{
int i=0;
assert(des);
assert(length%4==0);
while(i<length)
{
*des++=SixBitDecodeIndex(src[i])<<2 | SixBitDecodeIndex(src[i+1])>>4; //6+2
i++;
*des++=SixBitDecodeIndex(src[i])<<4 | SixBitDecodeIndex(src[i+1])>>2;//4+4
i++;
*des++=SixBitDecodeIndex(src[i])<<6 | SixBitDecodeIndex(src[i+1]); //2+6
i+=2;
}
*des=NULL;
}
void Date(string& buffer)
{
struct tm *newtime;
time_t aclock;
struct _timeb tstruct;
char str[BUFFER_BLOCK_SIZE];
time( &aclock );
newtime = localtime( &aclock );
strftime( str, BUFFER_BLOCK_SIZE,"%a, %d %b %Y %X ", newtime);
buffer=string("Date:")+str;
_ftime( &tstruct );
if(tstruct.timezone<0)
sprintf(str,"+%.2d%.2d\r\n",-tstruct.timezone/60,-tstruct.timezone%60);
else
sprintf(str,"-%.2d%.2d\r\n",tstruct.timezone/60,tstruct.timezone%60);
buffer+=str;
}
void MimeVersion(string & buffer)
{
buffer="Mime-Version: 1.0\r\n";
}
void Subject(const string& title,string & buffer)
{
char str[BUFFER_BLOCK_SIZE];
string::size_type pos=0;
BOOL bBase64=FALSE;
WCHAR wszUserName[BUFFER_BLOCK_SIZE/2]; // Unicode user name
int i;
int length=MultiByteToWideChar( CP_ACP, 0, title.c_str(),title.length()+1, wszUserName,
sizeof(wszUserName)/sizeof(WCHAR));
if(length==0 && title.length()!=0)
bBase64=TRUE;
for(i=0; i<length; i++)
{
if(wszUserName[i] >= 256)
{
bBase64=TRUE;
break;
}
}
if(bBase64)
{
EncodingBase64(title.c_str(),str);
buffer=string("Subject: ") + "=?gb2312?B?" + str + "?=\r\n";
}
else
{
buffer="Subject: "+title+"\r\n";
}
}
void HeadTextTemple(const string& command,const string& addr,string & buffer, BOOL bPrintCommond)
{
char str[BUFFER_BLOCK_SIZE],str2[BUFFER_BLOCK_SIZE];
string::size_type pos=0;
BOOL bBase64=FALSE;
WCHAR wszUserName[BUFFER_BLOCK_SIZE/2]; // Unicode user name
int i;
int length=MultiByteToWideChar( CP_ACP, 0, addr.c_str(),addr.length()+1, wszUserName,
sizeof(wszUserName)/sizeof(WCHAR));
buffer="";
if(length==0)
bBase64=TRUE;
for(i=0; i<length; i++)
{
if(wszUserName[i] >= 256)
{
bBase64=TRUE;
break;
}
}
if(bBase64)
{
if((pos=addr.find("<",pos))==string::npos)
{
if((pos=addr.find(" ",pos))==string::npos)
return;
}
strcpy(str,addr.c_str());
str[pos]=NULL;
EncodingBase64(str,str2);
if(bPrintCommond)
buffer= command + ": \"=?gb2312?B?" + str2 + "?=\"" + (addr.c_str()+pos) + "\r\n";
else
buffer= string("\"=?gb2312?B?") + str2 + "?=\"" + (addr.c_str()+pos);
}
else
{
if((pos=addr.find("<",pos))==string::npos)
{
if(bPrintCommond)
buffer=command + ": <" + addr + ">\r\n";
else
buffer=string("<") + addr + ">";
}
else
{
if(bPrintCommond)
buffer=command + ": " + addr + "\r\n";
else
buffer= addr;
}
}
}
void From(const string& addr,string & buffer)
{
HeadTextTemple("From", addr , buffer);
}
void To(const vector<string >& to,string & buffer)
{
string str;
buffer="To: ";
for(int i=0;i<to.size();i++)
{
if(i!=0)
buffer+=",";
HeadTextTemple("To", to[i] , str, FALSE);
buffer+=str;
}
buffer+="\r\n";
}
void Cc(const vector<string >& cc,string & buffer)
{
string str;
int i;
buffer="";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -