Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

316 lines
8.4 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: smtp.cxx
//
// Contents: Contains the command to send SMTP mail
//
// Stolen from KrisK's mail.exe tool.
//
//----------------------------------------------------------------------------
#include "headers.hxx"
#include <iostream.h>
#include <winsock2.h>
HRESULT
CScriptHost::SendSMTPMail(BSTR bstrFrom,
BSTR bstrTo,
BSTR bstrCC,
BSTR bstrSubject,
BSTR bstrMessage,
BSTR bstrSMTPHost,
long *plError)
{
char achRecvBuf[2048];
unsigned short port = 25;
struct sockaddr_in Ser;
struct hostent * hp;
WSADATA wsaData;
SOCKET conn_socket = INVALID_SOCKET;
int iRet;
int iLen;
char achSendBuf[1024];
char * pch;
char * aszToList[30];
int cToList = 0;
char * aszCCList[30];
int cCCList = 0;
SYSTEMTIME stUT;
int i;
ANSIString szFrom(bstrFrom);
ANSIString szTo(bstrTo);
ANSIString szCC(bstrCC);
ANSIString szSubject(bstrSubject);
ANSIString szMessage(bstrMessage);
ANSIString szSMTPHost(bstrSMTPHost);
// ************** Parse the ToList into individual recipients
pch = szTo;
while (*pch && cToList < 30)
{
// Strip leading spaces from recipient name and terminate preceding
// name string.
if (isspace(*pch))
{
*pch=0;
pch++;
}
// Add a name to the array and increment the number of recipients.
else
{
aszToList[cToList++] = pch;
// Move beginning of string to next name in ToList.
do
{
pch++;
} while (isgraph(*pch));
}
}
// Parse the CCList into individual recipients
pch = szCC;
// Parse CCList into rgRecipDescStruct.
while (*pch && cCCList < 30)
{
// Strip leading spaces from recipient name and terminate preceding
// name string.
if (isspace(*pch))
{
*pch=0;
pch++;
}
// Add a name to the array and increment the number of recipients.
else
{
aszCCList[cCCList++] = pch;
// Move beginning of string to next name in CCList.
do
{
pch++;
} while (isgraph(*pch));
}
}
// ************** Initialize Windows Sockets
// BUGBUG -- Make error return code meaningful
iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iRet != 0)
{
*plError = iRet;
return S_OK;
}
hp = gethostbyname(szSMTPHost);
if (hp == NULL)
goto WSAError;
memset(&Ser,0,sizeof(Ser));
memcpy(&(Ser.sin_addr),hp->h_addr,hp->h_length);
Ser.sin_family = hp->h_addrtype;
Ser.sin_port = htons(port);
// Open a socket
conn_socket = socket(AF_INET, SOCK_STREAM, 0);
if (conn_socket == INVALID_SOCKET)
goto WSAError;
// ************** Connect to the SMTP host
iRet = connect(conn_socket, (struct sockaddr*)&Ser, sizeof(Ser));
if (iRet == SOCKET_ERROR)
goto WSAError;
// Get the server's initial response
iRet = recv(conn_socket, achRecvBuf, sizeof(achRecvBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// We expect code 220: "Service Ready"
if (strncmp(achRecvBuf, "220", 3) != 0)
goto ACKError;
// ************** Send the mail command
iLen = wsprintfA(achSendBuf, "MAIL FROM: <%s>\r\n", szFrom);
iRet = send(conn_socket, achSendBuf, iLen, 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
iRet = recv(conn_socket, achRecvBuf, sizeof(achRecvBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// We expect code 250: "Requested mail action OK, completed"
if (strncmp(achRecvBuf, "250", 3) != 0)
goto ACKError;
// ************** Send the recipient list (combination of TO and CC)
for (i = 0; i < cToList; i++)
{
iLen = wsprintfA(achSendBuf, "RCPT TO: <%s>\r\n", aszToList[i]);
iRet = send(conn_socket, achSendBuf, iLen, 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
iRet = recv(conn_socket, achRecvBuf, sizeof(achRecvBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// We expect code 250: "Requested mail action OK, completed"
if (strncmp(achRecvBuf, "250", 3) != 0)
goto ACKError;
}
for (i = 0; i < cCCList; i++)
{
iLen = wsprintfA(achSendBuf, "RCPT TO: <%s>\r\n", aszCCList[i]);
iRet = send(conn_socket, achSendBuf, iLen, 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
iRet = recv(conn_socket, achRecvBuf, sizeof(achRecvBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// We expect code 250: "Requested mail action OK, completed"
if (strncmp(achRecvBuf, "250", 3) != 0)
goto ACKError;
}
// ************** Send the mail headers
iLen = wsprintfA(achSendBuf, "DATA\r\n");
iRet = send(conn_socket, achSendBuf, iLen, 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
iRet = recv(conn_socket, achRecvBuf, sizeof(achRecvBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// We expect code 354: "Start mail input; End with ."
if (strncmp(achRecvBuf, "354", 3) != 0)
goto ACKError;
GetSystemTime(&stUT);
GetDateFormatA(LOCALE_NEUTRAL,
0,
&stUT,
"dd MMM yy",
achRecvBuf,
sizeof(achRecvBuf));
wsprintfA(achSendBuf,
"Date: %s %02d:%02d UT\r\n",
achRecvBuf,
stUT.wHour,
stUT.wMinute);
iRet = send(conn_socket, achSendBuf, strlen(achSendBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
wsprintfA(achSendBuf, "From: <%s>\r\n", szFrom);
wsprintfA(&achSendBuf[strlen(achSendBuf)], "Subject: %s\r\n", szSubject);
wsprintfA(&achSendBuf[strlen(achSendBuf)], "To: ");
for (i = 0; i < cToList; i++)
{
wsprintfA(&achSendBuf[strlen(achSendBuf)],
"<%s>%s",
aszToList[i],
(i == cToList-1) ? "\r\n" : ",\r\n ");
}
if (cCCList > 0)
{
wsprintfA(&achSendBuf[strlen(achSendBuf)], "cc: ", szFrom);
for (i = 0; i < cCCList; i++)
{
wsprintfA(&achSendBuf[strlen(achSendBuf)],
"<%s>%s",
aszCCList[i],
(i == cCCList-1) ? "\r\n" : ",\r\n ");
}
}
wsprintfA(&achSendBuf[strlen(achSendBuf)], "Reply-To: <%s>\r\n\r\n", szFrom);
/*
BUGBUG -- Perhaps support HTML formatted mail in the future?
if ( html )
str += "MIME-Version: 1.0\r\nContent-Type: text/html;\r\n charset=\"iso-8859-1\"\r\nSUBJECT: "+ title + "\r\n\r\n"+ message +"\r\n.\r\n";
*/
iRet = send(conn_socket, achSendBuf, strlen(achSendBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// ************** Send the message body
iRet = send(conn_socket, szMessage, strlen(szMessage), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// ************** Close the connection
strcpy(achSendBuf, "\r\n.\r\n");
iRet = send(conn_socket, achSendBuf, strlen(achSendBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
iRet = recv(conn_socket, achRecvBuf, sizeof(achRecvBuf), 0);
if (iRet == SOCKET_ERROR)
goto WSAError;
// We expect code 250: "Requested mail action OK, completed"
if (strncmp(achRecvBuf, "250", 3) != 0)
goto ACKError;
strcpy(achSendBuf, "QUIT\r\n");
send(conn_socket, achSendBuf, strlen(achSendBuf), 0);
Cleanup:
if (conn_socket != INVALID_SOCKET)
{
closesocket(conn_socket);
}
WSACleanup();
return S_OK;
ACKError:
// BUGBUG -- Preserve entire string that was returned
achRecvBuf[3] = '\0';
*plError = atoi(achRecvBuf);
goto Cleanup;
WSAError:
*plError = WSAGetLastError();
goto Cleanup;
}