⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtp.c

📁 在嵌入式linux下发送邮件的SMTP客户端程序。基于mips平台可直接使用
💻 C
📖 第 1 页 / 共 4 页
字号:
//===================================================================
//	Asoka USA Corporation
//	文件名	:SMTP.cpp
//	作  者	:charlie(刘翔)
//	版  本	:
//	完成日期:2006-01-08
//	说  明	:此文件是用来实现SMTP协议处理
//	其  它	:
//	函数列表:	Data
//						Mail
//						Connect
//						......
//			 
//
//	历史记录:
//		作者:
//	修改内容:
//
//	2.	...


////////////////////////////////////////////////////////////////////////// 
// SMTP.cpp: implementation of the CSMTP class. 
// 
////////////////////////////////////////////////////////////////////// 

#include "SMTP.h" 
#include "Base64Coder.h"
#include <malloc.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <memory.h>
#include <unistd.h>
#include <netdb.h>


BOOL Mail(SMTP struMail); 

char* GetHost();

void SetHost(char* Host); 

//发送DATA命令信息
BOOL Data(SMTP struMail);	

//// 发送TO命令信息
BOOL SetTo(SMTP struMail); 

//发送MAIL命令信息
BOOL MailCMD(char* from); 

//和SMTP服务器断开连接
BOOL Disconnect();	

//和SMTP服务器进行连接
//BOOL Connect(); 

// 该函数是通过扩展SMTP会话方式连接服务器的
BOOL ConnectSrvSMTP(const char* pszLocalName, const char* pszUsername, const char* pszPassword);

// 使用AUTH LOGIN命令协商登录,即需要对用户名进行编码
BOOL AuthLogin(const char* pszUsername, const char* pszPassword);

//检查指定命令的响应信息
BOOL ReadCommandResponse(int nExpectedCode);

//检查邮件服务器的详细响应信息
BOOL ReadResponse(char* pszBuffer, int nInitialBufSize, char* pszTerminator, int nExpectedCode, char** ppszOverFlowBuffer, int nGrowBy);

char* GetError(char* Response); 

//检查邮件服务器的响应信息
BOOL CheckResponse(int Type);	

BOOL ProcedureCMD(int Type, char* buf);

char* T2A(char* lp);

//获取文件的内容信息
char* GetFileBody(char* strFileName, int* nBodySize);

//获取附件的头信息
char* GetAttachmentHeader(int* nHeaderSize, char* strFileName);

//发送指定信息的邮件
BOOL SendMailInfo(SMTP struMail);

//发送邮件的附件信息
BOOL SendAttachment(SMTP struMail);

//发送附件的尾信息
char* GetFooter(int* nFooterSize);

//发送邮件头信息
BOOL SendMIMEHead(SMTP struMail);

//MIME信息中需要增加邮件头中的MIME信息
BOOL GetMIMEHead(char* strMIMEHeadInfo);

//发送邮件的邮件头信息
BOOL SendHeader(SMTP struMail);

//判断是否是带附件的邮件
void ISMIME(SMTP struMail);

//检查邮件信息的合法性
BOOL CheckMailInfo(SMTP struMail);

//设置邮件的发送人信息
void SetSenderName(SMTP* struMail, char* strSenderName); 

//对SUBJECT信息进行编码处理
char* EnSubJectCodeString(char* sText);

//对邮件体BODY信息进行编码处理
void EnBodyCodeString(char* sText, char* strEncode); 

//初始化SMTP信息
void Initialize(SMTP *EmailSMTP);

//设置附件的文件信息
void SetFile(SMTP* struMail, char* strFileName);

//设置邮件的标题信息
void SetMailSubject(SMTP* struMail, char* strMailSubject); 

//设置邮件的正文信息
void SetMailText(SMTP* struMail, char* strMailText); 

//设置用户的帐号信息
void SetUSERID(SMTP* struMail, char* strUSERID); 

//设置用户的密码信息
void SetPWD(SMTP* struMail, char* strPWD); 

//设置邮件的SMPT服务器信息
void SetSMTPServer(SMTP* struMail, char* strSMTPServer); 

//设置邮件的目的址信息
void SetSendTo(SMTP* struMail, char* strSendTo);

//设置邮件的源地址信息
void SetSendFrom(SMTP* struMail, char* strSendFrom);

//对指定的字符串进行BASE64编码
void EnCodeString(char* strSoure,char* strEnCode);

BOOL IsSameWeek(char* strWeek, int weekly);

