#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "smtpclient.h"
#if defined(_WIN32) || defined(__WIN32__)
#include <stddef.h>
#include <winsock2.h>
#include <io.h>
#include <wchar.h>
#include <memory.h>
#include <time.h>
#define socketerrno WSAGetLastError()
#define ETIMEDOUT WSAETIMEDOUT
#define EWOULDBLOCK WSAEWOULDBLOCK
#define ERRINTR WSAEINTR
#define EINPROGRESS WSAEINPROGRESS
#define STDCALL __stdcall
#define HANDLEFILE_MODE (_O_RDWR|_O_CREAT|_O_APPEND)
#define FILE_MODE (_S_IREAD|_S_IWRITE)
typedef int ssize_t;
typedef unsigned int size_t;
#define snprintf _snprintf
#define close _close
#define bzero(ptr, size) memset(ptr, 0, size)
#define vsnprintf _vsnprintf
#define strncasecmp strnicmp
#define sleep Sleep
#define socklen_t int
#define LISTENQ SOMAXCONN
#else //UNIX
#include <signal.h>
#include <inttypes.h>
#include <strings.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
//#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <syslog.h>
#include <sys/utsname.h>
#include <pthread.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#define SOCKET int
#define socketerrno (errno)
#define ERRINTR EINTR
#define INVALID_SOCKET (-1)
#define INADDR_NONE ((in_addr_t) 0xffffffff)
#define STDCALL
#define LISTENQ (1024)
#define HANDLEFILE_MODE (O_RDWR)
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH)
#endif
#define CONNECT_DELAY_TIME (30)
#define SOCKET_READ_TIMEOUT CONNECT_DELAY_TIME
#define LINE_LEN (1024)
#define LONGLINE_LEN (4096)
#define SHORTLINE_LEN (256)
#define MAXLINE (8192)
#define MAXINT (int)(2147483647)
/////////////////////////////////////////////////////////////////////
//
// 下面是一些用于SMTP发信的宏定义
//
/////////////////////////////////////////////////////////////////////
#ifdef DEBUG
#define SMTP_DEBUG(a) a
#else
#define SMTP_DEBUG(a) /*a*/
#endif
#define SMTP_DOT (".")
#define SMTP_CRLF ("\r\n")
#define SMTP_CR ("\r")
#define SMTP_LF ("\n")
#define SMTP_CMD_EHLO ("EHLO ")
#define SMTP_CMD_HELO ("HELO ")
#define SMTP_CMD_AUTH_LOGIN ("AUTH LOGIN ")
#define SMTP_CMD_MAIL_FROM ("MAIL FROM: ")
#define SMTP_CMD_RCPT_TO ("RCPT TO: ")
#define SMTP_CMD_DATA ("DATA")
#define SMTP_CMD_HELP ("HELP")
#define SMTP_CMD_RSET ("RSET")
#define SMTP_CMD_NOOP ("NOOP")
#define SMTP_CMD_QUIT ("QUIT")
#define SMTP_END_OF_MAIL ("\r\n.\r\n")
#define SMTP_RCV_END SMTP_CRLF
#define SMTP_RCV_ESMTP ("ESMTP")
#define SMTP_RCV_SMTP ("SMTP")
#define SMTP_RCV_SERVOK ("220") // 220 服务就绪
#define SMTP_RCV_HELO ("250") // 250 要求的邮件操作完成
#define SMTP_RCV_AUTH_LOGIN ("334")
#define SMTP_RCV_AUTH_USER ("334")
#define SMTP_RCV_AUTH_PASSWD ("334")
#define SMTP_RCV_AUTH_OK ("235")
#define SMTP_RCV_MAIL_FROM ("250")
#define SMTP_RCV_RCPT_TO ("250")
#define SMTP_RCV_DATA ("354")
#define SMTP_RCV_SEND_END ("250")
#define SMTP_RCV_RSET ("250")
#define SMTP_RCV_NOOP ("250")
#define SMTP_RCV_QUIT ("221") // 221 服务关闭传输信道
#define SMTP_SEND_BLOCK_SIZE (1024) // 每次发送信件内容的块的大小
// 定义SMTP发信客户端结构
//struct SMTP_S {
// SOCKET sockfd; //SOCKET连接句柄
// char smtphost[128]; //SMTP服务器域名或IP地址
// int smtpport; //SMTP服务器PORT
// char user[128]; //发信认证用户名
// char passwd[64]; //发信认证用户密码
// char sender[128]; //发信人EMAIL
// char to[128]; //收信人EMAIL
// char *cc; //其他收件人和抄送者EMAIL地址列表,以回车换行分隔
// int ccsize; //存储地址列表空间的大小,不是地址列表的长度
// char *body; //信件内容空间指针,内容是字符串形式
// int bodysize; //存储信件内容的大小,不是信件内容的长度
// int sentsize; //已发送的数据大小
// int sentlines; //已发送的行数
// int recvsize; //已接收的数据大小
// int recvlines; //已接收的行数
// int errcode; //处理结果,错误号
// char errinfo[1024]; //处理结果信息
// char smtpcmd[32]; //发送的SMTP协议命令
// char smtprcv[32]; //收取的SMTP协议结果
//};
//typedef struct SMTP_S SMTP; //SMTP结构定义
/////////////////////////////////////////////////////////////////////
//
// 下面是一些基于TCP/IP的SOCKET通讯公用函数,适用于WIN32和UNIX
//
/////////////////////////////////////////////////////////////////////
// set non-blocking I/O
static int set_ndelay_on(int fd)
{
#if defined(_WIN32) || defined(__WIN32__)
u_long flag = 1;
return ioctlsocket(fd, FIONBIO, &flag);
#else
return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL,0) | O_NDELAY);
#endif
}
// set blocking I/O
static int set_ndelay_off(int fd)
{
#if defined(_WIN32) || defined(__WIN32__)
u_long flag = 0;
return ioctlsocket(fd, FIONBIO, &flag);
#else
return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL,0) & ~O_NDELAY);
#endif
}
static int GetSocketAsyncError(int s)
{
int error = 0;
#if defined(_WIN32) || defined(__WIN32__) || defined(OSF)
int error_len = 0;
#else
#if defined (HPUX)
int error_len = 0;
#else
socklen_t error_len = 0;
#endif
#endif
error_len = sizeof(error);
if( getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &error, &error_len) == -1 )
return -1;
return error;
}
static int SocketTimedCheck(int fd)
{
/* bring from postfix.... */
fd_set action_fds;
fd_set except_fds;
struct timeval tv;
struct timeval *tp;
int res;
#if !( defined(_WIN32) || defined(__WIN32__) )
if ( FD_SETSIZE <= fd ) //It's not true for Win32 Platform.
return -1 ;
#endif
FD_ZERO( &action_fds );
FD_SET( (unsigned int)fd, &action_fds );
FD_ZERO( &except_fds );
FD_SET( (unsigned int)fd, &except_fds );
if( CONNECT_DELAY_TIME > 0 )
{
tv.tv_usec = 0;
tv.tv_sec = CONNECT_DELAY_TIME;
tp = &tv;
}
else
tp = NULL;
for(;;)
{
res = select( fd + 1, NULL, &action_fds , &except_fds, tp);
switch ( res )
{
case -1:
if( socketerrno != ERRINTR ) return -1;
continue;
case 0:
#if defined(_WIN32) || defined(__WIN32__)
WSASetLastError( ETIMEDOUT );
#else
errno = ETIMEDOUT;
#endif
return -2;
default:
if( FD_ISSET(fd, &except_fds) )
return -3;
return 0;
}
}
return -4;
}
static SOCKET Connect(const char * szHost, unsigned short uPort)
{
int error = 0;