I.数据结构
{
int i4ServerIp; //smtp服务器ip
char ServerDomainName[]; //服务器域名
int ServerIpType[]; //ip类型,ipv4 ipv6 dns
int ServerPort; //smtp服务器端口号
char SendMail[]; //发送邮箱
char SendMailKey[]; //邮箱密码
char RecvMail[]; //收件邮箱
}
注:非完整代码,仅提供思路。
II.Telnet测试
1.发送邮件
以smtp.qq.com服务器为例:
在终端执行telnet smtp.qq.com 25命令连接smtp服务器,连接成功会返回220消息。以下任何步骤错误都会返回502错误消息。
1) 打招呼
向服务器发送Helo打招呼(即hello缩写),登录方式为auth login,还有其他的登录方式,这里不作展开。
2) 登录
服务器返回334 VXNlcm5hbWU6,即base64编码的'Username:' 所以我们发送用户名时也要使用base64编码的数据。334 UGFzc3dvcmQ6即'Password:',密码也要用base64编码发送。
这里password是从qq邮箱获取的授权码,教程网上搜索即可。
3) 指定发件人/收件人
MAIL FROM:<xxxx@qq.com>
RCPT TO:<xxxx@qq.com>
4) 发送数据:
首先要先发送DATA,会返回消息354 End data with <CR><LF>.<CR><LF>. 意思是接下来的正文键入回车时不会再发送,而是要以 <CR><LF>.<CR><LF>结尾才会发送出去。
正文要先输入发送邮箱/收件邮箱和标题
From:<xxxx@qq.com>
To:<xxxx@qq.com>
Subject: Test Mail
正文
.
结束发送QUIT即可。如果继续发送,将从3)开始继续输入发件人/收件人
2.C/S完整沟通
C:telnet smtp.qq.com 25
S:220 newxmesmtplogicsvrszb1-0.qq.com XMail Esmtp QQ Mail Server.
C:HELO SMTP
S:250 OK
C:AUTH LOGIN
S:334 VXNlcm5hbWU6
C:NDkzNDM0NDk2QHFxLmNvbQ==
S:334 UGFzc3dvcmQ6
C:cGxleG96emJmZ2p5Y2JiZg==
S:235 Authentication successful
C:MAIL FROM:<493434496@qq.com>
S:250 OK
C:RCPT TO:<466526618@qq.com>
S:250 OK
C:DATA
S:354 End data with <CR><LF>.<CR><LF>.
C:FROM:<493434496@qq.com>
C:TO:<466526618@qq.com>
C:Subject:Test Mail
C:Hello world!
C:.
S:250 OK: queued as.
C:QUIT
S:221 Bye.
3.测试及结果
III. 邮件附件及uuencode编码
1.文本发送附件原理
如果将纯文本内容进行uuencode编码写在正文中就会被识别为附件。
uuencode编码都是以'begin 644 文件名'开始,644为文件操作权限;编码的内容每行为60字节,行首一般都是以M开头,在编码的结尾以` end结尾。
例如:
begin 644 test.txt
MQ*K,_;2IP=:T\M*VR?FCK+K.M\'2]]"EQ]+0[-#0H:/6\=7(PZ+0K,?ARJ3"
M[:.LRZW%PJ._(-*[R_+1S-/JR,[&O<GZH:,*P<_'S;2ZM^>TM;[&T-&CK,ZB
MP.2CK,F]S;?0L=75R+3/X-.MH:.[V,K7S_+`M,_TR:JTIJ.LN>G(I:.LTK+.
.WK?GT^K2LL[>Q^>AHPH``
end
如果在正文中加入这段编码,收到的邮件就会有一个test.txt的文件,文件内容就是解码后的内容:
莫听穿林打叶声,何妨吟啸且徐行。竹杖芒鞋轻胜马,谁怕? 一蓑烟雨任平生。
料峭春风吹酒醒,微冷,山头斜照却相迎。回首向来萧瑟处,归去,也无风雨也无晴。
2.uuencode编码原理
uuencode将连续3个字节扩展成4个字节的编码,扩展后的4个字符将落在uuencode编码表中。
扩展规则如下:
s[3]; //源字节
d[4]; //目标字节
//tbl为uuencode编码表
d[0] = tbl[s[0]>>2];
d[1] = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
d[2] = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
d[3] = tbl[s[2] & 0x3f];
//如果s[]不足3个字节时,d[]后面补空格
//uuencode编码表
tbl[] = {
'`', '!', '"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`'
};
行首字节是用来表示本行有多少个字节,通常以满行60字节(源数据45字节)时首字节就是tbl(45),及在tbl中是M字符,所以通常行首都是以M开头,只有最后一行不是。而且通常最后行的结尾有时因为不足3个字节要补空格,所以经常出现多个'`'符号的情况。
注:uuencode编码表和ASCII表唯一不同的是32号space换成了96号的'`'符号,因此补空格出现的是'`'。也因为uuencode编码表和ASCII码表基本相同,也可以用宏转换字符
#define ENCODE_BYTE(x) (((x) == 0) ? 0x60 : ((x) + 0x20))
d[0] = ENCODE_BYTE(s[0]>>2);
d[1] = ENCODE_BYTE(((s[0] & 3) << 4) + (s[1] >> 4));
d[2] = ENCODE_BYTE(((s[1] & 0xf) << 2) + (s[2] >> 6));
d[3] = ENCODE_BYTE(s[2] & 0x3f);
3. uuencode代码
void uuencode (char* pu1DstBuf, const char * pu1SrcBuf, int i4Length)
{
const UINT1 *s = pu1SrcBuf;
/* Transform the 3x8 bits to 4x6 bits */
while (i4Length > 0) {
UINT1 s1;
UINT1 s2;
/* Are s[1], s[2] valid or should be assumed 0? */
s1 = s2 = 0;
i4Length -= 3; /* can be >=0, -1, -2 */
if (i4Length >= -1) {
s1 = s[1];
if (i4Length >= 0)
s2 = s[2];
}
*pu1DstBuf++ = tbl[s[0] >> 2];
*pu1DstBuf++ = tbl[((s[0] & 3) << 4) + (s1 >> 4)];
*pu1DstBuf++ = tbl[((s1 & 0xf) << 2) + (s2 >> 6)];
*pu1DstBuf++ = tbl[s2 & 0x3f];
s += 3;
}
/* Zero-terminate */
*pu1DstBuf = '\0';
/* If length is -2 or -1, pad last char or two */
while (i4Length) {
*--pu1DstBuf = tbl[64];
i4Length++;
}
}
顺带说一句,如果将tbl换成以下的表,那就是base64编码。
//base64编码表
tbl[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
'=' ,
};
IV.smtp加密连接
1. smtp端口号
摘自知乎:smtp端口号
163.com:
接收邮件服务器: http://pop.163.com
接收端口: 110或995(使用ssl时)
接收邮件服务器: http://imap.163.com
接收端口: 143或993(使用ssl时)
发送邮件服务器: http://smtp.163.com
发送端口: 25或465/994(使用ssl时)
126邮箱:
接收邮件服务器: http://pop.126.com
接收端口: 110
发送邮件服务器: http://smtp.126.com
发送端口: 25
139邮箱:
POP3服务器地址:http://POP.139.com(端口:110)
SMTP服务器地址:http://SMTP.139.com(端口:25)
QQ邮箱:
接收邮件服务器: http://pop.qq.com
接收端口: 110或995(使用ssl时)
接收邮件服务器: http://imap.qq.com
接收端口: 143或993(使用ssl时)
发送邮件服务器: http://smtp.qq.com
发送端口: 25或465/587(使用ssl时)
QQ企业邮箱 :
POP3服务器地址:http://pop.exmail.qq.com (SSL启用 端口:995)
SMTP服务器地址:http://smtp.exmail.qq.com【端口:25或465/587(使用ssl时)】
gmail(http://google.com) :
POP3服务器地址:http://pop.gmail.com(SSL启用 端口:995)
SMTP服务器地址:http://smtp.gmail.com(SSL启用 端口:587)
Foxmail:
POP3服务器地址:http://POP.foxmail.com(端口:110)
SMTP服务器地址:http://SMTP.foxmail.com(端口:25)
sina.com:
接收邮件服务器: http://pop.sina.com
接收端口: 110
发送邮件服务器: http://smtp.sina.com
发送端口: 25
sinaVIP:
POP3服务器:http://pop3.vip.sina.com (端口:110)
SMTP服务器:http://smtp.vip.sina.com (端口:25)
sohu.com:
POP3服务器地址:http://pop3.sohu.com(端口:110)
SMTP服务器地址:http://smtp.sohu.com(端口:25)
雅虎邮箱:
接收邮件服务器: http://pop.mail.yahoo.cn
接收端口: 110或995(使用ssl时)
接收邮件服务器: http://imap.mail.yahoo.cn
接收端口: 143或993(使用ssl时)
发送邮件服务器: http://smtp.mail.yahoo.cn
发送端口: 25或465(使用ssl时)
HotMail :
接收邮件服务器: http://pop3.live.com
接收端口: 995
发送邮件服务器: http://smtp.live.com
发送端口: 25
263.net:
POP3服务器地址:http://pop3.263.net(端口:110)
SMTP服务器地址:http://smtp.263.net(端口:25)
263.net.cn:
POP3服务器地址:http://pop.263.net.cn(端口:110)
SMTP服务器地址:http://smtp.263.net.cn(端口:25)
x263.net:
POP3服务器地址:http://pop.x263.net(端口:110)
SMTP服务器地址:http://smtp.x263.net(端口:25)
21cn.com:
POP3服务器地址:http://pop.21cn.com(端口:110)
SMTP服务器地址:http://smtp.21cn.com(端口:25)
china.com:
POP3服务器地址:http://pop.china.com(端口:110)
SMTP服务器地址:http://smtp.china.com(端口:25)
tom.com:POP3服务器地址:http://pop.tom.com(端口:110)
SMTP服务器地址:http://smtp.tom.com(端口:25)
etang.com:POP3服务器地址:http://pop.etang.com
SMTP服务器地址:http://smtp.etang.com
2. smtp跳转加密端口
根据以上各服务器的端口号能看出,非加密端口都是25,加密端口有465,587,994等。
以smtp.qq.com为例,如果直接连465端口,需要进行ssl连接。
如果连接25端口,但需要加密连接,则可以发送STARTTLS跳转到加密端口。
C:telnet smtp.qq.com 25
S:220 newxmesmtplogicsvrszb1-0.qq.com XMail Esmtp QQ Mail Server.
C:HELO SMTP
S:250 OK
C:STARTTLS
S:220 Ready to start TLS from 180.108.251.243 to newxmesmtplogicsvrszb1-0.qq.com.
...
之后要发送数字签名等,没法手写,所以telnet只能到这一步
3.SSL编程基础
我们通常进行tcp连接后都会返回一个sockfd,在之后读写数据时通过sockfd即可向远端进行通信。ssl加密连接相当于在sock上套了一层加密解密协议。简单来说,我们将sockfd作为参数传入SSL_Connect函数后,之后会返回一个(SSL *)pConnId,作用与sockfd一样,读写时使用SSL_Read和SSL_Write即可。以下给出SSL_Connect代码:
VOID* SmtpSslConnect(int i4SockFd)
{
SSL_CTX *pSslCtx;
SSL *pSslConnId = NULL;
BIO *pSockBio;
X509 *X509_cert_peer;
const char *pu1Cafile = NULL; //这里不需要Cafile
SSL_library_init();
/* 初始化ssl ctx */
pSmtpSslCtx = SSL_CTX_new(SSLv23_client_method());
/* 选择版本,去掉SSLv2,SSLv3,TLSv1版本 */
SSL_CTX_set_options(pSmtpSslCtx,
SSL_OP_NO_SSLv2 |
SSL_OP_NO_SSLv3 |
SSL_OP_NO_TLSv1);
/* 配置数字签名等 */
SSL_CTX_set_mode(SslCtx, SSL_MODE_AUTO_RETRY);
if(SMTP_SSL_CERT_VERIFY) /* 该宏需要自定义,这里未定义可视为0 */
{
SSL_CTX_set_verify(SslCtx, SSL_VERIFY_PEER, NULL);
}
/*
* Set the path to the user-provided CA file or use the default cert paths
* if not provided.
*/
if(pu1Cafile)
{
if(SSL_CTX_load_verify_locations(SslCtx, NULL, NULL) != 1)
{
SSL_CTX_free(SslCtx);
return (NULL);
}
}
else
{
X509_STORE_set_default_paths(SSL_CTX_get_cert_store(SslCtx));
if(ERR_peek_error() != 0)
{
SSL_CTX_free(SslCtx);
return (NULL);
}
}
/* 创建BIO socket */
pSockBio = BIO_new_socket(i4SockFd, 0))
SSL_set_bio (pSslConnId, pSockBio);
SSL_set_connect_state(pSslConnId);
/* ssl connect */
SSL_connect(pSslConnId)
return (VOID *)pSslConnId;
}
V. c语言实现smtp客户端代码
注意:非可直接运行的代码,只有函数实现,仅提供思路。
1.smtp客户端
#define SMTP_SRV_READY_CODE "220"
#define SMTP_SRV_CLOSE_CODE "221"
#define SMTP_SRV_OK_CODE "250"
#define SMTP_SRV_START_MAIL "354"
#define SMTP_SRV_AUTH_CODE "334"
#define SMTP_SRV_AUTH_SUCCESS "235"
int SmtpSslReadResponse (void *pConnId, const char *pu1Code)
{
char au1RecvBuf[SMTP_RCV_BUF_LEN];
memset(au1RecvBuf, 0, SMTP_RCV_BUF_LEN);
if ((SSL_read(pConnId, (UINT1 *)au1RecvBuf, SMTP_RCV_BUF_LEN)) > 0)
{
if ((strstr (au1RecvBuf, pu1CheckCode)) != NULL)
{
return (SMTP_SUCCESS);
}
else
{
return (SMTP_FAILURE);
}
}
strcpy (au1ErrorBuf, "Connection Closed ");
return (SMTP_FAILURE);
}
int SmtpSslSendCmd (void *pConnId, int u4Len)
{
int i4BytesWritten;
if ((i4BytesWritten = SSL_write(pConnId, (const char *)au1CmdBuf, u4Len)) > 0)
{
return i4BytesWritten;
}
else
{
return SMTP_FAILURE;
}
}
void SmtpSendEmail(void)
{
int i4SockFd;
void *pConnId;
//TCP Connect to Server
MailServAddr.sin_addr.s_addr = OSIX_HTONL (gsSmtpAlertParams.u4MailServerIp);
MailServAddr.sin_family = AF_INET;
MailServAddr.sin_port = OSIX_HTONS (gsSmtpAlertParams.u4SMTPPort);
i4SockFd = (socket (AF_INET, SOCK_STREAM, IPPROTO_TCP));
connect (i4SockFd, (struct sockaddr *) &MailServAddr, sizeof (MailServAddr);
/* 如果不是25端口,就认为是加密端口 */
if (gsSmtpAlertParams.u4SMTPPort != 25)
{
pConnId = SmtpSslConnect(i4SockFd);
if (SmtpSslReadResponse(pConnId,SMTP_SRV_READY_CODE) != SMTP_SUCCESS)
{
/* 连接之后会收到220消息,如果不是说明连接发生错误 */
close (i4SockFd);
return ;
}
}
else /* 发生STARTTLS */
{
/* 这里还没有加密,使用read而不是ssl_read */
if (SmtpReadResponse (i4SockFd, (const UINT1 *)SMTP_SRV_READY_CODE) != SMTP_SUCCESS)
{
close (i4SockFd);
return ;
}
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((char *) au1CmdBuf, "STARTTLS\r\n");
SmtpSendCmd (i4SockFd, u4Len);
if (SmtpReadResponse (i4SockFd,
const char *)SMTP_SRV_READY_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return;
}
pConnId = SmtpSslConnect(i4SockFd);
}
/* HELO SMTP */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((CHR1 *) au1CmdBuf, "HELO SMTP\r\n");
SmtpSslSendCmd (pConnId, u4Len);
if (SmtpSslReadResponse(pConnId, SMTP_SRV_OK_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* AUTH LOGIN */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((char *) au1CmdBuf, "AUTH LOGIN\r\n");
SmtpSslSendCmd (pConnId, u4Len);
if (SmtpSslReadResponse(pConnId, SMTP_SRV_AUTH_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* Username(base64) */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
memset (au1BaseBuf,0, SMTP_DOMAIN_NAME_LEN);
strcpy(au1BaseBuf, gsSmtpAlertParams.au1SysDomainName);
b64_ntop(au1BaseBuf, strlen(au1BaseBuf), (char*)au1CmdBuf, SMTP_CMD_BUF_LEN);
strcat(au1CmdBuf,"\r\n");
u4Len = STRLEN(au1CmdBuf);
SmtpSslSendCmd (pConnId, u4Len);
if (SmtpSslReadResponse(pConnId, SMTP_SRV_AUTH_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* Key(base64) */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
memset (au1BaseBuf,0, SMTP_DOMAIN_NAME_LEN);
strcpy(au1BaseBuf, gsSmtpAlertParams.au1SysDomainNameKey);
b64_ntop(au1BaseBuf, strlen(au1BaseBuf), (char*)au1CmdBuf, SMTP_CMD_BUF_LEN);
strcat(au1CmdBuf,"\r\n");
u4Len = strlen(au1CmdBuf);
SmtpSslSendCmd (pConnId, u4Len);
if (SmtpSslReadResponse(pConnId, SMTP_SRV_AUTH_SUCCESS) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* MAIL FROM:<> */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((CHR1 *) au1CmdBuf, "MAIL FROM:<%s> \r\n",
gsSmtpAlertParams.au1SysDomainName);
SmtpSslSendCmd (pConnId, u4Len);
if (SmtpSslReadResponse(pConnId, SMTP_SRV_OK_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* RCPT TO:<> */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((char *) au1CmdBuf, "RCPT TO:<%s> \r\n",
gsSmtpAlertParams.au1RcvDomainName);
SmtpSslSendCmd (pConnId, u4Len);
if (SmtpSslReadResponse(pConnId, SMTP_SRV_OK_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* DATA */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((char *) au1CmdBuf, "DATA\r\n");
SysLogSmtpSslSendCmd (pConnId, u4Len);
if (SysLogSmtpSslReadResponse(pConnId, SMTP_SRV_START_MAIL) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
/* data从flash中读取 */
SmtpSslSendData(pConnId, NULL, SYSLOG_ZERO);
/* QUIT */
memset (au1CmdBuf, 0, SMTP_CMD_BUF_LEN);
u4Len = sprintf ((char *) au1CmdBuf, "QUIT\r\n");
SysLogSmtpSslSendCmd (pConnId, u4Len);
if (SysLogSmtpSslReadResponse(pConnId, SMTP_SRV_CLOSE_CODE) == SMTP_FAILURE)
{
close (i4SockFd);
return SMTP_FAILURE;
}
return;
}
2.正文及附件处理
#difine TEST_FILE "test.txt"
enum {
UUENC_SRC_BUF_SIZE = 15*3,
UUENC_DST_BUF_SIZE = 4 * (UUENC_SRC_BUF_SIZE + 2) / 3,
}
int SmtpSslSendData (void *pConnId, char *pu1Data, int u4DataLen)
{
int i4Len;
char au1Subject[100];
char au1SendBuf[MAX_FLASH_FILESIZE];
char au1Str[SMTP_DOMAIN_NAME_LEN + SMTP_DOMAIN_NAME_LEN + SYSLOG_FIFTY];
char au1SrcBuf[UUENC_SRC_BUF_SIZE];
char au1DstBuf[UUENC_DST_BUF_SIZE + 1];
int i4Filefd = 0;
int i4Size = 0;
int u4Pos = 0;
int au1DataTermStr[] = "\r\n.\r\n";
/* From:
* To: */
memset (au1Str, 0, sizeof (au1Str));
sprintf ((char *) au1Str, "From: %s\r\nTo: %s\r\n",
gsSmtpAlertParams.au1SysDomainName,
gsSmtpAlertParams.au1RcvDomainName);
if (SSL_write (pConnId, (const char *)au1Str, (int) strlen (au1Str), 0) <= 0)
{
return SMTP_FAILURE;
}
/* Subject */
memset (au1Subject, 0, sizeof (au1Subject));
sprinft ((char *) au1Subject, "Subject: Email Alert \r\n");
if (SSL_write (pConnId, (const char *)au1Subject, (int) strlen (au1Subject), 0) <= 0)
{
return SMTP_FAILURE;
}
/* Main text and annexes */
memset (au1SendBuf, 0, MAX_FLASH_FILESIZE);
u4Pos = sprintf((char *)au1SendBuf, "Syslog.\r\n");
if (u4DataLen == 0)
{
u4Pos += sprintf((char *)au1SendBuf + u4Pos, "begin 644 %s", TEST_FILE);
i4Filefd = fileopen(TEST_FILE, FILE_RO);
while (1)
{
i4Size = fileread(i4Filefd, (char *)au1SrcBuf, UUENC_SRC_BUF_SIZE);
if (!i4Size)
break;
if (i4Size < 0)
{
fileclose (i4Filefd);
return SMTP_FAILURE;
}
uuencode(au1DstBuf, (const char *)au1SrcBuf, i4Size);
/* \n */
au1SendBuf[u4Pos++] = '\n';
/* Character representation length in ASCII */
au1SendBuf[u4Pos++] = UUENCODE_BYTE(i4Size);
/* 60 characters per line */
u4Pos += SPRINTF((CHR1 *)au1SendBuf + u4Pos, "%s", au1DstBuf);
}
u4Pos += sprintf((char *)au1SendBuf + u4Pos, "\n`\nend\n");
}
else
{
u4Pos += sprintf((char *)au1SendBuf + u4Pos, "%s", pu1Data);
}
i4Len = strlen (au1SendBuf);
if (SSL_write (pConnId, (const char *)au1SendBuf, i4Len, 0) <= 0)
{
fileclose (i4Filefd);
return SMTP_FAILURE;
}
/* \r\n.\r\n */
i4Len = strlen (au1DataTermStr);
if (SSL_write (pConnId, (const char *)au1DataTermStr, i4Len, 0) <= 0)
{
file (i4Filefd);
return SMTP_FAILURE;
}
fileclose (i4Filefd);
return SMTP_SUCCESS;
}