Hi,
I provide here for you two classes that are working :
//---MailMessage.h
#if !defined(_MAILMESSAGE_H_)
#define _MAILMESSAGE_H_
#include <afxtempl.h>
class CMailMessage
{
public:
CMailMessage();
virtual ~CMailMessage();
int GetNumRecipients();
BOOL GetRecipient( CString& sEmailAddress, CString& sFriendlyName, int nIndex = 0 );
BOOL AddRecipient( LPCTSTR szEmailAddress, LPCTSTR szFriendlyName = "" );
BOOL AddMultipleRecipients( LPCTSTR szRecipients = NULL );
CString m_sFrom;
CString m_sSubject;
CString m_sHeader;
CTime m_tDateTime;
CString m_sBody;
private:
class CRecipient
{
public:
CString m_sEmailAddress;
CString m_sFriendlyName;
};
CArray <CRecipient, CRecipient&> m_Recipients;
};
#endif
// ---MailMessage.cpp
// MailMessage.cpp: implementation of the CMailMessage class.
//////////////////////////////////////////////////////////////////////
//#include "stdafx.h" -obislavu- uncomment it if you use MFC precompiled headers
#include "MailMessage.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMailMessage::CMailMessage()
{
}
CMailMessage::~CMailMessage()
{
}
BOOL CMailMessage::AddRecipient( LPCTSTR szEmailAddress, LPCTSTR szFriendlyName)
{
ASSERT( szEmailAddress != NULL );
ASSERT( szFriendlyName != NULL );
CRecipient to;
to.m_sEmailAddress = szEmailAddress;
to.m_sFriendlyName = szFriendlyName;
m_Recipients.Add( to );
return TRUE;
}
// sEmailAddress and sFriendlyName are OUTPUT parameters.
// If the function fails, it will return FALSE, and the OUTPUT
// parameters will not be touched.
BOOL CMailMessage::GetRecipient(CString & sEmailAddress, CString & sFriendlyName, int nIndex)
{
CRecipient to;
if( nIndex < 0 || nIndex > m_Recipients.GetUpperBound() )
return FALSE;
to = m_Recipients[ nIndex ];
sEmailAddress = to.m_sEmailAddress;
sFriendlyName = to.m_sFriendlyName;
return TRUE;
}
int CMailMessage::GetNumRecipients()
{
return m_Recipients.GetSize();
}
BOOL CMailMessage::AddMultipleRecipients(LPCTSTR szRecipients )
{
TCHAR* buf;
UINT pos;
UINT start;
CString sTemp;
CString sEmail;
CString sFriendly;
UINT length;
int nMark;
int nMark2;
ASSERT( szRecipients != NULL );
// Add Recipients
//
length = strlen( szRecipients );
buf = new TCHAR[ length + 1 ]; // Allocate a work area (don't touch parameter itself)
strcpy( buf, szRecipients );
for( pos = 0, start = 0; pos <= length; pos++ )
{
if( buf[ pos ] == ';' ||
buf[ pos ] == 0 )
{
// First, pick apart the sub-strings (separated by ';')
// Store it in sTemp.
//
buf[ pos ] = 0; // Redundant when at the end of string, but who cares.
sTemp = &buf[ start ];
// Now divide the substring into friendly names and e-mail addresses.
//
nMark = sTemp.Find( '<' );
if( nMark >= 0 )
{
sFriendly = sTemp.Left( nMark );
nMark2 = sTemp.Find( '>' );
if( nMark2 < nMark )
{
delete[] buf;
return FALSE;
}
// End of mark at closing bracket or end of string
nMark2 > -1 ? nMark2 = nMark2 : nMark2 = sTemp.GetLength() - 1;
sEmail = sTemp.Mid( nMark + 1, nMark2 - (nMark + 1) );
}
else
{
sEmail = sTemp;
sFriendly = "";
}
AddRecipient( sEmail, sFriendly );
start = pos + 1;
}
}
delete[] buf;
return TRUE;
}
// -----------------SMTP.h-----------------
// SMTP.h: interface for the CSMTP class.
// use the SMTP Protocol
// 1999-12-01 -obislavu-
// Note: Please keep this note!!!!
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SMTP_H__55DE48CB_BEA4_11D1_870E_444553540000__INCLUDED_)
#define AFX_SMTP_H__55DE48CB_BEA4_11D1_870E_444553540000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include <afxsock.h>
#include "MailMessage.h"
#define SMTP_PORT 25 // Standard port for SMTP servers
#define RESPONSE_BUFFER_SIZE 1024
// CSMTP Encapsulate SMTP protocol
class CSMTP
{
public:
CSMTP( LPCTSTR szSMTPServerName, UINT nPort = SMTP_PORT );
virtual ~CSMTP();
void SetServerProperties( LPCTSTR sServerHostName, UINT nPort = SMTP_PORT );
CString GetLastError();
CString GetMailerName();
UINT GetPort();
BOOL Disconnect();
BOOL Connect();
virtual BOOL FormatMailMessage( CMailMessage* msg );
BOOL SendMessage( CMailMessage* msg );
CString GetServerHostName();
private:
BOOL get_response( UINT response_expected );
BOOL transmit_message( CMailMessage* msg );
CString prepare_body( CMailMessage* msg );
BOOL prepare_header( CMailMessage* msg);
CString m_sError;
BOOL m_bConnected;
UINT m_nPort;
CString m_sMailerName;
CString m_sSMTPServerHostName;
CSocket m_wsSMTPServer;
protected:
//
// Helper Code
//
struct response_code
{
UINT nResponse; // Response we're looking for
TCHAR* sMessage; // Error message if we don't get it
};
enum eResponse
{
GENERIC_SUCCESS = 0,
CONNECT_SUCCESS,
DATA_SUCCESS,
QUIT_SUCCESS,
// Include any others here
LAST_RESPONSE // Do not add entries past this one
};
TCHAR response_buf[ RESPONSE_BUFFER_SIZE ];
static response_code response_table[];
};
#endif // !defined(AFX_SMTP_H__55DE48CB_BEA4_11D1_870E_444553540000__INCLUDED_)
// --------------------------SMTP.CPP ---
// SMTP.cpp: implementation of the CSMTP class.
// 1999-12-01 -obislavu--
//////////////////////////////////////////////////////////////////////
// #include "stdafx.h" - uncomment it if MFC with precompiled headers
#include "SMTP.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Static member initializers
//
// Note: the order of the entries is important.
// They must be synchronized with eResponse entries.
CSMTP::response_code CSMTP::response_table[] =
{
{ 250, "SMTP server error" }, // GENERIC_SUCCESS
{ 220, "SMTP server not available" }, // CONNECT_SUCCESS
{ 354, "SMTP server not ready for data" }, // DATA_SUCCESS
{ 221, "SMTP server didn't terminate session" } // QUIT_SUCCESS
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSMTP::CSMTP( LPCTSTR szSMTPServerName, UINT nPort )
{
ASSERT( szSMTPServerName != NULL );
AfxSocketInit();
m_sMailerName = _T( "WC Mail" );
m_sSMTPServerHostName = szSMTPServerName;
m_nPort = nPort;
m_bConnected = FALSE;
m_sError = _T( "OK" );
}
CSMTP::~CSMTP()
{
if( m_bConnected )
Disconnect();
}
CString CSMTP::GetServerHostName()
{
return m_sSMTPServerHostName;
}
BOOL CSMTP::Connect()
{
CString sHello;
TCHAR local_host[ 80 ]; // Warning: arbitrary size
if( m_bConnected )
return TRUE;
if( !m_wsSMTPServer.Create() )
{
m_sError = _T( "Unable to create the socket." );
return FALSE;
}
if( !m_wsSMTPServer.Connect( GetServerHostName(), GetPort() ) )
{
m_sError = _T( "Unable to connect to server" );
m_wsSMTPServer.Close();
return FALSE;
}
if( !get_response( CONNECT_SUCCESS ) )
{
m_sError = _T( "Server didn't respond." );
m_wsSMTPServer.Close();
return FALSE;
}
gethostname( local_host, 80 );
sHello.Format( "HELO %s\r\n", local_host );
m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() );
if( !get_response( GENERIC_SUCCESS ) )
{
m_wsSMTPServer.Close();
return FALSE;
}
m_bConnected = TRUE;
return TRUE;
}
BOOL CSMTP:

