// ==========================================================================
// Author: Yee Hsu
// Date: 6/11/2005
// File: SMTP.cpp
//
// Desc: This is the SMTP class implementation file. This file
// implements all necessary variables and funtions to create
// an open socket that connects to a remote SMTP Email Server,
// and sends a contructed email to the recipient.
//
// Currently, this implementation only supports TCP connection
// and is only an MUA (Mail User Agent). What's cool about this
// class and implementation is it is cross platform independent
// and may be compiled on Windows or Unix machines.
//
// Legal: Copyright (c) Yee Hsu 2005
// ==========================================================================
#include "SMTP.h"
// ==========================================================================
// Identifier: SMTP()
//
// Description: SMTP Constructor
// Initialize default Email fields
// User should overside these variables before sending Email
// ==========================================================================
SMTP::SMTP()
{
// initialize default SMTP Server
this->SMTP_Server = "localhost";
// initialize default Email fields
this->From = "postmaster@localhost";
this->Rcpt = "postmaster@localhost";
this->To = "";
this->Cc = "";
this->Subject = "";
this->Body = "";
// initialize Send Mail Vars
this->Packet.erase();
}
// ==========================================================================
// Identifier: ~SMTP()
//
// Description: SMTP Destructor
// Deinitialize all Email fiends
// ==========================================================================
SMTP::~SMTP()
{
// empty all Email fields
this->From.erase();
this->Rcpt.erase();
this->To.erase();
this->Cc.erase();
this->Subject.erase();
this->Body.erase();
this->Packet.erase();
}
// ==========================================================================
// Identifier: Send(void)
//
// Post: Email is sent to the SMTP server which will deliver
// the email to the recipent(s)
//
// Calls: Many socket system calls to deliver the email message
//
// Returns: True if email sent successfully, False otherwise
//
// Description: Send generates the Email packet and sends it to the
// recipient. The packet is created by first opening a
// socket and connecting to the destination SMTP server,
// the email packet is created and finally sent off to
// the recipient. This is an email sent via TCP stream
// and currently is only an MUA.
// ==========================================================================
bool SMTP::Send(void)
{
SOCKET sd = 0;
struct sockaddr_in sock, sockName;
struct hostent *pHost;
// initialize Window Socket DLL
this->WinInit();
// translate domain name to ip address
if ((pHost = gethostbyname(SMTP_Server.c_str())) == NULL)
{
fprintf(stderr, "Error: gethostbyname()\n");
return false;
}
// setup server socket
memset(&sock, 0, sizeof(sock));
sock.sin_family = AF_INET;
memcpy(&sock.sin_addr, pHost->h_addr_list[0], pHost->h_length);
sock.sin_port = htons(SMTP_PORT);
// setup local socket
memset(&sockName,0, sizeof(sockName));
sockName.sin_family = AF_INET;
sockName.sin_addr.s_addr = INADDR_ANY;
sockName.sin_port = htons(0);
// Create a Socket
if ((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "Error: socket()\n");
return false;
}
// Bind to Socket
if (bind(sd, (struct sockaddr*) &sockName, sizeof(sockName)) < 0)
{
fprintf(stderr, "Error: bind()\n");
return false;
}
// Make TCP Connection to Socket
if ((connect(sd, (struct sockaddr*) &sock, sizeof(sock))) < 0)
{
fprintf(stderr, "Error: connect()\n");
return false;
}
// Contruct the Email Message according to SMTP Protocol
this->Packet.erase();
// Contruct Email Source and Recipient address
this->Packet += "MAIL FROM:<" + this->From + ">\r\n";
this->Packet += "RCPT TO:<" + this->Rcpt + ">\r\n";
// Contruct Email Subject and Body
this->Packet += "DATA\r\n";
this->Packet += "From: " + this->From + "\r\n";
this->Packet += "To: " + this->To + "\r\n";
this->Packet += "Cc: " + this->Cc + "\r\n";
this->Packet += "Subject: " + this->Subject + "\r\n";
this->Packet += "" + this->Body + "\r\n";
// Tag Email termination seqeunce
this->Packet += "\r\n.\r\n";
this->Packet += "QUIT\r\n";
// Finally, Send the Email
if (send(sd, this->Packet.c_str(), this->Packet.length(), 0) < 0)
{
fprintf(stderr, "Error: send()\n");
return false;
}
// Close all open sockets and release Window Socket DLL
close(sd);
this->WinTerm();
return true;
}
// ==========================================================================
// Identifier: WinInit(void)
//
// Description: A must to init for Window Socket.
// This should be called at the beginning of every
// program when using Window Sockets. This function opens
// and utilizes an WinSock DLL.
// ==========================================================================
void SMTP::WinInit(void)
{
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err = 0;
wVersionRequested = MAKEWORD(2,0);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
fprintf(stderr, "Error: unable to initialize WinSock DLL\n");
return;
}
#endif
}
// ==========================================================================
// Identifier: WinTerm(void)
//
// Description: A must to term for Window Socket.
// This should be called at the end of every
// program when using Window Sockets.
// ==========================================================================
void SMTP::WinTerm(void)
{
#ifdef _WIN32
WSACleanup();
#endif
}