-
February 3rd, 2013, 02:39 AM
#1
Sending email using C++
I am experimenting with sending email directly from an .exe created by Visual Studio 2010, using C++. I've taken some code originally posted by Andreas Masur (with minor modifications) as a starting point to start learning about this.
When I call the function SendEmail("mail.mydomain.com","targetaddress@mydomain.com","sentfromaddress@mydomain.com","email"), it makes it all the way through the function,and fills m_ErrorLogListBox with: "Sent email as email message to targetaddress@mydomain.com." (In other words, it seems to go through without problems, connecting as needed). When I check my email, however, nothing arrives. My domain host says that I need a user name and password in order to send email (which is reassuring). Unfortunately, I don't know how to modify the code to include these things.
Can anyone give me some pointers on where to go from here? (Specifically, how do I include passwords and so forth...)
Code:
void CTestEmailProgramDlg::Check(int iStatus, char *szFunction)
{
if((iStatus != SOCKET_ERROR) && (iStatus))
return;
string text_string(szFunction);
string error_string("Error during call to " + text_string + ": " + DataManip::itos(iStatus) + " - " + DataManip::itos(GetLastError()));
m_ErrorLogListBox.AddString(error_string.c_str());
}
bool CTestEmailProgramDlg::SendEmail(char* smtpserver, char* toaddress, char* fromaddress, char* message)
{
int iProtocolPort = 0;
char szSmtpServerName[64] = "";
char szToAddr[64] = "";
char szFromAddr[64] = "";
char szBuffer[4096] = "";
char szLine[255] = "";
char szMsgLine[255] = "";
SOCKET hServer;
WSADATA WSData;
LPHOSTENT lpHostEntry;
LPSERVENT lpServEntry;
SOCKADDR_IN SockAddr;
// Load command-line args
lstrcpy(szSmtpServerName, smtpserver);
lstrcpy(szToAddr, toaddress);
lstrcpy(szFromAddr, fromaddress);
// Create input stream for reading email message file
ifstream MsgFile(message);
// Attempt to intialize WinSock (1.1 or later)
if(WSAStartup(MAKEWORD(VERSION_MAJOR, VERSION_MINOR), &WSData))
{
string error_string = "Cannot find Winsock v" + DataManip::itos(VERSION_MAJOR) + "." + DataManip::itos(VERSION_MINOR) + " or later!\n";
m_ErrorLogListBox.AddString(error_string.c_str());
return false;
}
// Lookup email server's IP address.
lpHostEntry = gethostbyname(szSmtpServerName);
if(!lpHostEntry)
{
string servername(szSmtpServerName);
string error_string = "Cannot find SMTP mail server " + servername + "\n";
m_ErrorLogListBox.AddString(error_string.c_str());
return false;
}
// Create a TCP/IP socket, no specific protocol
hServer = socket(PF_INET, SOCK_STREAM, 0);
if(hServer == INVALID_SOCKET)
{
string error_string = "Cannot open mail server socket\n";
m_ErrorLogListBox.AddString(error_string.c_str());
return false;
}
// Get the mail service port
lpServEntry = getservbyname("mail", 0);
// Use the SMTP default port if no other port is specified
if(!lpServEntry)
iProtocolPort = htons(IPPORT_SMTP);
else
iProtocolPort = lpServEntry->s_port;
// Setup a Socket Address structure
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = iProtocolPort;
SockAddr.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
// Connect the Socket
if(connect(hServer, (PSOCKADDR) &SockAddr, sizeof(SockAddr)))
{
string error_string = "Error connecting to Server socket\n";
m_ErrorLogListBox.AddString(error_string.c_str());
return false;
}
// Receive initial response from SMTP server
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() Reply");
// Send HELO server.com
sprintf(szMsgLine, "HELO %s%s", szSmtpServerName, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() HELO");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() HELO");
// Send MAIL FROM: <sender@mydomain.com>
sprintf(szMsgLine, "MAIL FROM:<%s>%s", szFromAddr, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() MAIL FROM");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() MAIL FROM");
// Send RCPT TO: <receiver@domain.com>
sprintf(szMsgLine, "RCPT TO:<%s>%s", szToAddr, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() RCPT TO");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() RCPT TO");
// Send DATA
sprintf(szMsgLine, "DATA%s", CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() DATA");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() DATA");
// Send all lines of message body (using supplied text file)
MsgFile.getline(szLine, sizeof(szLine)); // Get first line
do // for each line of message text...
{
sprintf(szMsgLine, "%s%s", szLine, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() message-line");
MsgFile.getline(szLine, sizeof(szLine)); // get next line.
} while(MsgFile.good());
// Send blank line and a period
sprintf(szMsgLine, "%s.%s", CRLF, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() end-message");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() end-message");
// Send QUIT
sprintf(szMsgLine, "QUIT%s", CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() QUIT");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() QUIT");
// Report message has been sent
string text_message(message);
string to_address_string(szToAddr);
string error_string = "Sent " + text_message + " as email message to " + szToAddr;
m_ErrorLogListBox.AddString(error_string.c_str());
// Close server socket and prepare to exit.
closesocket(hServer);
WSACleanup();
return true;
}
error C2146a : syntax error : nebulizer stained in the tower floppy apple rider. Go rubble in flee smite. Bleeble snip snip.
Documentation says: error C2146a - This means there is an error somewhere in the course of human endeavor. Fix in the usual way.
-
February 3rd, 2013, 04:22 PM
#2
Re: Sending email using C++
Today many mail-servers require authentication before allowing you to send a mail. How this signalling is done I don't know but you can run the same commands as in the code by using Telnet to see what the server responds with. See http://en.wikipedia.org/wiki/Simple_...nsfer_Protocol
-
February 4th, 2013, 09:44 AM
#3
Re: Sending email using C++
if your server allows for a plain text user name and password, things are fairly easy, you just give the commands after the HELO (or EHLO) command.
This usually will only work with internal domain authentication (meaning the SMTP server will need to be in the same domain as you).
If you need actual SMTP authentication, then things are going to be considerably harder...
You'll need to take a look at RFC5321, RFC2821, RFC1869, RFC1870, RFC2554, RFC1731, RFC2195...
Here's the "simple" version of it all (http://www.fehcom.de/qmail/smtpauth.html)
if you want a full implemention, you'll also need to handle SSL and TLS type encryption (needed for public SMTP sites like yahoo and gmail).
-
February 4th, 2013, 02:11 PM
#4
Re: Sending email using C++
Or you could use these lib's and forget about all the strange stuff...
http://www.marshallsoft.com/
Select SMTP/POP3/IMAP Email component.
Jim
ATP BE400 CE500 (C550B-SPW) CE560XL MU300 CFI CFII
"The speed of non working code is irrelevant"... Of course that is just my opinion, I could be wrong.
"Nothing in the world can take the place of persistence. Talent will not; nothing is more common than unsuccessful men with talent. Genius will not; unrewarded genius is almost a proverb. Education will not; the world is full of educated derelicts. Persistence and determination are omnipotent. The slogan 'press on' has solved and always will solve the problems of the human race."...Calvin Coolidge 30th President of the USA.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|