/*
对繁体中文支持不好, 不能正常显示.
对日文支持不好,不能正常显示.
quoted模式支持的不好.有空再改.
有时候附件是一封邮件的情况下,就不能做base64解码了。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <direct.h>
#include <windows.h>
#include <shellapi.h>
#include "AMailAttch.h"
#pragma comment(lib,"shell32.lib")
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void main(int argc, char **argv)
{
char linebuf[4096] = {0};
char users[128] = {0};
char filename[512] = {0};
char szBuffer[256] = {0};
char plain_charset[128] = {0};
int base64_count = 0;
FILE * fp = NULL;
FILE * logfile = NULL;
if(argc < 2)
{
help();
return;
}
if( (fp = fopen(argv[1], "rt")) == NULL )
{
printf("cannot open email file %s\n", argv[1]);
return;
}
if( (logfile = fopen("AMailLog.txt", "w+")) == NULL )
{
printf("create log file failed!\n");
return;
}
fseek(fp, 0, SEEK_END);
int filelen = ftell(fp);
fseek(fp, 0, SEEK_SET); //得到文件长度,并将指针放到文件头
char *pEncoded = new char[filelen];
char *pDecoded = new char[filelen];
if((pEncoded == NULL) || (pDecoded == NULL) )
{
printf("alloc memory fail.\n");
return;
}
memset(pEncoded, 0, filelen);
memset(pDecoded, 0, filelen);
if(GetAttchBoundary(AttchBoundary, fp) == false) //是否存在附件
{
printf("Not find mail attchment!\n");
return;
}
if(GetPlainBoundary(PlainBoundary, fp) == false) //如果没有找到邮件正文的标志,就用附件的标志做分隔符.
strcpy(PlainBoundary, AttchBoundary);
sprintf(linebuf, "%s\n", argv[1]);
FormatPrint(linebuf, logfile);
PickStatus status = STATUS_FIND_USERS;
while(fgets((char*)linebuf, 4095, fp)!=NULL) //从文件中读取8192个字符到缓冲区.
{
trimline((char*)linebuf);
if(strlen((char*)linebuf)==0)
continue;
if(status == STATUS_FIND_USERS) //找到发件人
{
if(strncmp((char*)linebuf, "From: ", 6) == NULL)
{
GetUser(users, linebuf);
sprintf(szBuffer, "From: %s\n", users);
FormatPrint(szBuffer, logfile);
status = STATUS_FIND_SUBJECT;
}
}
if(status == STATUS_FIND_SUBJECT) //显示主题
{
if(strncmp((char*)linebuf, "Subject:", 8) == NULL)
{
char Subject[1024] = {0};
GetSubject(Subject, linebuf, fp);
sprintf(szBuffer, "Subject: %s\n", Subject);
FormatPrint(szBuffer, logfile);
status = STATUS_FIND_TEXT;
}
}
if(status == STATUS_FIND_TEXT)
{
if(strncmp((char*)linebuf, "Content-Type: text/plain", 24) == NULL) //通常都是这个纯文本模式的正文
{
while( GetPlainCharset(linebuf, plain_charset) == 0 )
{
fgets((char*)linebuf, 4095, fp);
trimline((char*)linebuf);
}
status = STATUS_FIND_PLAINENCODING;
}
if(strncmp((char*)linebuf, "Content-Type: text/html", 23) == NULL) //如果找不到上面的,也会以这个作为标准. 但是前提是先经过了上面的过滤.
{
while( GetPlainCharset(linebuf, plain_charset) == 0 )
{
fgets((char*)linebuf, 4095, fp);
trimline((char*)linebuf);
}
status = STATUS_FIND_PLAINENCODING;
}
}
if(status == STATUS_FIND_PLAINENCODING) //找到邮件正文编码模式
{
char *pset = NULL;
if(strncmp(linebuf,"Content-Transfer-Encoding:", 26) == 0) //获得正文编码模式
{
pset = linebuf + strlen("Content-Transfer-Encoding:");
while(*pset == ' ') pset++;
strcpy(PlainEncoding, pset);
status = STATUS_FIND_PLAIN;
}
}
if(status == STATUS_FIND_PLAIN) //找到邮件正文并进行解码。
{
if((strncmp(linebuf,"Content-",8) == 0) || (strncmp(linebuf,"charset",7) == 0))
continue;
if(1 == GetPlainText(pDecoded, pEncoded, linebuf, PlainBoundary, PlainEncoding, plain_charset))
{
sprintf(pEncoded, "Plain: %s\n", pDecoded);
FormatPrint(pEncoded, logfile);
// status = STATUS_FIND_ATTACHMENT;
status = STATUS_FIND_FILENAME;
}
}
/*
if(status == STATUS_FIND_ATTACHMENT)
{
if(strstr((char*)linebuf, "isposition: attachment")!=NULL)
{
status = STATUS_FIND_FILENAME;
}
}
*/
if(status == STATUS_FIND_FILENAME) //找到附件文件名
{
if(strstr((char*)linebuf, "filename=")!=NULL)
{
GetAttchName(filename, linebuf, fp);
sprintf(szBuffer, "AttchName: %s\n", filename);
FormatPrint(szBuffer, logfile);
base64_count = 0;
memset(pEncoded, 0, filelen);
status = STATUS_RECV_BASE64;
continue;
}
}
if(status == STATUS_RECV_BASE64)
{
int len = strlen((char*)linebuf);
if((strncmp(linebuf,"Content-",8) == 0) ||
(strncmp(linebuf,"X-Attachment",12) == 0) ||
(strncmp(linebuf,"filename", 8 ) == 0) ||
(strncmp(linebuf,"name",4) == 0)
) //对部分解码失败的附件,是因为可能多了这些行其中的某行
continue;
if(strstr((char*)linebuf, AttchBoundary)!=NULL)
{
// todo: base64 decoding...
int decode_len = DecodeBase64(pEncoded, (unsigned char*)pDecoded, strlen(pEncoded));
DumpEmlAttch(filename, (unsigned char *)pDecoded, decode_len);
status = STATUS_FIND_ATTACHMENT;
}
else
{
memcpy(pEncoded + base64_count, (char*)linebuf, len);
base64_count += len;
}
}
}
fclose(fp);
delete []pEncoded;
delete []pDecoded;
sprintf(szBuffer, "%d attchments dumped\n", attch_count);
FormatPrint(szBuffer, logfile);
fclose(logfile);
// AmMoveFile("AMailLog.txt");
}