www.pudn.com > FindMail.zip > smtp.cpp


/* smtp.c
*  by lgd/Paladin.InetSoft   GuangZhou
*  
*/
#include "stdafx.h"
#include 
#include 
#include 
#include  

#include "tcp.h"
#include "smtp.h"

char m_base64tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
				"abcdefghijklmnopqrstuvwxyz0123456789+/";
#define BASE64_MAXLINE  76
#define EOL  "\r\n"

int Base64BufferSize(int);
int EncodeBase64(const char* pszIn, int nInLen, char* pszOut, int nOutSize, int* nOutLen);
int get_filename(char *path, char *filename);
 
#define REPLY_SIZE	4096 

int smtp_connect(char *host, int port, int timeout)
{
	int sd, ret =0; 
	char reply[REPLY_SIZE+1]; 
 
	if(port <=0) port =25;
	if((sd =tcp_connect(host, port, timeout, false)) <0)
		return -1;
	if(smtp_getreply(sd, reply) !=220)
	{
		tcp_close(sd);
		return -10;
	}
	if((ret =smtp_cmd(sd, "HELO iampaladin\r\n", 250)) <0) 
	{ 
		tcp_close(sd); 
		return ret; 
	} 
 
	return sd;
}

char *Weeks[] ={"Mon", "002", "003", "004", "005", "006", "Sun"};
char *Months[] ={"m01", "m02", "m03", "m04", "m05", "m06", "m07", "m08", "m09", "m10", "m11", "m12"};
 
int smtp_sendfile(int sd, char *AddrFrom, char *AddrTo, char *filename) 
{ 
	FILE *fp; 
	char buf[1024]; 
	int len; 
	int ret =0; 
 
	if((fp =fopen(filename, "r")) ==NULL) return -1; 
	while(!feof(fp) && (len =fread(buf, 1, sizeof(buf)-1, fp)) >0) 
	{ 
		buf[len] =0; 
		if(smtp_sendmessage(sd, AddrFrom, &AddrTo, 1, NULL, "pass", buf, 
			NULL, 0, 60) <0) 
		{ 
			ret =-1; 
			break; 
		} 
	} 
	fclose(fp); 
	return ret; 
} 

int smtp_sendmsg(int sd, char *from, char *to, char *subject, char *msg, int timeout) 
{ 
	return smtp_sendmessage(sd, from, &to, 1, NULL, subject, msg, 
			NULL, 0, timeout); 
} 
 
int smtp_test_to(int sd, char *to) 
{ 
	char cmd[100]; 
	int ret; 
 
	sprintf(cmd, "RCPT TO:<%s>\r\n", to); 
	if((ret =smtp_cmd(sd, cmd, 250)) <0) 
		return ret; 
	return 0; 
} 
 
int smtp_test_from(int sd, char *from) 
{ 
	char cmd[100]; 
	int ret; 
 
	sprintf(cmd, "MAIL FROM:<%s>\r\n", from); 
	if((ret =smtp_cmd(sd, cmd, 250)) <0) 
		return ret; 
 
	return 0; 
} 
 
