www.pudn.com > pop3.rar > MimeMessage.c


/****************************************************************** 
// MimeMessage.c  
// Function: 为CMailAdapter提供接口 
// Author	: wan ning 
// Date		: 2006/11/17 
// history	: 
*******************************************************************/ 
 
#include  
#include  
#include  
#include  
#include  
 
#include "MimeMessage.h" 
#include "mimeb64.h" 
 
enum RecipClass { 
	TO = 1, 
	CC, 
	BCC 
}; 
 
 
#define MAX_BUFFER_SIZE				1024 
#define MIN_BUFFER_SIZE				128 
 
#define CONTENT_TYPE_STRING			"text/plain" 
#define CONTENT_TYPE_JPG			"image/jpeg" 
#define CONTENT_TYPE_DEF            "text/html" 
#define CONTENT_TYPE_MULTIPART		"multipart/mixed" 
#define CONTENT_TYPE_OCTET_STREAM	"application/octet-stream" 
 
#define CHAR_SET					"gb2312" 
 
#define TRANSFER_ENCODING_7BIT		"7bit" 
#define TRANSFER_ENCODING_B64		"base64" 
 
#define MAIL_PART_BOUNDARY			"_.__.__TOL__Mailer__Part_Boundary_" 
 
#define ERROR_OPEN_FILE_FAIL		"Can not open file" 
#define ERROR_MALLOC_FAILE			"malloc failed" 
#define ERROR_EBADF					"invalid file-handle" 
 
//全局变量,用于构造boundary 
int BoundaryLevel = 0; 
 
//-------------------------------------------------------------- 
//	功能:转换邮件为MIME编码字符串 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strMail MIME编码后邮件字符串指针 
//	OUT char* strError 错误信息提示 
//	返回值:成功为TRUE,失败为FALSE 
//  备注:strMail要足够大,这里不检查溢出 
//-------------------------------------------------------------- 
BOOL getMailString( LPVOID pMail, char *strMail, char *strError ) 
{ 
	BOOL bRet; 
 
    assert( pMail!=NULL && strMail!=NULL && strError!=NULL ); 
 
	// 初始化字符串strMail 
	startHeader( strMail ); 
	// 将邮件头部信息追加到字符串strMail 
	prepareHeader( pMail, strMail ); 
/* 
	endHeader( strMail ); 
*/ 
	// 将邮件体追加到字符串strMail 
	bRet = prepareBody( pMail, strMail, strError ); 
	 
	return bRet; 
} 
 
//-------------------------------------------------------------- 
//	功能:分配MIME编码字符串所需的内存空间 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strError 错误信息提示 
//	返回值:NULL 失败 ,其它,分配的内存空间的起始地址 
//-------------------------------------------------------------- 
void * mallocMime( LPVOID pMail, char *strError ) 
{ 
	long lmimeStrLen = getMimeStrLen(pMail, strError); 
	 
	if ( lmimeStrLen != -1L ) 
	{ 
		return malloc( lmimeStrLen ); 
	} 
	else 
	{ 
		return NULL; 
	} 
} 
 
//-------------------------------------------------------------- 
//	功能:释放MIME编码字符串所需的内存空间 
//	参数: 
//	IN char* strMail MIME编码后邮件字符串指针 
//	返回值:空 
//-------------------------------------------------------------- 
void freeMime( void *strMail ) 
{ 
	free( strMail ); 
} 
 
