www.pudn.com > doc2pdf-0_7_1.rar > doc2pdf_smtp.cpp


///////////////////////////////////////////////////////////////////////////// 
//  
// Project:		Doc2pdf 
// 
// File:		doc2pdf_smtp.cpp 
// 
// Author(s):	Matt Peterson  
// 
// Description:	SMTP email sender 
// 
///////////////////////////////////////////////////////////////////////////// 
 
#include "doc2pdf_smtp.h" 
#include "doc2pdf_log.h" 
 
#define DOC2PDF_SMTP_PORT		25 
#define DOC2PDF_SMTP_BUFSIZE	4096 
#define DOC2PDF_PART_BOUNDARY	"--DoC2PdFbOuNdArY" 
 
 
#ifndef CRLF  
#define CRLF "\r\n" 
#endif 
 
#define DOC2PDF_TOO_LARGE_SUBJECT  "DOC2PDF ERROR: Attachment too large. Can not be delivered" 
 
int Doc2pdfSmtpSender::AddressStringToList(const CString& str, CStringList& list) 
{ 
	int		start; 
	int		end; 
	CString listItem; 
	 
	list.RemoveAll(); 
 
	start = str.Find(':',0) + 1; 
	end = start; 
	if(str.GetLength() > start) 
	{ 
		while(end != 0 && end != -1) 
		{ 
			do 
			{ 
				end = str.Find(',',end); 
				if(end >= 0) 
				{ 
					listItem = str.Mid(start,end - start); 
				} 
				else 
				{ 
					listItem = str.Mid(start,str.GetLength() - start); 
					break; 
				} 
				end ++; 
			}while(listItem.Find('@') == -1); 
		 
			if(listItem.ReverseFind(' ') >= 0) 
			{ 
				listItem = listItem.Right(listItem.GetLength() - listItem.ReverseFind(' ') - 1); 
			} 
 
			if(listItem.Find('<') < 0) 
			{ 
				listItem.Insert(0,'<'); 
				listItem += ">"; 
			} 
			 
			if(listItem.Find('@') !=-1) 
			{ 
				listItem.MakeLower(); 
				list.AddTail(listItem); 
			} 
			else 
			{ 
				start = end; 
			} 
 
			start = end;			 
		} 
	} 
	 
	return 0; 
} 
 
 
// Do MAIL TO for each address and remove my address 
// Returns zero on success 
int Doc2pdfSmtpSender::SendMailTo(Doc2pdfIO* io, CString& addresses) 
{ 
	POSITION	pos; 
	CStringList	list; 
	CString		line; 
	CString		msg; 
 
	AddressStringToList(addresses,list); 
	addresses.Empty(); 
	pos = list.GetHeadPosition(); 
	while(pos) 
	{ 
		/* Don't let our address be replied do */ 
		/* Don't reply to bounced mail */ 
		if(list.GetAt(pos).Find(m_MyAddress) < 0 && 
		   list.GetAt(pos).Find("mailer-daemon") < 0)		    
		{ 
			line = "RCPT TO: "; 
			line += list.GetAt(pos); 
			if(io->WriteLine(line) == 0) 
			{ 
				/* Read the (hopefully 250 response) */ 
				io->ReadLine(line); 
				if(line.Left(3) != "250") 
				{ 
					msg.Format("SMTP ERROR: \"rcpt to:%s\" returned: %s",list.GetAt(pos),(LPCSTR)line); 
					theLog.Log(msg); 
				} 
				addresses += list.GetAt(pos); 
				addresses += ","; 
			}			 
		} 
		list.GetNext(pos); 
	} 
	addresses.TrimRight(','); 
 
	return 0; 
} 
 
