分类: C/C++
2008-08-26 11:26:21
Win32 SMTP Wrapper with handy local ip and hostname functions.
A real basic SMTP wrapper. I tried to find one, but I couldn't - so here is another one. It is fast and straight forward - just instantiate the class with a SMTP server and then set the sender email property and message body. The rest of the settings are pretty much optional. There are also a couple of nice utility functions for getting your local hostname and local ip address.
We hope this code helps you out!
CFastSmtp mail; if (mail.ConnectServer("SERVER")) { mail.SetSenderName("Sender's Name"); mail.SetSenderEmail("senders@address.com"); mail.SetSubject("CFastSmtp v1.1 Release"); mail.AddRecipient("test@test.com"); mail.AddCCRecipient("test@test.com"); mail.AddBCCRecipient("test@test.com"); mail.SetMessageBody("Here is another test of CFastSmtp SMTP class!"); if (mail.GetConnectStatus()) { printf(mail.Send() ? "Send was a success!" : "Send failed!"); mail.Disconnect(); } }
Here is the source (FastSmtp.cpp):
//******************************************************************** /* Fast & Simple SMTP Class Author: christopher w. backenHere is the header (FastSmtp.h):Purpose: Simple smtp class with handy local ip and hostname functions ToDo: Attachments & UUEncode/Decode */ //******************************************************************** //*** Change History //*** DEVELOPER DATE MODIFICATION //*** //*** christopher w. backen 09.05.2002 Misc. updates and corrections //*** christopher w. backen 08.28.2001 Bug fixes & code changes //*** christopher w. backen 04.12.2001 Release //*** //******************************************************************** #include "stdafx.h" #include "FastSmtp.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CFastSmtp::CFastSmtp() { // Initialize variables bCon = false; m_pcFromEmail = NULL; m_pcFromName = NULL; m_pcSubject = NULL; m_pcMsgBody = NULL; m_pcXMailer = NULL; m_pcReplyTo = NULL; m_pcIPAddr = NULL; // Initialize WinSock WORD wVer = MAKEWORD(2,2); if (WSAStartup(wVer,&wsaData) != NO_ERROR) { printf("WSAStartup %d\r\n", WSAGetLastError()); throw; } if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { printf("Can't find a useable WinSock DLL\r\n"); WSACleanup(); throw; } } CFastSmtp::~CFastSmtp() { // Free recipient lists for (unsigned int n = 0; n < Recipients.size(); n++) delete Recipients[n]; for (unsigned int n = 0; n < CCRecipients.size(); n++) delete CCRecipients[n]; for (unsigned int n = 0; n < BCCRecipients.size(); n++) delete BCCRecipients[n]; // Free variables if (m_pcFromEmail) delete m_pcFromEmail; if (m_pcFromName) delete m_pcFromName; if (m_pcSubject) delete m_pcSubject; if (m_pcMsgBody) delete m_pcMsgBody; if (m_pcXMailer) delete m_pcXMailer; if (m_pcReplyTo) delete m_pcReplyTo; // Close connection if (bCon) Disconnect(); // Cleanup WSACleanup(); } bool CFastSmtp::AddRecipient(const char email[], const char name[]) { assert(email); int s=strlen(email); if (s==0) return false; CRecipient *pRec = new CRecipient(); char *pcBuf = new char[s+strlen(name)+4]; sprintf(pcBuf,"%s<%s>",name,email); pRec->SetEmail(pcBuf); Recipients.insert(Recipients.end(), pRec); delete pcBuf; return (true); } bool CFastSmtp::AddCCRecipient(const char email[], const char name[]) { assert(email); int s=strlen(email); if (s==0) return false; CRecipient *pRec = new CRecipient(); char *pcBuf = new char[s+strlen(name)+4]; sprintf(pcBuf,"%s<%s>",name,email); pRec->SetEmail(pcBuf); CCRecipients.insert(CCRecipients.end(), pRec); delete pcBuf; return (true); } bool CFastSmtp::AddBCCRecipient(const char email[], const char name[]) { assert(email); int s=strlen(email); if (s==0) return false; CRecipient *pRec = new CRecipient(); char *pcBuf = new char[s+strlen(name)+4]; sprintf(pcBuf,"%s<%s>",name,email); pRec->SetEmail(pcBuf); BCCRecipients.insert(BCCRecipients.end(), pRec); delete pcBuf; return (true); } bool CFastSmtp::Disconnect() { if (!bCon) { printf("Not connected to server!\r\n"); return (false); } BYTE sReceiveBuffer[4096]; int iLength = 0; int iEnd = 0; if (send(hSocket, (LPSTR)"QUIT\r\n", strlen("QUIT\r\n"), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; bCon=false; hSocket=NULL; return (true); } bool CFastSmtp::Send() { // verify sender email if (m_pcFromEmail == NULL) { printf("Please specifiy a sender email address\r\n"); return (false); } BYTE sReceiveBuffer[4096]; int iLength = 0; int iEnd = 0; char buf[4096]; // get proper header char* msgHeader = _formatHeader(); if (msgHeader == NULL) { delete [] msgHeader; printf("Failed to format message header\r\n"); return (false); } // start strcpy(buf, "MAIL FROM: <"); strcat(buf, m_pcFromEmail); strcat(buf, ">\r\n"); if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; // create message receipts char *token; for(unsigned int i=0;i<Recipients.size();i++) { token = strtok(Recipients.at(i)->GetEmail(),"<"); token = strtok(NULL,"<"); if (token == NULL) token = strtok(Recipients.at(i)->GetEmail(),"<"); strcpy(buf, "RCPT TO: <"); strcat(buf, token); strcat(buf, "\r\n"); if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; } for(unsigned int i=0;i<CCRecipients.size();i++) { token = strtok(CCRecipients.at(i)->GetEmail(),"<"); token = strtok(NULL,"<"); if (token == NULL) token = strtok(Recipients.at(i)->GetEmail(),"<"); strcpy(buf, "RCPT TO: <"); strcat(buf, token); strcat(buf, "\r\n"); if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; } for(unsigned int i=0;i<BCCRecipients.size();i++) { token = strtok(BCCRecipients.at(i)->GetEmail(),"<"); token = strtok(NULL,"<"); if (token == NULL) token = strtok(Recipients.at(i)->GetEmail(),"<"); strcpy(buf, "RCPT TO: <"); strcat(buf, token); strcat(buf, "\r\n"); if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd, sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; } // init data if (send(hSocket, (LPSTR)"DATA\r\n", strlen("DATA\r\n"), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; // send header if (send(hSocket, (LPSTR)msgHeader, strlen(msgHeader), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); delete [] msgHeader; return (false); } // send body if (send(hSocket, (LPSTR)m_pcMsgBody, strlen(m_pcMsgBody), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } // signal end if (send(hSocket, (LPSTR)"\r\n.\r\n", strlen("\r\n.\r\n"), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; delete [] msgHeader; return (true); } bool CFastSmtp::ConnectServer(const char server[], const unsigned short port) { assert(server); if (bCon) Disconnect(); bCon=false; hSocket = INVALID_SOCKET; hSocket = _connectServerSocket(server, port); if (hSocket != INVALID_SOCKET) { BYTE sReceiveBuffer[4096]; int iLength = 0; int iEnd = 0; char buf[4096]; strcpy(buf, "HELO "); strcat(buf, server); strcat(buf, "\r\n"); if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) { printf("Socket send error: %d\r\n", WSAGetLastError()); return (false); } iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,sizeof(sReceiveBuffer)-iEnd, NO_FLAGS); iEnd += iLength; sReceiveBuffer[iEnd] = '\0'; } else { printf("Invalid socket\r\n"); return (false); } bCon=true; return (true); } SOCKET CFastSmtp::_connectServerSocket(const char server[], const unsigned short port) { int nConnect; short nProtocolPort; LPHOSTENT lpHostEnt; LPSERVENT lpServEnt; SOCKADDR_IN sockAddr; SOCKET hServerSocket = INVALID_SOCKET; lpHostEnt = gethostbyname(server); if (lpHostEnt) { hServerSocket = socket(PF_INET, SOCK_STREAM,DEFAULT_PROTOCOL); if (hServerSocket != INVALID_SOCKET) { if (port != NULL) { nProtocolPort = port; }else{ lpServEnt = getservbyname("mail", DEFAULT_PROTOCOL); if (lpServEnt == NULL) nProtocolPort = htons(IPPORT_SMTP); else nProtocolPort = lpServEnt->s_port; } sockAddr.sin_family = AF_INET; sockAddr.sin_port = nProtocolPort; sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list); nConnect = connect(hServerSocket, (PSOCKADDR)&sockAddr, sizeof(sockAddr)); if(nConnect) hServerSocket = INVALID_SOCKET; } else { printf("Invalid socket\r\n"); throw; } } return(hServerSocket); } char* CFastSmtp::_formatHeader() { // check for at least one recipient if(Recipients.size() <= 0 ) { printf("Please add a message recipient!\r\n"); return NULL; } int s=0; char *msgHeader = new char[16385]; //char to[1024]; for (unsigned int i=s=0;i<Recipients.size();i++) { s+=strlen(Recipients.at(i)->GetEmail())+1; } if (s==0) s=1; char *to = new char[s]; //char cc[1024]; for (i=s=0;i<CCRecipients.size();i++) { s+=strlen(CCRecipients.at(i)->GetEmail())+1; } if (s==0) s=1; char *cc = new char[s]; //char bcc[1024]; for (i=s=0;i<BCCRecipients.size();i++) { s+=strlen(BCCRecipients.at(i)->GetEmail())+1; } if (s==0) s=1; char *bcc = new char[s]; TCHAR szDate[500]; TCHAR sztTime[500]; // create the recipient string, cc string, and bcc string to[0] = '\0'; for (i=0;i<Recipients.size();i++) { i > 0 ? strcat(to,","):strcat(to,""); strcat(to,Recipients.at(i)->GetEmail()); } cc[0] = '\0'; for (i=0;i<CCRecipients.size();i++) { i > 0 ? strcat(cc,","):strcat(cc,""); strcat(cc,CCRecipients.at(i)->GetEmail()); } bcc[0] = '\0'; for (i=0;i<BCCRecipients.size();i++) { i > 0 ? strcat(bcc,","):strcat(bcc,""); strcat(bcc,BCCRecipients.at(i)->GetEmail()); } // get the current date and time SYSTEMTIME st={0}; ::GetSystemTime(&st); ::GetDateFormat(LOCALE_SYSTEM_DEFAULT,0,&st,"ddd', ' dd MMM yyyy",szDate,sizeof(szDate)); ::GetTimeFormat(LOCALE_SYSTEM_DEFAULT,TIME_FORCE24HOURFORMAT,&st, "HH':'mm':'ss tt",sztTime,sizeof(sztTime)); // here it is...the main data of the message wsprintf(msgHeader,"DATE: %s %s\r\n", szDate, sztTime); if (m_pcFromName != NULL) { strcat(msgHeader,"FROM: "); strcat(msgHeader, m_pcFromName); strcat(msgHeader, "\r\n"); } strcat(msgHeader,"To: "); strcat(msgHeader, to); strcat(msgHeader, "\r\n"); strcat(msgHeader,"Cc: "); strcat(msgHeader, cc); strcat(msgHeader, "\r\n"); if (m_pcSubject != NULL) { strcat(msgHeader, "Subject: "); strcat(msgHeader, m_pcSubject); strcat(msgHeader, "\r\n"); } if (m_pcXMailer != NULL) { strcat(msgHeader,"X-Mailer: "); strcat(msgHeader, m_pcXMailer); strcat(msgHeader, "\r\n"); } // start optional fields if (m_pcReplyTo != NULL) { strcat(msgHeader, "Reply-To: "); strcat(msgHeader, m_pcReplyTo); strcat(msgHeader, "\r\n"); } // start MIME versions strcat(msgHeader, "MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n"); // send header finish command strcat(msgHeader, "\r\n"); // clean up delete to; delete cc; delete bcc; // done return msgHeader; } const char* const CFastSmtp::GetLocalHostIp() { in_addr *iaHost; if (gethostname(m_cHostName,255) != SOCKET_ERROR) { HOSTENT *pHe = NULL; pHe = gethostbyname(m_cHostName); if (pHe != NULL) { for (int i=0;pHe->h_addr_list[i] != 0;i++) { iaHost = (LPIN_ADDR)pHe->h_addr_list[i]; m_pcIPAddr = inet_ntoa(*iaHost); } } } else { DWORD dErr = WSAGetLastError(); printf("Failed to get the local ip address\r\n"); } return m_pcIPAddr; } const char* const CFastSmtp::GetLocalHostname() { if (gethostname((char FAR*)m_cHostName,255) == SOCKET_ERROR) printf("Failed to get the local hostname\r\n"); return m_cHostName; } //********************************************************************************** //*** Properties //********************************************************************************** bool CFastSmtp::GetConnectStatus() { return (bCon); } unsigned const int CFastSmtp::GetBCCRecipientCount() { return (BCCRecipients.size()); } unsigned const int CFastSmtp::GetCCRecipientCount() { return (CCRecipients.size()); } unsigned const int CFastSmtp::GetSocket() { return (hSocket); } const char* const CFastSmtp::GetMessageBody() { return (m_pcMsgBody); } unsigned const int CFastSmtp::GetRecipientCount() { return (Recipients.size()); } const char* const CFastSmtp::GetReplyTo() { return (m_pcReplyTo); } const char* const CFastSmtp::GetSenderEmail() { return (m_pcFromEmail); } const char* const CFastSmtp::GetSenderName() { return (m_pcFromName); } const char* const CFastSmtp::GetSubject() { return (m_pcSubject); } const char* const CFastSmtp::GetXMailer() { return (m_pcXMailer); } void CFastSmtp::SetMessageBody(const char body[]) { assert(body); int s=strlen(body); if (m_pcMsgBody) delete [] m_pcMsgBody; m_pcMsgBody = new char[s+1]; strcpy(m_pcMsgBody, body); } void CFastSmtp::SetReplyTo(const char replyto[]) { assert(replyto); int s=strlen(replyto); if (m_pcReplyTo) delete [] m_pcReplyTo; m_pcReplyTo = new char[s+1]; strcpy(m_pcReplyTo, replyto); } void CFastSmtp::SetSenderEmail(const char email[]) { assert(email); int s=strlen(email); if (m_pcFromEmail) delete [] m_pcFromEmail; m_pcFromEmail = new char[s+1]; strcpy(m_pcFromEmail, email); } void CFastSmtp::SetSenderName(const char name[]) { assert(name); int s=strlen(name); if (m_pcFromName) delete [] m_pcFromName; m_pcFromName = new char[s+1]; strcpy(m_pcFromName, name); } void CFastSmtp::SetSubject(const char subject[]) { assert(subject); int s=strlen(subject); if (m_pcSubject) delete [] m_pcSubject; m_pcSubject = new char[s+1]; strcpy(m_pcSubject, subject); } void CFastSmtp::SetXMailer(const char xmailer[]) { assert(xmailer); int s=strlen(xmailer); if (m_pcXMailer) delete [] m_pcXMailer; m_pcXMailer = new char[s+1]; strcpy(m_pcXMailer, xmailer); }
// CFastSmtp.h: interface for the Smtp class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_SMTP_H__C66CDD0A_4F6F_4465_BAD6_8FA531785B5D__INCLUDED_) #define AFX_SMTP_H__C66CDD0A_4F6F_4465_BAD6_8FA531785B5D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <winsock2.h> #include <assert.h> #include <vector> const int DEFAULT_PROTOCOL = 0; const int NO_FLAGS = 0; class CFastSmtp { public: CFastSmtp(); virtual ~CFastSmtp(); bool AddRecipient(const char email[], const char name[]=""); bool AddBCCRecipient(const char email[], const char name[]=""); bool AddCCRecipient(const char email[], const char name[]=""); bool ConnectServer(const char server[], const unsigned short port=NULL); bool Disconnect(); bool GetConnectStatus(); const unsigned int GetBCCRecipientCount(); const unsigned int GetCCRecipientCount(); const unsigned int GetRecipientCount(); const unsigned int GetSocket(); const char* const GetLocalHostIp(); const char* const GetLocalHostname(); const char* const GetMessageBody(); const char* const GetReplyTo(); const char* const GetSenderEmail(); const char* const GetSenderName(); const char* const GetSubject(); const char* const GetXMailer(); bool Send(); void SetMessageBody(const char body[]); void SetSubject(const char subject[]); void SetSenderName(const char name[]); void SetSenderEmail(const char email[]); void SetReplyTo(const char replyto[]); void SetXMailer(const char xmailer[]); private: class CRecipient { public: CRecipient() { m_pcEmail = NULL; }; CRecipient& operator=(const CRecipient& src) { if (&src != this) { if (m_pcEmail) delete [] m_pcEmail; int s = strlen(src.m_pcEmail); m_pcEmail = new char[s+1]; strcpy(m_pcEmail, src.m_pcEmail); } return (*this); }; virtual ~CRecipient() { if (m_pcEmail) delete [] m_pcEmail; }; char* GetEmail() { return m_pcEmail; }; void SetEmail(const char email[]) { assert(email); int s=strlen(email); if (s > 0) { m_pcEmail = new char[s+1]; strcpy(m_pcEmail, email); } }; private: char *m_pcEmail; }; bool bCon; char m_cHostName[MAX_PATH]; char* m_pcFromEmail; char* m_pcFromName; char* m_pcSubject; char* m_pcMsgBody; char* m_pcXMailer; char* m_pcReplyTo; char* m_pcIPAddr; WSADATA wsaData; SOCKET hSocket; std::vector<CRecipient*> Recipients; std::vector<CRecipient*> CCRecipients; std::vector<CRecipient*> BCCRecipients; char* _formatHeader(); bool _formatMessage(); SOCKET _connectServerSocket(const char* server, const unsigned short port=NULL); }; #endif // !defined(AFX_SMTP_H__C66CDD0A_4F6F_4465_BAD6_8FA531785B5D__INCLUDED_)