//-------------------------------------------------------------- 
//	功能:计算存放MIME编码字符串所需的大小,单位Byte 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strError 错误信息提示 
//	返回值:-1 失败,其它 存放MIME编码字符串所需的大小 
//  备注:只要有一个附件打开失败都将返回-1 
//-------------------------------------------------------------- 
long getMimeStrLen( LPVOID pMail, char *strError ) 
{ 
#define HEADER_SIZE			1024 
#define BODY_TAG			256	 
	LPNOTE_DETAIL pMailBody = (LPNOTE_DETAIL)pMail; 
	long ltotalSize = 0L; 
	long lfileSize; 
	long lmimeSize = 0L; 
	int i; 
 
	// 邮件首部大小设置为HEADER_SIZE 
	ltotalSize += HEADER_SIZE; 
	 
	assert(pMail!=NULL && strError!=NULL); 
	 
	// 计算发/收信人地址所需的空间 
	ltotalSize += strlen( pMailBody->pcDisplaySender ); 
	ltotalSize += strlen( pMailBody->pcDisplayTo ); 
	ltotalSize += strlen( pMailBody->pcDisplayCc ); 
	ltotalSize += strlen( pMailBody->pcDisplayBcc ); 
 
	// 计算正文文本所需空间大小 
/* 
	// 正文文本以文件形式保存的情况 
	// 路径名为空时,表示没有邮件正文,不计算空间。 
	if ( pMailBody->pcBodyFilePathName != NULL ) 
	{ 
		lfileSize = getByteFileSize( pMailBody->pcBodyFilePathName ); 
		if ( -1L == lfileSize ) 
		{ 
			sprintf( strError, "%s: %s", ERROR_OPEN_FILE_FAIL,  
									pMailBody->pcBodyFilePathName ); 
			return -1L; 
		} 
		else 
		{ 
			lmimeSize += lfileSize; 
		} 
	} 
*/ 
	// 正文文本在内存中 
	if ( pMailBody->pcBodyContent[0] != '\0' ) 
	{ 
		lmimeSize += strlen( pMailBody->pcBodyContent ); 
	} 
 
	// 计算标题所需空间大小 
	if ( pMailBody->pcSubject[0] != '\0' ) 
	{ 
		lmimeSize += strlen( pMailBody->pcSubject ); 
	} 
 
	// 计算附件所需空间大小 
	if ( pMailBody->bHasAttach ) 
	{ 
		for( i = 0; i < pMailBody->iAttachCount; i++ ) 
		{ 
			// 附件的标记信息大小 
			ltotalSize += BODY_TAG; 
			lfileSize = getByteFileSize( (pMailBody->lpAttach[i]).lpszPathName ); 
			if ( -1L == lfileSize ) 
			{ 
				sprintf( strError, "%s %d %s: %s", 
							__FILE__,  
							__LINE__,  
							ERROR_OPEN_FILE_FAIL,  
							(pMailBody->lpAttach[i]).lpszPathName ); 
			return -1L; 
			} 
			else 
			{ 
				lmimeSize += lfileSize; 
			} 
		} 
	} 
	// Base64编码后长度是原来的4/3 
	lmimeSize = ( lmimeSize*4 )/3+1; 
	// 编码后每行的长度不能超过76,所以要加上每行回车换行所需的空间 
	ltotalSize += lmimeSize + (lmimeSize/BASE64_LINE_SIZE*2); 
 
	return ltotalSize; 
} 
 
//-------------------------------------------------------------- 
//  功能:初始化邮件字符串为空串 
//	参数: 
//	IN/OUT char* strMail 邮件字符串指针 
//	返回值:空 
//-------------------------------------------------------------- 
static void startHeader( char *strMail ) 
{ 
	strMail[0] = '\0'; 
} 
 
//-------------------------------------------------------------- 
//  功能:邮件头部结束符 
//	参数: 
//	IN/OUT char* strMail 邮件字符串指针 
//	返回值:空 
//-------------------------------------------------------------- 
static void endHeader( char *strMail ) 
{ 
	strcat( strMail, "\r\n" ); 
} 
 
//-------------------------------------------------------------- 
//  功能:追加一个新行到邮件字符串 
//	参数: 
//	IN const char* plszNewLine  
//	IN/OUT char* plHeader 
//	返回值:空 
//-------------------------------------------------------------- 
static void addHeaderLine( char *plHeader, const char *plszNewLine ) 
{ 
	strcat( plHeader, plszNewLine ); 
	strcat( plHeader, "\r\n" ); 
} 
 
//-------------------------------------------------------------- 
//  功能:处理邮件头部信息到字符串 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strMail MIME编码后邮件字符串指针 
//	返回值:空 
//-------------------------------------------------------------- 
static void prepareHeader( LPVOID pMail, char *strMail ) 
{ 
	LPNOTE_DETAIL pMailHeader = ( LPNOTE_DETAIL )pMail; 
     
	char strImportance[sizeof(long)+1]; 
	 
	// 临时缓冲区 
	char sTemp[MAX_BUFFER_SIZE]={'\0'}; 
	char sTemp2[MAX_BUFFER_SIZE]={'\0'}; 
/* 
	char sTo[MAX_BUFFER_SIZE]={'\0'}; 
	char sCc[MAX_BUFFER_SIZE]={'\0'}; 
	char sBcc[MAX_BUFFER_SIZE]={'\0'}; 
*/	 
	struct tm *ptrTime; 
	time_t lt; 
     
	// 用于计算时区 
	TIME_ZONE_INFORMATION timezoneinfo; 
	LONG lTimeDifferential = 0; 
	LONG lHours = 0; 
	LONG lMinutes = 0; 
	unsigned long dwReturn; 
 
	// From, To, Cc, Bcc 
	if ( pMailHeader->pcDisplaySender[0] != '\0' ) 
	{ 
		sprintf( sTemp, "From: %s", pMailHeader->pcDisplaySender ); 
		addHeaderLine( strMail, sTemp ); 
	} 
	if ( pMailHeader->pcDisplayTo[0] != '\0' ) 
	{ 
		sprintf( sTemp, "To: %s", pMailHeader->pcDisplayTo ); 
		addHeaderLine( strMail, sTemp ); 
	} 
	if ( pMailHeader->pcDisplayCc[0] != '\0' ) 
	{ 
		sprintf( sTemp, "Cc: %s", pMailHeader->pcDisplayCc ); 
		addHeaderLine( strMail, sTemp ); 
	} 
	if ( pMailHeader->pcDisplayBcc[0] != '\0' ) 
	{ 
		sprintf( sTemp, "Bcc: %s", pMailHeader->pcDisplayBcc ); 
		addHeaderLine( strMail, sTemp ); 
	} 
/*	 
	//收件人数量 
	int iRcvrCount = pMailHeader->iRcvrCount; 
	//收件人 
	LPMAIL_USR lpRecipience; 
    int i; 
	 
	// From: 
	sprintf( sTemp, "From: \"%s\" <%s>", pMailHeader->lpSender->lpszName, 
		    pMailHeader->lpSender->lpszAddress ); 
	addHeaderLine( strMail, sTemp ); 
		 
	// To/Cc/Bcc: 
	for ( i = 0; i < iRcvrCount; i++ ) 
	{ 
		//lpRecipience = getRecipient( pMailHeader, i ); 
		lpRecipience = &pMailHeader->lpReceiver[i]; 
		sprintf( sTemp, "\"%s\" <%s>",lpRecipience->lpszName,  
			     lpRecipience->lpszAddress ); 
 
		switch ( lpRecipience->lRecipClass ) 
		{ 
		case TO: 
			if( '\0' == sTo[0] ) 
			{ 
				sprintf( sTo, "To: %s", sTemp ); 
			} 
			else 
			{ 
				strcat( sTo, ",\r\n\t" ); 
				strcat( sTo, sTemp ); 
			} 
			break; 
		case CC: 
			if ( '\0' == sCc[0] ) 
			{ 
				sprintf( sCc, "Cc: %s", sTemp ); 
			} 
			else 
			{ 
				strcat( sCc, ",\r\n\t" ); 
				strcat( sCc, sTemp ); 
			} 
			break; 
		case BCC: 
			if ('\0' == sBcc[0]) 
			{ 
				sprintf( sBcc, "Bcc: %s", sTemp ); 
			} 
			else 
			{ 
				strcat( sBcc, ",\r\n\t" ); 
				strcat( sBcc, sTemp ); 
			} 
			break; 
		default: 
			break; 
		} 
	} 
	 
	//将收信人信息追加到字符串strMail 
	if ( sTo[0] != '\0' )  
	{ 
		addHeaderLine( strMail, sTo ); 
	} 
	if ( sCc[0] != '\0' )  
	{ 
		addHeaderLine( strMail, sCc ); 
	} 
	if ( sBcc[0] != '\0' )  
	{ 
		addHeaderLine( strMail, sBcc ); 
	} 
*/ 
	// Date: 
	// Format: Mon, 01 Jun 98 01:10:30 GMT 
	lt = time( NULL ); 
	ptrTime = localtime( < ); 
	 
	strftime( sTemp2, MAX_BUFFER_SIZE, "Date: %a, %d %b %y %H:%M:%S ", ptrTime ); 
 
	// 时区计算 
	dwReturn  = GetTimeZoneInformation( &timezoneinfo ); 
		switch ( dwReturn ) 
		{ 
		case TIME_ZONE_ID_UNKNOWN: 
		case TIME_ZONE_ID_STANDARD: 
			lTimeDifferential = timezoneinfo.Bias + timezoneinfo.StandardBias; 
			//Bias is in minutes--calculate the hours for HHMM format. 
			lHours = -(lTimeDifferential/60); 
			//Bias is in minutes--calculate the minutes for HHMM format. 
			lMinutes = lTimeDifferential%60L; 
			break; 
		case TIME_ZONE_ID_DAYLIGHT: 
			lTimeDifferential = timezoneinfo.Bias + timezoneinfo.DaylightBias; 
			//Bias is in minutes--calculate the hours for HHMM format. 
			//Need to take the additive inverse. 
			//Bias is based on GMT=Local+Bias. 
			//We need a differential based on GMT=Local-Bias. 
			lHours = -(lTimeDifferential/60); 
			//Bias is in minutes--calculate the minutes for HHMM format. 
			lMinutes = lTimeDifferential%60L; 
			break; 
		case TIME_ZONE_ID_INVALID: 
			assert( FALSE ); 
			break; 
		} 
 
	sprintf( sTemp, "%s%+.2d%.2d", sTemp2, lHours, lMinutes ); 
	addHeaderLine( strMail, sTemp ); 
 
	// Subject: 将邮件标题转为Base64编码,并追加到strMail 
	if ( pMailHeader->pcSubject[0] != '\0' ) 
	{ 
		Base64Encode( (char *const)sTemp2,  
						(const unsigned char*)pMailHeader->pcSubject, 
						strlen(pMailHeader->pcSubject) ); 
		sprintf( sTemp, "Subject: =?gb2312?B?%s?=", sTemp2 ); 
		addHeaderLine( strMail, sTemp ); 
	} 
/*	 
	// X-Mailer:表示信件是从哪个客户端发送出来的 
 
	sprintf( sTemp, "X-Mailer: %s", pMailHeader->XXXX ); 
	addHeaderLine( strMail, sTemp ); 
*/ 
	// X-Priority:  
    sprintf( sTemp, "X-Priority: %s",  
				_ltoa(pMailHeader->lImportance, strImportance, 10) ); 
	addHeaderLine( strMail, sTemp ); 
 
	addHeaderLine( strMail, "MIME-Version: 1.0" ); 
} 
 
//-------------------------------------------------------------- 
//  功能:将邮件体信息追加到到字符串 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strMail MIME编码后邮件字符串指针 
//	OUT char* strError 错误信息提示 
//	返回值:成功为TRUE,失败为FALSE 
//-------------------------------------------------------------- 
static BOOL prepareBody( LPVOID pMail, char *strMail, char *strError ) 
{ 
	LPNOTE_DETAIL pMailBody = (LPNOTE_DETAIL)pMail; 
	BOOL bRet; 
	LPMAIL_ATCH lpMailAttach; 
 
	char sTemp[MIN_BUFFER_SIZE]={'\0'}; 
	char strBoundaryLevel[sizeof(int)+1]; 
	int i; 
 
	if ( !pMailBody->bHasAttach ) 
	// 不带带附件的邮件处理 
	{	 
		// 添加正文 
		bRet = appendText( pMail, strMail, strError ); 
	} 
	// 带附件的邮件处理 
	else 
	{ 
		//Content-Type: multipart/mixed; boundary=_0_.__.__TOL__Mailer__Part_Boundary_ 
		sprintf( sTemp, "Content-Type: %s;\r\n\tboundary=_%s%s\r\n",  
						CONTENT_TYPE_MULTIPART,  
						_itoa(BoundaryLevel, strBoundaryLevel, 10),  
						MAIL_PART_BOUNDARY ); 
		addHeaderLine( strMail, sTemp ); 
		 
		addHeaderLine( strMail, "This is a multi-part message in MIME format.\r\n" ); 
		 
		// 添加正文 
		insertBoundary( strMail ); 
		bRet = appendText( pMail, strMail, strError ); 
		 
		// 如果正文添加失败,则不进行附件添加 
		// 当正文在字符串中保存时总返回TRUE 
		if ( bRet ) 
		{ 
			for ( i = 0; i < pMailBody->iAttachCount; i++ ) 
			{ 
				// 添加附件 
				// lpMailAttach = getMailAttach(pMailBody, i); 
				lpMailAttach = &pMailBody->lpAttach[i]; 
				appendAttach( lpMailAttach, strMail, strError ); 
			}// end for 
		}// end if 
	}// end else 
	 
	return bRet; 
} 
 
//-------------------------------------------------------------- 
//  功能:将邮件正文MIME编码并追加到字符串 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strMail MIME编码后邮件字符串指针 
//	OUT char* strError 错误信息提示 
//	返回值:成功为TRUE,失败为FALSE 
//-------------------------------------------------------------- 
static BOOL appendText( LPVOID pMail, char *strMail, char *strError ) 
{ 
	char sTemp[MIN_BUFFER_SIZE]; 
	int fbeginToEncode; 
/*	 
	// 正文以文件形式保存时 
	char *pcFilename = ( (LPNOTE_DETAIL)pMail )->pcBodyFilePathName; 
	BOOL bRet; 
*/ 
	char *pcTextBody = ( (LPNOTE_DETAIL)pMail )->pcBodyContent; 
	 
	 
	assert(pMail != NULL && strMail != NULL); 
	 
	// 没有邮件正文时不做处理 
	if ( '\0' == pcTextBody[0] ) 
	{ 
		return TRUE; 
	} 
	 
	// 设置SMTP正文头部参数 
/*	 
	// 用于发送html格式的邮件 
	// Content-Type: text/html; charset="iso-8859-1" 
	sprintf( sTemp, "Content-Type: %s; charset=\"%s\"",  
							"text/html", "gb2312" ); 
*/ 
	// 用于发送文本格式的邮件 
	// Content-Type: text/plain; charset="gb2312" 
	sprintf( sTemp, "Content-Type: %s; charset=\"%s\"",  
					CONTENT_TYPE_STRING, CHAR_SET ); 
	addHeaderLine( strMail, sTemp ); 
	 
	// Content-Transfer-Encoding: base64 
	sprintf( sTemp, "Content-Transfer-Encoding: %s\r\n",  
					TRANSFER_ENCODING_B64 ); 
	addHeaderLine( strMail, sTemp ); 
/*	 
	// 将指定文件中的邮件正文编码并追加到strMail 
	bRet = appendFileBody(( (LPNOTE_DETAIL)pMail )->pcBodyFilePathName,  
								strMail, strError ); 
*/ 
	// 将邮件正文紧接在strMail字符串的后面 
	fbeginToEncode = strlen( strMail ); 
	Base64Encode( (char *const)(&strMail[fbeginToEncode]),  
					(const unsigned char*)pcTextBody,  
					strlen(pcTextBody) ); 
 
	return TRUE; 
} 
 
//-------------------------------------------------------------- 
//  功能:获得一个收件人信息 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	返回值:收件人结构体指针 
//-------------------------------------------------------------- 
static LPMAIL_USR getRecipient( LPNOTE_DETAIL pMail, int i ) 
{ 
	return &pMail->lpReceiver[i]; 
} 
 
//-------------------------------------------------------------- 
//  功能:获得一个附件信息 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	返回值:附件结构体指针 
//-------------------------------------------------------------- 
static LPMAIL_ATCH getMailAttach( LPNOTE_DETAIL pMail, int i ) 
{ 
	return &pMail->lpAttach[i]; 
} 
 