//根据Quoted printable编码规则对数据进行编码处理
void QuotedPrintableEncode(char* sText, char* strEncode);

char HexDigit(int nDigit);

char*  substr(char* pstrChar, int iBegin, int nLength);

//查找指定字符串
int   find(char* pstrChar, const char* strSoure);

//查询函数
int  rfind(char* strData, const char* strSoure);


BOOL  Create();
BOOL  ConnectServer(const char* pszHostAddress, int nPort);
BOOL  ConnectSvr(const struct sockaddr* lpSockAddr, int nSockAddrLen);
BOOL  SendDate(const char*  pszBuf, int nBuf);
void   CloseSocket();
int    Receive(char*  pszBuf, int nBuf);
//BOOL  IsReadable(BOOL bReadible);

static   BOOL				g_bMIME = TFALSE;	
static   int 				g_hSocket = -1; 
static   int				g_NoOfTo = 0;											//发送的目的地址的个数	
static   char				g_ErrorMessage[128];		
static   char				g_Host[128];											//主机信息
static   int				g_nLastCommandResponseCode = 0;
static   char				g_sLastCommandResponse[128];		
static   int				g_dwTimeout = 0;									//超时时间
static   BOOL				g_bConnected = TFALSE;	
static   char				g_strBoundary[128];								//Boundary信息,MIME中定义的数据
static   char				g_strEncode[128];								//编码方式,MIME中定义的数据
static   char				g_stCharset[128];								//charset信息,MIME中定义的数据

////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 

void Initialize(SMTP *EmailSMTP)
{ 
	//重新初始化全局变量
	g_NoOfTo = 0; 	
	g_dwTimeout = 120;			//超时时间设置为120秒
	g_bMIME = TFALSE;	
	g_bConnected = TFALSE;	
	memset(g_strBoundary, 0, 128);	
	memset(g_strEncode, 0, 128);	
	memset(g_stCharset, 0, 128);	
	strcpy(g_strBoundary, "18ac0781-9ae4-4a2a-b5f7-5479635efb6b");	
	strcpy(g_strEncode ,"base64");
	strcpy(g_stCharset, "gb2312");
	g_hSocket = -1;
	
	//初始化SMTP结构
	memset(EmailSMTP->m_strFile, 0, 128);					
	memset(EmailSMTP->m_strSendFrom, 0, 64);			
	memset(EmailSMTP->m_strSendTo, 0, 64);			
	memset(EmailSMTP->m_strSMTPServer, 0, 64);			
	memset(EmailSMTP->m_strPWD, 0, 64);			
	memset(EmailSMTP->m_strUSERID, 0, 64);						
	memset(EmailSMTP->m_strMailText, 0, 64);			
	memset(EmailSMTP->m_strMailSubject, 0, 64);			
	memset(EmailSMTP->m_strSenderName, 0, 64);		
	
} 

char* T2A(char* lp)
{ 
	return lp; 
}

// 读取主机信息
char* GetHost( )
{ 
	return g_Host; 
} 

//设置主机信息
void SetHost(char* Host) 
{ 
	memset(g_Host, 0, 128);
	strcpy(g_Host, Host);
} 

//连接SMTP服务器
BOOL ConnectSMTP(SMTP struMail) 
{ 
	// printf("begin Connect!\n");
	//char* From= NULL;
	//char* strtemp = NULL;
	//char* Host = NULL;
	//int		nPos = 0;
	char sHostName[100];
	BOOL bConnectOk = TFALSE;	
	//char*  strUsername = NULL;
	//char*  strPassword = NULL;	

	/*
	nPos = find(struMail.m_strSendFrom, "@");	
	From = substr(struMail.m_strSendFrom, 0, nPos);
	strcat(From, struMail.m_strSMTPServer);
	*/
	
	// SMTP端口默认是25
	if (!ConnectServer(struMail.m_strSMTPServer, 25)) 
	{ 
		strcpy(g_ErrorMessage,  "Server cannot be connected"); 
		printf("Server cannot be connected!\n"); 	
		return TFALSE; 
	}
	
	else 
	{ 
		// printf("Connect successfully!\n"); 
		//检查返回的值是否是220
		if(CheckResponse(CONNECTION_CHECK) == TFALSE) 
		{		
			return TFALSE; 
		}
		
		//获得本地机器名		
		memset(sHostName, 0, 100);
		gethostname(sHostName, sizeof(sHostName));		
		
		// 进行下一步连接,即进行SMTP会话,采用鉴权方式进行会话			
		bConnectOk = ConnectSrvSMTP(sHostName, struMail.m_strUSERID , struMail.m_strPWD );
		if(bConnectOk == TFALSE)
		{
			printf("ConnectESMTP fail!\n"); 		
			return TFALSE; 
		}		
		
		return TTRUE; 
	} 	

} 

