📄 pop2cmc.cpp
字号:
//
// implementation of pop3 to cmc/mapi mail forward
// currently only base64 decoding supported
// Pop2cmc.cpp: implementation of the Pop2cmc class.
// NO WARRANTY!
// USE AT YOUR OWN RISK
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <winbase.h>
#include "InetServer.h"
#include "Pop2cmc.h"
#include "wrap2cmc.h"
#include "base64.h" // public domain code for encoding/decoding
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
extern Wrap2CMC CMCObject ;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Pop2cmc::Pop2cmc()
{
VERIFY(CMCReceiver = new CMC_recipient[16]);
CMCAttach = 0 ;
CMCMessage = 0 ;
mime_cntrfr_val = mime_char_val = mime_cont_val = 0 ;
mime_cndisp_val = mime_cndisc_val = mime_fname_val = 0 ;
mime_name_val = Mailboundary = MailSubject = 0 ;
MailFrom = 0 ;
}
Pop2cmc::~Pop2cmc()
{
delete [] CMCReceiver ;
//delete [] CMCAttach ;
//delete CMCMessage ;
}
int Pop2cmc::ParsePOP3nSend(CString cMFileName)
{
char tempstr[255] ;
char MailFile[50];
long err = 999 ;
if ( GetCurrentDirectory( 255,tempstr ) == 0 )
{
return 200 ; // system command failed
}
sprintf(MailPath,"%s\\cmcqueue\\",tempstr);
sprintf(MailFile,"%s",cMFileName);
if ( ! ReadMailFile(cMFileName))
return 300 ; //
int PathLength = strlen(MailPath);
LPCTSTR lpcmsg = MailMessage ;
// build attachment
if ( isMultiPart )
{
int pathLength = strlen(MailPath);
if ( isParsedFully )
{
VERIFY(CMCAttach = new CMC_attachment[nOfAttachment]);
for ( int j = 0 ; j < nOfAttachment ; j++ )
{
CMCAttach[j].attach_title = MailAttachment[j]+pathLength ;
CMCAttach[j].attach_filename = MailAttachment[j] ;
CMCAttach[j].attach_type = CMC_ATT_OID_BINARY ;
CMCAttach[j].attach_flags = 0 ;
CMCAttach[j].attach_extensions = NULL ;
}
CMCAttach[nOfAttachment-1].attach_flags= CMC_ATT_LAST_ELEMENT ;
}
else
{
VERIFY(CMCAttach = new CMC_attachment[1]);
sprintf(tempstr,"%s%s",MailPath,MailFile);
CMCAttach[0].attach_title = MailFile ;
CMCAttach[0].attach_filename = tempstr ;
CMCAttach[0].attach_type = CMC_ATT_OID_BINARY ;
CMCAttach[0].attach_flags = CMC_ATT_LAST_ELEMENT ;
CMCAttach[0].attach_extensions = NULL ;
}
}
CMCReceiver[nOfReceiver-1].recip_flags = CMC_RECIP_LAST_ELEMENT ;
VERIFY(CMCMessage = new CMC_message) ;
/* Put it together in the message structure. */
CMCMessage->message_reference = NULL;
CMCMessage->message_type = NULL;
CMCMessage->subject = (char *) MailSubject; /* Message subject */
CMCMessage->time_sent = CMCTime; /* Ignored on cmc_send calls. */
CMCMessage->text_note = (char *) lpcmsg ;
CMCMessage->recipients = CMCReceiver ;
CMCMessage->attachments = CMCAttach ;
CMCMessage->message_flags = 0; /* No flags */
CMCMessage->message_extensions = NULL; /* No message extensions */
err = CMCObject.CMCSend(CMCMessage) ;
CleanAttachment();
if ( MailSubject) delete [] MailSubject ;
MailSubject = 0 ;
if ( MailFrom ) delete [] MailFrom ;
MailFrom = 0 ;
if ( CMCMessage ) delete CMCMessage ;
MailMessage = "" ;
MailMessage.FreeExtra();
for (int i = 0 ; i < nOfReceiver ; i++ )
{
delete [] CMCReceiver[i].name ;
delete [] CMCReceiver[i].address ;
}
delete [] CMCAttach ;
CMCAttach = 0 ;
return err ;
}
BOOL Pop2cmc::ReadMailFile(CString cMFileName)
{
char tempstr[255] ;
pop3file = fopen(MailPath + cMFileName,"r");
if ( pop3file == NULL )
{
// TODO log error message
//MessageBox(NULL,"File open failed",NULL,MB_OK);
return FALSE ;
}
Mailboundary = MailSubject = MailFrom = 0 ;
isB64 = isMultiPart = isParsedFully = FALSE ;
nOfReceiver = nOfAttachment = 0 ;
while ( !feof(pop3file) )
{
fgets(tempstr,255,pop3file);
if( tempstr[0] == 'X' && tempstr[1] == '-' &&
tempstr[2] == 'C' && tempstr[3] == 'M' &&
tempstr[4] == 'C' && tempstr[5] == 'E' &&
tempstr[6] == 'N' && tempstr[7] == 'D' &&
tempstr[8] == '\n' )
break ;
BuildCMCAddress(tempstr);
}
BuildHeader();
BuildBody();
BuildAttachment();
fclose(pop3file);
return TRUE ;
}
// RFC822 doesn't specify about header length but says
// there should be a blank line (CR+LF) between header & message body
BOOL Pop2cmc::BuildHeader()
{
char tempstr[512] ;
char *ptr = 0 ;
char *cont_val = 0 ; // Content-Type
char *char_val = 0 ; // charset
char *cntrfr_val = 0 ; // content-transfer-encoding
char *MailHeader = 0 ;
VERIFY(MailHeader = new char[1024]);
strcpy(MailHeader,"");
while( fgets(tempstr,512,pop3file) )
{
if ( !strnicmp(tempstr,"\r\n",2) )
{
break ; //
}
strcat(MailHeader,tempstr);
} // end of while loop
if ( ptr = strstr(MailHeader,"From:") )
{
for(int j = 0 ; j < 5 ; j++ , ptr++);
MailFrom = getCleanStr(ptr);
}
if ( ptr = strstr(MailHeader,"\nSubject:") )
{
for(int j = 0 ; j < 9 ; j++ , ptr++);
MailSubject = getCleanStr(ptr);
}
if ( ptr = strstr(MailHeader,"\nContent-Type:") )
{
if ( !strnicmp(ptr,"\nContent-Type: multipart/mixed",29 ) )
{
isMultiPart = TRUE ;
if ( ptr = strstr(ptr,"boundary=") )
{
for (int j = 0 ; j < 9 ; j++ , ptr++ ) ;
pop3boundary(ptr) ;
}
// TODO
}
else if ( !strnicmp(ptr,"\nContent-Type: text/plain",24) )
{
isMultiPart = FALSE ;
}
if (cont_val = strstr(ptr,"Content-Type:") )
{
for (int j = 0 ; j < 13 ; j++ , cont_val++);
mime_cont_val = getCleanStr(cont_val);
}
if ( char_val = strstr(ptr,"charset=") )
{
for (int j = 0 ; j < 8 ; j++ , char_val++);
mime_char_val = getCleanStr(char_val);
}
if ( cntrfr_val = strstr(ptr,"Content-Transfer-Encoding:") )
{
for (int j = 0 ; j < 26 ; j++ , cntrfr_val++);
mime_cntrfr_val = getCleanStr(cntrfr_val);
}
}
delete [] MailHeader ;
return TRUE ;
}
void Pop2cmc::BuildBody()
{
char tempstr[512] ;
MailMessage += "(SMTP2MAPI Forwarder) \r\n" ;
MailMessage += "From : " ;
MailMessage += MailFrom ;
MailMessage += "\r\n" ;
MailMessage += "\r\n" ;
// Multipart messages have message boundary for body of mail
if ( isMultiPart )
{
// start parsing body of message for encoding used
do
{
if ( !strnicmp(tempstr,Mailboundary,strlen(Mailboundary)) )
{
break ;
}
} while(fgets(tempstr,512,pop3file) ) ;
ParseMimeHdr();
}
// build message body
while ( fgets(tempstr,512,pop3file) != NULL )
{
if ( isMultiPart && !strnicmp(tempstr,Mailboundary,strlen(Mailboundary)))
{
break ;
}
else if ( !strnicmp(tempstr,".\r\n",3) && !isMultiPart )
{
break ;
}
MailMessage +=tempstr ;
}
CleanMimeHdr();
}
void Pop2cmc::BuildAttachment()
{
char tempstr[512] ;
nOfAttachment = 0 ;
if ( !isMultiPart )
return ;
while ( !feof(pop3file) )
{
isB64 = FALSE ;
is7bt = FALSE ;
is8bt = FALSE ;
isQtp = FALSE ;
isUen = FALSE ;
isBin = FALSE ;
isXen = FALSE ;
isParsedFully = TRUE ; // if not parsed fully we will send
// mail file as one attachement
ParseMimeHdr();
if ( mime_cont_val || mime_char_val || mime_cntrfr_val || mime_cndisp_val || mime_name_val || mime_fname_val )
{
if ( !strnicmp(mime_cntrfr_val,"base64",6) )
isB64 = TRUE ;
else
{
if ( !strnicmp(mime_cntrfr_val,"quoted-printable",16))
isQtp = TRUE ;
if ( !strnicmp(mime_cntrfr_val,"8bit",4))
is8bt = TRUE ;
if ( !strnicmp(mime_cntrfr_val,"7bit",4))
is7bt = TRUE ;
if ( !strnicmp(mime_cntrfr_val,"uuencoded",9))
isUen = TRUE ;
if ( !strnicmp(mime_cntrfr_val,"binary",6))
isBin = TRUE ;
if ( !strnicmp(mime_cntrfr_val,"X-EncodingName",14))
isXen = TRUE ;
isParsedFully = FALSE ;
}
char tmpfile[128] ;
nOfAttachment++ ;
if ( mime_name_val )
{
sprintf(tmpfile,"%s%s",MailPath,mime_name_val);
}
else if ( mime_fname_val )
{
sprintf(tmpfile,"%s%s",MailPath,mime_fname_val);
}
else
{
char file[30] ;
sprintf(file,"mes%d.out",nOfAttachment);
sprintf(tmpfile,"%s%s",MailPath,file);
}
VERIFY(MailAttachment[nOfAttachment-1] = new char[strlen(tmpfile)+1]) ;
strcpy(MailAttachment[nOfAttachment-1],tmpfile);
fstream outf(tmpfile,ios::in|ios::out|ios::binary) ;
// othere decoding scheme will be added in future
if ( isB64 )
{
Base64Decoder b64(outf);
while (fgets(tempstr,100,pop3file))
{
if ( !strnicmp(tempstr,Mailboundary,strlen(Mailboundary)) )
{
break ;
}
b64.Put((unsigned char*)(tempstr),strlen(tempstr));
}
b64.InputFinished();
}
if ( isQtp )
{
}
}
}
CleanMimeHdr();
return ;
}
// this function will create message boundary
void Pop2cmc::pop3boundary(char *mBoundary)
{
char *buf = 0 ;
VERIFY(buf = new char[strlen(mBoundary)+4]) ;
if ( *mBoundary == '\"' ) mBoundary++ ;
strcpy(buf,"--");
sscanf(mBoundary,"%[^\"\r\n]",buf+2);
VERIFY(Mailboundary = new char[strlen(buf)+1]);
strcpy(Mailboundary,buf);
delete [] buf ;
}
char * Pop2cmc::pop3filename(char *fname)
{
char *buf = 0 ;
VERIFY(buf = new char[strlen(fname)+2]) ;
if ( *fname == '\"' ) fname++ ;
sscanf(fname,"%[^\"\r\n]",buf);
return buf ;
}
void Pop2cmc::CleanAttachment()
{
if ( ! isMultiPart )
return ;
for(int j = 0 ; j < nOfAttachment ; j++)
{
DeleteFile(MailAttachment[j]);
}
delete [] *MailAttachment ;
}
void Pop2cmc::ParseMimeHdr()
{
char tempstr[512] ;
char *cont_val = 0 ; // Content-Type
char *char_val = 0 ; // charset
char *cntrfr_val = 0 ; // content-transfer-encoding
char *cndisp_val = 0 ; // content-disposition
char *cndisc_val = 0 ; // content-description
char *fname_val = 0 ; // filename
char *name_val = 0 ; // name
char mimeHeader[512] ;
strcpy(mimeHeader,"");
while(fgets(tempstr,512,pop3file) )
{
if ( !strnicmp(tempstr,"\r\n",2) )
break ;
strcat(mimeHeader,tempstr);
}
strcpy(tempstr,mimeHeader);
char2lower(tempstr) ;
if (cont_val = strstr(tempstr,"content-type:") )
{
for (int j = 0 ; j < 13 ; j++ , cont_val++);
mime_cont_val = getCleanStr(cont_val);
}
if ( char_val = strstr(tempstr,"charset=") )
{
for (int j = 0 ; j < 8 ; j++ , char_val++);
mime_char_val = getCleanStr(char_val);
}
if ( cntrfr_val = strstr(tempstr,"content-transfer-encoding:") )
{
for (int j = 0 ; j < 26 ; j++ , cntrfr_val++);
mime_cntrfr_val = getCleanStr(cntrfr_val);
}
if ( name_val = strstr(tempstr," name=") ) // avoid filename
{
for (int j = 0 ; j < 6 ; j++ , name_val++);
mime_name_val = getCleanStr(name_val);
}
if ( fname_val = strstr(tempstr,"filename=") )
{
for (int j = 0 ; j < 9 ; j++ , fname_val++);
mime_fname_val = getCleanStr(fname_val);
}
if ( cndisp_val = strstr(tempstr,"content-disposition:") )
{
for (int j = 0 ; j < 20 ; j++ , cndisp_val++);
mime_cndisp_val = getCleanStr(cndisp_val);
}
if ( cndisc_val = strstr(tempstr,"content-description:") )
{
for (int j = 0 ; j < 20 ; j++ , cndisc_val++);
mime_cndisc_val = getCleanStr(cndisc_val);
}
}
void Pop2cmc::char2lower(char *tempstr)
{
int length = strlen(tempstr);
for (int i=0; i<length; i++)
{
tempstr[i] = tolower(tempstr[i]) ;
}
}
char * Pop2cmc::getCleanStr(char *tempstr)
{
char *lbufret = 0 ;
VERIFY(lbufret = new char[strlen(tempstr)+1]) ;
for ( ; *tempstr == ' ' ; tempstr++) ;
if ( *tempstr == '\"' ) tempstr++ ;
sscanf(tempstr,"%[^;\"\r\n]",lbufret);
for ( int j = strlen(lbufret) ; lbufret[j] == '\0' || lbufret[j] == '\r' || lbufret[j] == '\n' ; j-- )
lbufret[j] = '\0' ;
return lbufret ;
}
void Pop2cmc::BuildCMCAddress(LPSTR tempstr)
{
LPSTR lpszName = 0 ;
VERIFY(lpszName = new CHAR[64]);
LPSTR lpszAddress = 0 ;
VERIFY(lpszAddress = new CHAR[47]);
int i ;
if ( nOfReceiver == 16 )
return ;
for ( ; *tempstr != ':' ;tempstr++ );
tempstr++ ;
for ( i = 0 ; *tempstr != ';' ; tempstr++ , i++ )
lpszName[i] = *tempstr ;
lpszName[i] = '\0' ;
tempstr++;
for ( i = 0 ; *tempstr != ';' ; tempstr++ , i++ )
lpszAddress[i] = *tempstr ;
lpszAddress[i] = '\0' ;
// Build recipient list with two recipients. Add one "To" recipient.
CMCReceiver[nOfReceiver].name = (char *) lpszName;
CMCReceiver[nOfReceiver].name_type = CMC_TYPE_INDIVIDUAL;
CMCReceiver[nOfReceiver].address = (char *) lpszAddress ;
CMCReceiver[nOfReceiver].role = CMC_ROLE_TO;
CMCReceiver[nOfReceiver].recip_flags= 0 ;
CMCReceiver[nOfReceiver].recip_extensions = NULL;
nOfReceiver++ ;
}
void Pop2cmc::CleanMimeHdr()
{
if ( mime_cont_val) delete [] mime_cont_val ;
if ( mime_char_val) delete [] mime_char_val ;
if ( mime_cntrfr_val) delete [] mime_cntrfr_val ;
if ( mime_cndisp_val) delete [] mime_cndisp_val ;
if ( mime_cndisc_val) delete [] mime_cndisc_val ;
if ( mime_fname_val) delete [] mime_fname_val ;
if ( mime_name_val) delete [] mime_name_val ;
mime_cont_val = mime_char_val = 0 ;
mime_cntrfr_val = mime_cndisp_val = 0 ;
mime_cndisc_val = mime_fname_val = 0 ;
mime_name_val = 0 ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -