//+--------------------------------------------------------------------------- // // 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 #include 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; }