// 该函数是通过扩展SMTP会话方式连接服务器的
BOOL ConnectSrvSMTP(const char* pszLocalName, const char* pszUsername, const char* pszPassword)
{
	char	sBuf[128];
	char*	pszData = NULL;
	BOOL	bLoginOk = TFALSE;
	int		nCmdLength = 0;
	
	//验证参数
	if((pszLocalName == NULL) || (pszUsername == NULL)|| (pszPassword == NULL))
	{
		return TFALSE;
	}
	
	//发送EHLO命令	
	memset(sBuf, 0, 128);
	strcpy(sBuf, "EHLO ");	
	strcat(sBuf, pszLocalName);
	strcat(sBuf, "\r\n");	
	
	pszData = T2A(sBuf);
	nCmdLength = strlen(pszData);
	if (!SendDate(pszData, nCmdLength))
	{
		return TFALSE;
	}
	
	//检查Hello命令的响应 250
	if(CheckResponse(HELLO_CHECK)==TFALSE) 
	{
		return TFALSE; 
	}	
	
	//进行帐号密码验证
    bLoginOk = AuthLogin(pszUsername, pszPassword); 
	if(bLoginOk == TFALSE)
	{
		return TFALSE;
	}	
	
	return bLoginOk;
}

// 使用AUTH LOGIN命令协商登录,即需要对用户名进行编码
BOOL AuthLogin(const char* pszUsername, const char* pszPassword)
{
	char		sBuf[128];
	int			nCmdLength = 0;
	char*		pszData = NULL;
	char*		temp = NULL;
	char*		pTmp = NULL;		
	char*		sLastCommandString = NULL;
	char*		pszLastCommandString = NULL;
	Base64Coder Coder;
	Base64Coder CoderPWD;
	
	//验证参数
	if((pszUsername == NULL)|| (pszPassword == NULL))
	{
		return TFALSE;
	}
	
	//发送AUTH LOGIN命令	
	temp = (char*)malloc(100);
	//检查分配内存是否成功
	if(temp == NULL)
	{
		return TFALSE;
	}
	
	memset(sBuf, 0, 128);
	strcpy(sBuf, "AUTH LOGIN\r\n");
	pszData = T2A(sBuf);
	nCmdLength = strlen(pszData);	
	if (!SendDate(pszData, nCmdLength))
	{
		printf("An unexpected error occurred while sending the AUTH command\n");
		free(temp);
		temp = NULL;
		return TFALSE;
	}
	
	//初始化
	
	//检查Hello命令的响应 334
	if (!ReadCommandResponse(334))
	{
		printf("Server does not support AUTH LOGIN!\n");
		free(temp);
		temp = NULL;
		return TFALSE;
	}
	else
	{		
		//发送base64编码后的用户名
		sLastCommandString = (char*)malloc(1024);
		if(sLastCommandString == NULL)
		{
			free(temp);
			temp = NULL;
			return TFALSE;
		}
		strcpy(sLastCommandString , g_sLastCommandResponse);
		//需要进行数据测试
		sLastCommandString = substr(sLastCommandString, 4, strlen(sLastCommandString) -4);
		pszLastCommandString = T2A(sLastCommandString);
		Base64CoderInit(&Coder);
		_Init(&Coder);
		Decode(&Coder, pszLastCommandString);		
		if (strcmp(DecodedMessage(Coder), "Username:") == 0)
		{
			Encode(&Coder, T2A((char*)pszUsername));			
			memset(temp, 0, 100);
			sprintf(temp, "%s\r\n", EncodedMessage(Coder));			
			strcpy(sBuf, (const char*)temp);			
			
			pszData = T2A((char*)sBuf);
			nCmdLength = strlen(pszData);
			if (!SendDate(pszData, nCmdLength))
			{
				printf("An unexpected error occurred while sending the username\n");	
				free(sLastCommandString);				
				sLastCommandString = NULL;
				free(temp);
				temp = NULL;
				return TFALSE;
			}
			
		}
		else
		{
			printf("An unexpected request received when expecting username request");
			free(sLastCommandString);				
			sLastCommandString = NULL;
			free(temp);
			temp = NULL;
			return TFALSE;
		}
	}
	
	//重新分配内存资源	
	free(sLastCommandString);
	sLastCommandString = NULL;
	sLastCommandString = (char*)malloc(1024);
	if(sLastCommandString == NULL)
	{
		return TFALSE;
	}
	
	//检查返回用户名返回码 
	if (!ReadCommandResponse(334))
	{
		printf("Server did not response correctly to AUTH LOGIN username field!\n");
		free(sLastCommandString);
		sLastCommandString = NULL;
		free(temp);
		temp = NULL;
		return TFALSE;
	}
	else
	{
		//发送密码到服务器	
		memset(sLastCommandString, 0, 1024);
		strcpy(sLastCommandString, g_sLastCommandResponse);		
		pTmp = substr(sLastCommandString, 4, strlen(sLastCommandString) -4);
		pszLastCommandString = T2A(pTmp);
		Base64CoderInit(&CoderPWD);
		_Init(&CoderPWD);
		Decode(&CoderPWD, pszLastCommandString);	
		if (strcmp(DecodedMessage(CoderPWD), "Password:") == 0)
		{
			Encode(&CoderPWD, T2A((char*)pszPassword));
			memset(temp, 0, 100);
			sprintf(temp, "%s\r\n", EncodedMessage(CoderPWD));
			strcpy(sBuf, (const char*)temp);			
			
			pszData = T2A(sBuf);
			nCmdLength = strlen(pszData);
			if (!SendDate(pszData, nCmdLength))
			{
				printf("An unexpected error occurred while sending the password\n");
				free(sLastCommandString);
				sLastCommandString = NULL;
				free(temp);
				temp = NULL;
				return TFALSE;
			}
			
			//检查是否成功
			if (!ReadCommandResponse(235))
			{
				printf("AUTH LOGIN authentication was unsuccessful\n");
				free(sLastCommandString);
				sLastCommandString = NULL;
				free(temp);
				temp = NULL;
				return TFALSE;
			}
			
			// printf("Test Password successfully!\n"); 
		}
		else
		{
			printf("An unexpected request received when expecting password request\n");
			free(sLastCommandString);
			sLastCommandString = NULL;
			free(temp);
			temp = NULL;
			return TFALSE;
		}
	}
	
	free(sLastCommandString);
	sLastCommandString = NULL;
	free(temp);
	temp = NULL;
	return TTRUE;
}