int smtp_sendmessage(int sd, char *AddrFrom, char **AddrTo, int AddrToCount,
		char *AddrReply, char *subject, char *msg, char **AttachFiles,
		int AttachCount, int timeout)
{
	int i, ret =0, outsize, bufsize, flen;
	char buf[5000];
	char szTo[2000];
	char szDate[50];
	char *fbuf, *pbuf =NULL;
	FILE *fp;
	time_t t;
	struct tm *ptm;
	char filename[128];

	sprintf(buf, "MAIL FROM:<%s>\r\n", AddrFrom);
	if((ret =smtp_cmd(sd, buf, 250)) <0)
		return ret;
	for(i =0; i\r\n", AddrTo[i]);
		if((ret =smtp_cmd(sd, buf, 250)) <0)
			return ret;
	}
	if((ret =smtp_cmd(sd, "DATA\r\n", 354)) <0)
		return ret;
	/* fill header */
	szTo[0] =0;
	for(i =0; itm_wday], ptm->tm_mday, Months[ptm->tm_mon],
		ptm->tm_year, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, _tzname[0]);
	sprintf(buf, "From: %s\r\nTo: %s\r\nSubject:%s\r\nDate: %s\r\nX-Mailer: Paladin.InetSoft\r\n",
			AddrFrom, szTo, subject, szDate);
	if(AddrReply)
	{
		strcat(buf, "Reply-To: ");
		strcat(buf, AddrReply);
		strcat(buf, "\r\n");
	}
	if(AttachCount)
	{
		strcat(buf, "MIME-Version: 1.0\r\nContent-type: multipart/mixed; boundary=\"#BOUNDARY#\"\r\n");
	}
	strcat(buf, "\r\n");
	/* end of header */

	if(tcp_send(sd, buf, strlen(buf), 20) <0)
		return -2;
	if(AttachCount)
	{
		strcpy(buf, "\r\n--#BOUNDARY#\r\nContent-Type: text/plain; charset=us-ascii\r\n"
			"Content-Transfer-Encoding: quoted-printable\r\n\r\n");
		if(tcp_send(sd, buf, strlen(buf), 10) <0)
			return -2;
	}
	if(tcp_send(sd, msg, strlen(msg), 60) <0)
		return -2;
	/* sending attachment */
	for (i=0; iMAX_WAIT_TIMES) break;

		len =tcp_recv(sd, reply, REPLY_SIZE-len_recved, 2);
		if (len ==SOCKET_ERROR)
		{
			reply[len_recved] = 0;
			return 1; 
		}
		else
		{
			if(len)	time(&t1);
			len_recved += len;
		}

		reply[len_recved] =0;
		if(strstr(reply, "\r\n") != NULL) break;
	}
	reply[len_recved] =0;

	if(sscanf(reply, "%d", &code) !=1)
		return 1;
	return code;
}

int Base64BufferSize(int fsize)
{
  int bufsize = (fsize+2)/3*4;    // 3:4 conversion ratio

  bufsize += strlen(EOL)*bufsize/BASE64_MAXLINE + 3;  // Space for newlines and NUL
  return bufsize;
}

BOOL EncodeBase64(const char* pszIn, int nInLen, char* pszOut, int nOutSize, int* nOutLen)
{
	int nInPos  = 0;
	int nOutPos = 0;
	int nLineLen = 0;
	int i, c1, c2;
	char *cp;

	// Get three characters at a time from the input buffer and encode them
	for (i=0; i> 2];
		pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)];
		pszOut[nOutPos++] = m_base64tab[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)];
		pszOut[nOutPos++] = m_base64tab[c3 & 0x3F];
		nLineLen += 4;

		//Handle the case where we have gone over the max line boundary
		if (nLineLen >= BASE64_MAXLINE-3) 
		{
			cp = EOL;
			pszOut[nOutPos++] = *cp++;
			if (*cp) 
			pszOut[nOutPos++] = *cp;
			nLineLen = 0;
		}
	}

	// Encode the remaining one or two characters in the input buffer
	switch (nInLen % 3) 
	{
	case 0:
	{
		cp = EOL;
		pszOut[nOutPos++] = *cp++;
		if (*cp) 
			pszOut[nOutPos++] = *cp;
		break;
	}
	case 1:
	{
		c1 = pszIn[nInPos] & 0xFF;
		pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
		pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4)];
		pszOut[nOutPos++] = '=';
		pszOut[nOutPos++] = '=';
		cp = EOL;
		pszOut[nOutPos++] = *cp++;
		if (*cp) 
			pszOut[nOutPos++] = *cp;
		break;
	}
	case 2:
	{
		c1 = pszIn[nInPos++] & 0xFF;
		c2 = pszIn[nInPos] & 0xFF;
		pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
		pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)];
		pszOut[nOutPos++] = m_base64tab[((c2 & 0x0F) << 2)];
		pszOut[nOutPos++] = '=';
		cp = EOL;
		pszOut[nOutPos++] = *cp++;
		if (*cp) 
			pszOut[nOutPos++] = *cp;
		break;
	}
	default: 
		break;
	}
	pszOut[nOutPos] = 0;
	*nOutLen = nOutPos;
	return TRUE;
}

int get_filename(char *path, char *filename)
{
	int i =0;
	int len =strlen(path);

	while(i