//-------------------------------------------------------------- 
//  功能:得到Content-Type 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT sTemp 输出Content-Type字符串 
//	返回值:成功TRUE,失败为FALSE 
//-------------------------------------------------------------- 
static BOOL getContentType(LPMAIL_ATCH lpMailAttach,char *sTemp) 
{ 
	 
	char *szPostfix; 
	int ch = '.'; 
	BOOL bRet = FALSE; 
	assert(lpMailAttach != NULL); 
	//得到附件的后缀名 
	szPostfix = strrchr(lpMailAttach->lpszName,ch)+1; 
	// 设置SMTP附件头部参数 
	// Content-Type: text/plain; file=XXXXX 
	if((strcmp(szPostfix,"txt") == 0) || (strcmp(szPostfix,"TXT") == 0)) 
	{ 
		sprintf( sTemp, "Content-Type: %s; file=%s", 
			CONTENT_TYPE_STRING,lpMailAttach->lpszName ); 
		bRet = TRUE; 
	} 
	else if((strcmp(szPostfix,"jpg") == 0) || (strcmp(szPostfix,"JPG") == 0)) 
	{ 
		sprintf( sTemp, "Content-Type: %s; file=%s", 
			CONTENT_TYPE_JPG,lpMailAttach->lpszName ); 
		bRet = TRUE; 
	} 
	else 
	{ 
		sprintf( sTemp, "Content-Type: %s; file=%s", 
			CONTENT_TYPE_DEF,lpMailAttach->lpszName ); 
		bRet = TRUE; 
	} 
	return bRet; 
} 
//-------------------------------------------------------------- 
//  功能:将附件追加到字符串 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strMail MIME编码后邮件字符串指针 
//	OUT char* strError 错误信息提示 
//	返回值:成功为TRUE,失败为FALSE 
//-------------------------------------------------------------- 
static BOOL appendAttach( LPMAIL_ATCH lpMailAttach, char *strMail, char *strError ) 
{ 
	char sTemp[MIN_BUFFER_SIZE]; 
	BOOL bRet = FALSE; 
		 
	insertBoundary( strMail ); 
	if(!getContentType(lpMailAttach,sTemp)) 
		return bRet; 
	// 设置SMTP附件头部参数 
	// Content-Type: text/plain; file=XXXXX 
	/*if(strcmp(szPostfix,"txt") == 0) 
	{ 
		sprintf( sTemp, "Content-Type: %s; file=%s", 
				CONTENT_TYPE_STRING,lpMailAttach->lpszName ); 
	} 
	 
	else// Content-Type: application/octet-stream; file=XXXXX 
	{ 
		sprintf( sTemp, "Content-Type: %s; file=%s",  
			CONTENT_TYPE_OCTET_STREAM, lpMailAttach->lpszName ); 
	} 
	*/ 
	addHeaderLine( strMail, sTemp ); 
 
	// Content-Transfer-Encoding: base64 
	sprintf( sTemp, "Content-Transfer-Encoding: %s", TRANSFER_ENCODING_B64 ); 
	addHeaderLine( strMail, sTemp ); 
 
	// Content-Disposition: attachment; filename=XXXXX 
	sprintf( sTemp, "Content-Disposition: attachment; filename=%s\r\n",  
						lpMailAttach->lpszName ); 
	addHeaderLine( strMail, sTemp ); 
	 
	// 将指定文件中的附件编码并追加到strMail 
	bRet = appendFileBody(lpMailAttach->lpszPathName, strMail, strError ); 
 
	return bRet; 
} 
 
//-------------------------------------------------------------- 
//  功能:将指定路径文件的内容BASE64编码并追加到字符串 
//	参数: 
//	IN LPVOID pMail 邮件结构指针 
//	OUT char* strMail MIME编码后邮件字符串指针 
//	OUT char* strError 错误信息提示 
//	返回值:成功为TRUE,失败为FALSE 
//-------------------------------------------------------------- 
static BOOL appendFileBody(char *plszfilename, char *strMail, char *strError ) 
{ 
/*	FILE *fp; 
 
	unsigned char buf[MAX_BUFFER_SIZE]; 
	size_t iflag;			 
	size_t iReadSize;		//记录从文件中读出的长度 
	size_t iWriteSize;		//记录Base64编码后的长度 
	 
	 
 
	assert(plszfilename!=NULL && strMail!=NULL); 
*/ 
	//以二进制方式“读打开” 
/*	fp = fopen( plszfilename, "rb" ); 
	 
	if( NULL == fp ) 
	{ 
		sprintf(strError, "%s: %s", ERROR_OPEN_FILE_FAIL, plszfilename); 
		return FALSE; 
	} 
	 
	//从strMail字符串的结束符的位置开始保存编码后的邮件正文 
	//iflag用于记录每次保存的开始位置 
	 
	iflag = strlen( strMail ); 
	while( !feof(fp) ) 
	{ 
		iReadSize = fread( buf, sizeof(char), MAX_BUFFER_SIZE,  fp ); 
		//如果文件为空不进行编码转换. 
		if ( 0 == iReadSize ) 
		{ 
			continue; 
		} 
		 
		iWriteSize = Base64Encode( (char *const)(&strMail[iflag]),  
			                    (const unsigned char*)buf, iReadSize ); 
		 
		iflag +=iWriteSize; 
	} 
	fclose( fp ); 
*/ 
	long lfileSize; 
	int handle; 
	void *plbuf; 
	int fbeginToEncode; 
 
	assert(plszfilename!=NULL && strMail!=NULL); 
	 
	// 以二进制只读形式打开文件 
	handle = open( plszfilename, _O_BINARY ); 
	if ( -1 == handle ) 
	{ 
		sprintf( strError, "%s: %s", ERROR_OPEN_FILE_FAIL, plszfilename ); 
		return FALSE; 
	} 
	 
	// 获得文件大小,单位为byte 
	lfileSize = filelength( handle );	 
	// –1L to indicate an error, and an invalid handle sets errno to EBADF 
	if ( -1L == lfileSize ) 
	{ 
		sprintf( strError, "%s: %s", ERROR_EBADF, plszfilename ); 
		close( handle ); 
		return FALSE; 
	} 
	// 文件不为空时进行编码 
	if ( lfileSize > 0L ) 
	{ 
		//分配合适的缓冲区存放文件的备份 
		plbuf = malloc( lfileSize + 1 ); 
		if (NULL == plbuf) 
		{ 
			sprintf( strError, "%s", ERROR_MALLOC_FAILE ); 
			close( handle ); 
			return FALSE; 
		} 
		 
		read( handle, plbuf, lfileSize ); 
		 
		// 将缓冲区中的数据编码,编码后的数据紧接在strMail字符串的后面 
		fbeginToEncode = strlen( strMail ); 
		Base64Encode( (char *const)(&strMail[fbeginToEncode]),  
						(const unsigned char*)plbuf,lfileSize ); 
	 
		// 释放内存 
		free( plbuf ); 
	} 
	// 关闭文件 
	close( handle ); 
 
	return TRUE; 
} 
 