// 发送"QUIT"命令到SMTP服务器: 
BOOL Disconnect() 
{ 
	char buf[256]; 
	memset(buf, 0, 256);	
	sprintf (buf, "QUIT \r\n"); 
	
	//发送QUIT命令
	if(SendDate(buf, strlen (buf)) == TFALSE)
	{
		return TFALSE; 
	}
	
	//检查是否正常退出
	if (CheckResponse(QUIT_CHECK) == TFALSE) 
	{
		return TFALSE; 
	}
	else 
	{
		return TTRUE; 
	}
} 

// 发送"MAIL" 命令到SMTP服务器: 
BOOL MailCMD(char* from) 
{ 
	char buf[256]; 	
	memset(buf, 0, 256);	
	sprintf(buf, "MAIL FROM:<%s>\r\n", from); 
	
	//发送MAIL命令
	if(SendDate(buf, strlen (buf)) == TFALSE)
	{
		return TFALSE; 
	}
	
	//检查MAIL命令是否正常处理
	if (CheckResponse(MAIL_CHECK) == TFALSE) 
	{
		return TFALSE; 
	}
	else 
	{
		return TTRUE; 
	}
} 

// 发送TO命令信息
BOOL SetTo(SMTP struMail) 
{ 
	char buf[256]; 
	memset(buf, 0, 256);	
	sprintf (buf, "RCPT TO:<%s>\r\n", struMail.m_strSendTo); 
	
	//发送TO命令
	if(SendDate(buf, strlen (buf)) == TFALSE)
	{
		return TFALSE; 
	}
	
	//检查TO命令是否正常处理
	if (CheckResponse(RCPT_CHECK) == TFALSE) 
	{
		return TFALSE; 
	}
	
	return TTRUE; 	
} 

// 发送"DATA" 命令到 SMTP 服务器: 
//进行扩展,可以发送文件
BOOL Data(SMTP struMail) 
{ 
	char buf[256];
	//char* Subject = NULL;
	//char* Body = NULL;
	//char* strFileName = NULL;
	
	memset(buf, 0, 256);
	
	//发送DATA命令
	sprintf(buf, "DATA\r\n"); 	
	SendDate(buf, strlen (buf)); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -