https://github.com/dinhviethoa/libetpan/blob/master/tests/smtpsend.c
linux下c发送邮件socket验证问题
下面是一个linux下c写的发送邮件的程序。我想在SendMail函数中加一些判断。就是与smtp服务器数据交换的每一步加一个验证。比如认证失败了。然后就停止发送邮件。返回一个错误的代号。现在是失败了函数也一直执行。返回结果都是0。不知道是否成功失败。只有看调试信息。我是一个新手。请高手帮忙。先谢了。
[code]
#include "smtp.h"
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#else
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#endif
int sock_connect(const char *pHostName, unsigned short nPort)
{
int nSock;
struct hostent *host;
struct sockaddr_in client_addr;
if ((host = gethostbyname(pHostName)) == NULL)
{
#ifdef _DEBUG
printf("sock_connect gethostbyname() error!\r\n");
#endif
return 0;
}
if ((nSock = (int) socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
#ifdef _DEBUG
printf("sock_connect socket() error!\r\n");
#endif
return 0;
}
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(nPort);
client_addr.sin_addr = * ((struct in_addr *) host->h_addr);
memset(&(client_addr.sin_zero), 0, 8) ;
if (connect(nSock, (struct sockaddr *) &client_addr, sizeof(struct sockaddr)) == -1)
{
#ifdef _DEBUG
printf("sock_connect connect() error!\r\n");
#endif
return 0;
}
return (nSock);
}
int sock_close(int nSock)
{
#ifdef WIN32
return closesocket(nSock);
#else
return close(nSock);
#endif
}
int sock_send(int nSock, char *pFormat, ...)
{
char szBuffer[1024];
va_list argptr;
va_start(argptr, pFormat);
vsnprintf(szBuffer, sizeof(szBuffer), pFormat, argptr);
va_end(argptr);
#ifdef _DEBUG
printf("%s\r\n",szBuffer);
#endif
return send(nSock, szBuffer, (int) strlen(szBuffer), 0) ;
}
int sock_read(int nSock, const char *pStop)
{
int iResult = 0;
const int nSize = 256;
char szBuf[256 + 1];
while ((iResult = recv(nSock, szBuf, nSize, 0)) > 0)
{
szBuf[iResult] = '\0';
#ifdef _DEBUG
printf("%s\r\n",szBuf);
#endif
if ((pStop) && (strstr(szBuf, pStop) != NULL))
{
break;
}
}
return iResult;
}
int SendMail(const char *pHostName, unsigned short nPort, SMTP_MAIL *pMail)
{
int nSock;
char szBase64UserName[256];
char szBase64Password[256];
sock_start();
nSock = sock_connect(pHostName, nPort);
if (nSock)
{
sock_read(nSock, "220");
sock_send(nSock, "HELO host_name\r\n");
sock_read(nSock, "250");
sock_send(nSock, "EHLO\r\n");
sock_read(nSock, "250");
sock_send(nSock, "AUTH LOGIN\r\n") ;
sock_read(nSock, "334");
Base64Enc(szBase64UserName, pMail->stHeader.szUserName) ;
sock_send(nSock, "%s\r\n", szBase64UserName);
Base64Enc(szBase64Password, pMail->stHeader.szPassword) ;
sock_send(nSock, "%s\r\n", szBase64Password);
sock_read(nSock, "235");
sock_send(nSock, "MAIL FROM: <%s> \r\n", pMail->stHeader.szMailFrom);
sock_read(nSock, "250") ;
sock_send(nSock, "RCPT TO: <%s> \r\n", pMail->stHeader.szMailTo);
sock_read(nSock, "250") ;
sock_send(nSock,"DATA\r\n") ;
sock_read(nSock,"354") ;
sock_send(nSock, "From:%s\r\nTo: %s \r\n", pMail->stHeader.szMailFrom, pMail->stHeader.szMailTo);
sock_send(nSock, "Subject: %s \r\n", pMail->szSubject);
sock_send(nSock, "Content-type: %s;charset=%s\r\n", pMail->szContentType, pMail->szCharSet);
sock_send(nSock, "\r\n%s\r\n", pMail->szMailBody);
sock_send(nSock,"\r\n.\r\n") ; /*end data */
sock_read(nSock,"250") ;
sock_send(nSock, "QUIT\r\n") ;
sock_read(nSock, "221");
sock_close(nSock);
}
sock_end();
return 0;
}
[/code]
[[i] 本帖最后由 m_lm 于 2007-3-23 13:06 编辑 [/i]] sock_read(nSock, "250");
在这个sock_read里处理
如果read的相应不是250就表示出错,其他类似
回复 2楼 dajun 的帖子
dajun谢了。这么简单,我怎么没想到:)。 一位楼主可以提供一个完整发邮件代码吗?我参考很多网站的代码都不成功,不知道可否分享大客代码供像我这样的菜的小C初学者做参考学习用?发现大客的不但在linux下能用好像在windows下也可以用?是C还是C++代码? SMTP 协议要求每条指令的 TCP 包带 push flag。 typedef struct {char szUserName[256]="";
char szPassword[256]="";
char szMailFrom[256]="";
char szMailTo[256]="";
char szSubject[256]="";
char szContentType[256]="";
char szContentType[256]="";
char szCharSet[256]="";
char szMailBody[256]="";
}stHeader;
楼主的数据大至结构是这样吗?
SMTP_MAIL *pMail
^^^^^^^这个是什么?是用define声明?其它大客们有否类似的stmp发送邮件的代码!
我在网上只找到一个:
[url]http://blog.linuxpk.com/8571/viewspace-890[/url]
163/126/tom等没有一个通得过! 呵呵,想要练习收发邮件,强烈建议先从 sohu 的开始,sohu 的邮箱真好啊。
感谢 sohu! 1.HELO/EHLO部分处理的不对
2。对于扩展的ESMTP command,比如AUTH需要验证SMTP Server是否支持该命令。SERVER 支持的ESMTP commands在EHLO命令的返回星系里面可以读到。