// Send a multipart attachment 
// Returns zero on success 
int Doc2pdfSmtpSender::SendAttachment(Doc2pdfIO* io, Doc2pdfAttachment* attachment) 
{ 
	CString line; 
	CString filename; 
	CFile	file; 
	int		count; 
	void*	buf; 
 
 
	buf = malloc(DOC2PDF_SMTP_BUFSIZE); 
	if(buf == NULL) 
	{ 
		return -1; 
	} 
	 
	if(attachment->m_Converted) 
	{ 
		if(file.Open(attachment->m_Path,CFile::modeRead)) 
		{			 
			filename = attachment->m_Name.Left(attachment->m_Name .ReverseFind('.')); 
			filename += ".pdf";	 
			line = CRLF "--"DOC2PDF_PART_BOUNDARY CRLF; 
			line += "Content-Type: application/pdf; name=\""; 
			line += filename; 
			line += "\"" CRLF; 
			line += "Content-Transfer-Encoding: base64" CRLF; 
			line += "Content-Disposition: attachment; filename=\""; 
			line += filename; 
			line += "\"" CRLF; 
			if(io->WriteLine(line)) 
			{ 
				/* Problems passing sending */ 
				goto END;							 
			} 
			while((count = file.Read(buf,DOC2PDF_SMTP_BUFSIZE)) > 0) 
			{ 
				if(io->Write(buf,count)) 
				{ 
					break; 
				} 
			} 
 
			file.Close();			 
		} 
 
	} 
 
END: 
	free(buf); 
 
	return 0; 
} 
 
int Doc2pdfSmtpSender::SendEmail(Doc2pdfIO* io, Doc2pdfEmail* email) 
{ 
	CString				line; 
	CString				msg; 
	POSITION			pos; 
 
	 
	/*-----------*/ 
	/* Mail From */ 
	/*-----------*/ 
	line.Format("MAIL FROM: %s",m_MyAddress); 
	if(io->WriteLine(line)) 
	{ 
		/* Problems doing MailFrom */ 
		goto RESET; 
	} 
	io->ReadLine(line); 
	if(line.Left(3) != "250") 
	{ 
		/* Problems doing Mail From */ 
		msg.Format("SMTP ERROR: \"mail from:\"%s returned: %s",m_MyAddress,(LPCSTR)line); 
		theLog.Log(msg); 
		goto RESET; 
	} 
 
	/*----------------------------------------*/ 
	/* MAIL TO: for From or Reply-to recipients */ 
	/*----------------------------------------*/ 
	if(email->m_ReplyTo.GetLength() == 0) 
	{ 
		SendMailTo(io, email->m_From); 
	} 
	else 
	{ 
		SendMailTo(io, email->m_ReplyTo); 
	} 
 
	if(email->m_Attachments.GetCount()) 
	{ 
		/*----------------------------*/ 
		/* MAIL TO: for To recipients */ 
		/*----------------------------*/ 
		SendMailTo(io,email->m_To); 
 
		/*----------------------------*/ 
		/* MAIL TO: for To recipients */ 
		/*----------------------------*/ 
		SendMailTo(io,email->m_Cc); 
	}	 
	 
	/* Don't continue if there are no recipients */ 
	if(email->m_From.GetLength() == 0 && 
	   email->m_To.GetLength() == 0 && 
	   email->m_Cc.GetLength() == 0) 
	{ 
		goto RESET; 
	} 
 
	/*------*/ 
	/* DATA */ 
	/*------*/ 
	line = "DATA"; 
	if(io->WriteLine(line)) 
	{ 
		/* Problems passing DATA */ 
		goto RESET; 
	} 
	io->ReadLine(line); 
	if(line.Left(3) != "354") 
	{ 
		/* Problems with DATA */ 
		line.Insert(0,"SMTP ERROR: writing envelope. MTA returned: "); 
		theLog.Log(line); 
		goto RESET; 
	} 
	line = "From: "; 
	line += m_MyAddress; 
	line += CRLF; 
	line += "To: "; 
	line += email->m_From; 
	line += CRLF; 
	line += "Cc: "; 
	line += email->m_Cc; 
	line += CRLF; 
	line += "Subject: "; 
	line += "Converted: "; 
	if(email->m_Subject.GetLength() > 8) 
	{ 
		email->m_Subject.Delete(0,8); // we don't want 2 "Subject:" 
	} 
	line += email->m_Subject; 
	line += CRLF; 
	line += "MIME-Version: 1.0" CRLF; 
	line += "Content-Type: Multipart/Mixed; boundary=\""; 
	line +=  DOC2PDF_PART_BOUNDARY "\"" CRLF CRLF; 
	line += "This is a multipart MIME message" CRLF CRLF; 
	line += "--" DOC2PDF_PART_BOUNDARY CRLF; 
	line += "Content-Type: text/plain; charset=US-ASCII"; 
	line += CRLF CRLF; 
	line += email->m_Body; 
	if(io->WriteLine(line)) 
	{ 
		/* Problems with body */ 
		goto RESET; 
	} 
	 
	/*-------------*/ 
	/* ATTACHMENTS */ 
	/*-------------*/ 
	pos = email->m_Attachments.GetHeadPosition(); 
	while(pos) 
	{ 
		SendAttachment(io, email->m_Attachments.GetAt(pos)); 
		email->m_Attachments.GetNext(pos); 
	} 
 
	/* Last Boundary and . terminator */ 
	line = CRLF "--" DOC2PDF_PART_BOUNDARY "--" CRLF CRLF; 
	line += CRLF "."; 
	if(io->WriteLine(line)) 
	{ 
		/* Problems writing last boundary */ 
		goto RESET;				 
	} 
 
	io->ReadLine(line); 
	if(line.Left(3) != "250") 
	{ 
		/* Not a terminate data */ 
		msg=line; 
		msg.Insert(0,"SMTP ERROR: terminating message. MTA returned: "); 
		theLog.Log(msg); 
 
#ifdef DEBUG 
		/* Send back an informative little reply on message to large */ 
		if(line.Left(3) == "552") 
		{ 
			Doc2pdfEmail toolarge; 
			toolarge.m_Body = email->m_Body; 
			toolarge.m_From = email->m_From; 
			toolarge.m_ReplyTo = email->m_ReplyTo; 
			toolarge.m_Subject = DOC2PDF_TOO_LARGE_SUBJECT; 
			SendEmail(io,&toolarge);			 
		} 
#endif 
 
	}		 
 
	/* SUCCESS */ 
 
	return 0; 
 
RESET: 
 
	io->WriteLine("RSET"); 
	io->ReadLine(line); 
 
	return 0; 
} 
 
