www.pudn.com > mailserver-muiter.zip > 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#include #include #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