//-------------------------------------------------------------- 
//  功能:为mime邮件添加边界标记 
//	参数: 
//	IN/OUT char* strMail MIME编码后邮件字符串指针 
//	返回值:空 
//-------------------------------------------------------------- 
static void insertBoundary( char* strMail ) 
{ 
	char sTemp[64]; 
	char strBoundaryLevel[sizeof(int)+1]; 
	char * lastTowChar = &strMail[strlen(strMail)-2]; 
	 
	// 保证在插入边界前,字符串的末尾为“\r\n” 
	if ( (strcmp(lastTowChar, "\r\n")) != 0 ) 
	{ 
		strcat(strMail, "\r\n"); 
	} 
 
	sprintf( sTemp, "\r\n--_%s%s\r\n",  
				_itoa(BoundaryLevel, strBoundaryLevel, 10),  
				MAIL_PART_BOUNDARY ); 
	strcat(strMail, sTemp); 
} 
 
//-------------------------------------------------------------- 
//  功能:获得文件大小,单位为Byte 
//	参数: 
//	IN char *fileName 文件路径名字符串 
//	返回值:-1 文件打开失败 
//			其它 以byte为单位的文件大小 
//-------------------------------------------------------------- 
static long getByteFileSize( char *fileName ) 
{ 
	int handle; 
	long lfileSize; 
	 
	// 获得文件句柄 
	handle = open( fileName, _O_BINARY ); 
	 
	// 当open返回-1时表示打开文件错误 
	if ( -1 == handle ) 
	{ 
		return ( -1L ); 
	} 
	 
	// filelength函数返回 –1L 表示: invalid file-handle 
	lfileSize = filelength( handle ); 
	 
	// 关闭文件 
	close( handle ); 
 
	return ( lfileSize ); 
 
} 
 
 
//end 
 
/* 
From: "wan ning"  
To: "william"  
Date: Thu, 16 Nov 06 16:20:28 +0800 
Subject: =?gb2312?B?xOO6wyE=?= 
X-Priority: 0 
MIME-Version: 1.0 
Content-Type: multipart/mixed; 
	boundary=_0_.__.__TOL__Mailer__Part_Boundary_ 
 
This is a multi-part message in MIME format. 
 
 
--_0_.__.__TOL__Mailer__Part_Boundary_ 
Content-Type: text/plain; charset="gb2312" 
Content-Transfer-Encoding: base64 
 
PGhlYWQ+DQoJPHRpdGxlPg0KCQloZWxsbyx0ZXN0DQoJPC90aXRsZT4NCjwvaGVhZD4NCjxoMT7E 
47rD1tC5+iENCjxoMj4gaGVsbG8sIHdvcmxkIQ0KPGJvZHk+DQo8L2JvZHk+ 
 
--_0_.__.__TOL__Mailer__Part_Boundary_ 
Content-Type: application/octet-stream; file=body.txt 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename=body.txt 
 
YWJjxOO6w6Oh1tC5+g== 
 
*/