// Initialize this object 
int Doc2pdfSmtpSender::Init(const CString& smtphost, const CString myaddress) 
{ 
	m_SmtpHost = smtphost; 
	m_MyAddress = myaddress; 
 
	return 0; 
} 
 
// Returns number of emails sent 
int Doc2pdfSmtpSender::SendAllEmail(const Doc2pdfEmailList& emaillist) 
{ 
	Doc2pdfSocket		sock; 
	Doc2pdfIO*			io; 
	Doc2pdfEmail*		email; 
	Doc2pdfEmail		eemail; 
	POSITION			pos; 
	CString				line; 
	CString				msg; 
	int					result = 0; 
 
	/*------------------------*/ 
	/* Connect to Smtp server */ 
	/*------------------------*/ 
	// Connect to the Pop3 host 
	if(sock.Connect(m_SmtpHost,DOC2PDF_SMTP_PORT)) 
	{ 
		// Could not connect 
 
		// TODO: Log the fact that we could not connect 
		return -1; 
	} 
	io = (Doc2pdfIO*)&sock; 
 
	/*-----------------------------*/ 
	/* Read Greeting and say Hello */ 
	/*-----------------------------*/ 
	io->ReadLine(line); 
	if(line.Left(1) != "2") 
	{ 
		/* Not a SMTP server */ 
		theLog.Log("SMTP ERROR: Not an SMTP server. Check configuration"); 
		result = -1; 
		goto END; 
	}	 
	line = "HELO there"; 
	if(io->WriteLine(line)) 
	{ 
		/* Write Error */		 
		result = -1; 
		goto END; 
	} 
	io->ReadLine(line); 
	if(line.Left(3) != "250") 
	{ 
		/* Not a SMTP server */ 
		line.Insert(0,"SMTP ERROR: \"hello\" returned: "); 
		theLog.Log(line); 
		result = -1; 
		goto END; 
	} 
	 
	pos = emaillist.GetHeadPosition(); 
	while(pos) 
	{ 
		email = emaillist.GetAt(pos); 
		if(SendEmail(io,email) == 0) 
		{ 
			result ++; 
		}				 
 
		emaillist.GetNext(pos); 
	} 
 
END: 
	 
	/*-------------------*/ 
	/* Free up resources */ 
	/*-------------------*/ 
	sock.Close(); 
 
	return result; 
}