isconnect()
{
BOOL ret;
if( !m_bConnected )
return TRUE;
// Disconnect gracefully from the server and close the socket
CString sQuit = _T( "QUIT\r\n" );
m_wsSMTPServer.Send( (LPCTSTR)sQuit, sQuit.GetLength() );
// No need to check return value here.
// If it fails, the message is available with GetLastError
ret = get_response( QUIT_SUCCESS );
m_wsSMTPServer.Close();
m_bConnected = FALSE;
return ret;
}
UINT CSMTP::GetPort()
{
return m_nPort;
}
CString CSMTP::GetMailerName()
{
return m_sMailerName;
}
CString CSMTP::GetLastError()
{
return m_sError;
}
BOOL CSMTP::SendMessage(CMailMessage * msg)
{
ASSERT( msg != NULL );
if( !m_bConnected )
{
m_sError = _T( "Must be connected" );
return FALSE;
}
if( FormatMailMessage( msg ) == FALSE )
{
return FALSE;
}
if( transmit_message( msg ) == FALSE )
{
return FALSE;
}
return TRUE;
}
BOOL CSMTP::FormatMailMessage( CMailMessage* msg )
{
ASSERT( msg != NULL );
if( prepare_header( msg ) == FALSE )
{
return FALSE;
}
// Append a CR/LF to body if necessary.
if( msg->m_sBody.Right( 2 ) != "\r\n" )
msg->m_sBody += "\r\n";
return TRUE;
}
void CSMTP::SetServerProperties( LPCTSTR sServerHostName, UINT nPort)
{
ASSERT( sServerHostName != NULL );
// Needs to be safe in non-debug too
if( sServerHostName == NULL )
return;
m_sSMTPServerHostName = sServerHostName;
m_nPort = nPort;
}
// Create the SMTP message header as per RFC822
BOOL CSMTP:

repare_header(CMailMessage * msg)
{
ASSERT( msg != NULL );
CString sTo;
CString sDate;
CString& sHeader = msg->m_sHeader; // Shorthand
if( msg->GetNumRecipients() <= 0 )
{
m_sError = "No Recipients";
return FALSE;
}
sHeader = ""; // Clear it
// Get the recipients into a single string
sTo = "";
CString sEmail = "";
CString sFriendly = "";
for( int i = 0; i < msg->GetNumRecipients(); i++ )
{
msg->GetRecipient( sEmail, sFriendly, i );
sTo += ( i > 0 ? "," : "" );
sTo += sFriendly;
sTo += "<";
sTo += sEmail;
sTo += ">";
}
msg->m_tDateTime = msg->m_tDateTime.GetCurrentTime();
// Format: Mon, 01 Jun 98 01:10:30 GMT
sDate = msg->m_tDateTime.Format( "%a, %d %b %y %H:%M:%S %Z" );
sHeader.Format( "Date: %s\r\n" "From: %s\r\n" "To: %s\r\n" "Subject: %s\r\n" "X-Mailer: <%s>\r\n\r\n",
// Include other extension lines if desired
(LPCTSTR)sDate,
(LPCTSTR)msg->m_sFrom,
(LPCTSTR)sTo,
(LPCTSTR)msg->m_sSubject,
(LPCTSTR)m_sMailerName );
return TRUE;
}
CString CSMTP:

repare_body(CMailMessage * msg)
{
ASSERT( msg != NULL );
CString sTemp;
CString sCooked = "";
LPTSTR szBad = "\r\n.\r\n";
LPTSTR szGood = "\r\n..\r\n";
int nPos;
int nStart = 0;
int nBadLength = strlen( szBad );
sTemp = msg->m_sBody;
if( sTemp.Left( 3 ) == ".\r\n" )
sTemp = "." + sTemp;
//
// This is a little inefficient because it beings a search
// at the beginning of the string each time. This was
// the only thing I could think of that handled ALL variations.
// In particular, the sequence "\r\n.\r\n.\r\n" is troublesome.
// (Even CStringEx's FindReplace wouldn't handle that situation
// with the global flag set.)
//
while( (nPos = sTemp.Find( szBad )) > -1 )
{
sCooked = sTemp.Mid( nStart, nPos );
sCooked += szGood;
sTemp = sCooked + sTemp.Right( sTemp.GetLength() - (nPos + nBadLength) );
}
return sTemp;
}
BOOL CSMTP::transmit_message(CMailMessage * msg)
{
CString sFrom;
CString sTo;
CString sTemp;
CString sEmail;
ASSERT( msg != NULL );
if( !m_bConnected )
{
m_sError = _T( "Must be connected" );
return FALSE;
}
// Send the MAIL command
//
sFrom.Format( "MAIL From: <%s>\r\n", (LPCTSTR)msg->m_sFrom );
m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() );
if( !get_response( GENERIC_SUCCESS ) )
return FALSE;
// Send RCPT commands (one for each recipient)
//
for( int i = 0; i < msg->GetNumRecipients(); i++ )
{
msg->GetRecipient( sEmail, sTemp, i );
sTo.Format( "RCPT TO: <%s>\r\n", (LPCTSTR)sEmail );
m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );
get_response( GENERIC_SUCCESS );
}
// Send the DATA command
sTemp = "DATA\r\n";
m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
if( !get_response( DATA_SUCCESS ) )
{
return FALSE;
}
// Send the header
//
m_wsSMTPServer.Send( (LPCTSTR)msg->m_sHeader, msg->m_sHeader.GetLength() );
// Send the body
//
sTemp = prepare_body( msg );
m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
// Signal end of data
//
sTemp = "\r\n.\r\n";
m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
if( !get_response( GENERIC_SUCCESS ) )
{
return FALSE;
}
return TRUE;
}
BOOL CSMTP::get_response( UINT response_expected )
{
ASSERT( response_expected >= GENERIC_SUCCESS );
ASSERT( response_expected < LAST_RESPONSE );
CString sResponse;
UINT response;
response_code* pResp; // Shorthand
if( m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE ) == SOCKET_ERROR )
{
m_sError = _T( "Socket Error" );
return FALSE;
}
sResponse = response_buf;
sscanf( (LPCTSTR)sResponse.Left( 3 ), "%d", &response );
pResp = &response_table[ response_expected ];
if( response != pResp->nResponse )
{
m_sError.Format( "%d:%s", response, (LPCTSTR)pResp->sMessage );
return FALSE;
}
return TRUE;
}
How to use ?
CSMTP smtp(STRINGSERVER); // "mail.yyy.uk"

;
if( !smtp.Connect() )
{
LogError( smtp.GetLastError() );
return FALSE;
}
CMailMessage objMailMessage;
objMailMessage.AddRecipient("obislavu@hotmail.com"

;
objMailMessage.AddRecipient("abc@d.ca"

;
}
objMailMessage.m_sFrom = ".....FROMSTRING";
objMailMessage.m_sSubject ="....SUBJECTSTRING";
objMailMessage.m_sHeader = "";
objMailMessage.m_sBody = " ....sTextFromFile";
smtp.SendMessage(&objMailMessage);
if( !smtp.Disconnect() )
{
LogError( smtp.GetLastError() );
return FALSE;
}
See the // commented lines for the StdAfx.h.
Let me know if it is not working!
-obislavu-