📄 sendmail.c
字号:
/////////////////////////////////////////////////////////////////
// SendMail.cpp - implements the functions for the SendMail DLL.
// Author - Arnab Bhaduri.
/////////////////////////////////////////////////////////////////
// defines //////////////////////////////////////////////////////
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define NOIME
#define VERIFY_RET_VAL( arg ) \
{ int nRet = arg; if( nRet ) return nRet; }
// includes /////////////////////////////////////////////////////
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include "sendmail.h"
// private functions - used internally //////////////////////////
int SendMailMessage( SENDMAIL *pMail );
int Send( SOCKET s, const char *lpszBuff, int nLen, int nFlags );
int Receive( SOCKET s, LPTSTR lpszBuff, int nLenMax, int nFlags,
LPCTSTR lpszReplyCode );
void LogMessage( LPCTSTR lpszMsg );
// Static variables /////////////////////////////////////////////
static BOOL gbLog = FALSE;
static HANDLE ghFile = INVALID_HANDLE_VALUE;
static char gszMailerID[] = "X-Mailer: SendMail DLL V1.0\r\n";
static char gszLogFile[] = "SendMail.Log";
// SendMail - sends an SMTP mail message to specified host. This
// is the only exported function from this DLL.
/////////////////////////////////////////////////////////////////
__declspec ( dllexport )
BOOL WINAPI SendMail( SENDMAIL *pMail, int *pResult )
{
WORD wVersion = MAKEWORD( 1, 1 );
WSADATA wsaData;
int nRet;
// check for required parameters
if( pMail == NULL || pResult == NULL || pMail->lpszHost == NULL ||
pMail->lpszRecipient == NULL || pMail->lpszSubject == NULL ||
pMail->lpszMessage == NULL )
{
if( pResult )
*pResult = WSAEINVAL;
return FALSE;
}
if( (*pResult = WSAStartup(wVersion, &wsaData)) )
return FALSE;
// open log file if specified
if( pMail->bLog )
{
char szLogPath[ MAX_PATH + 1 ];
*szLogPath = '\0';
GetTempPath( MAX_PATH, szLogPath );
strcat( szLogPath, gszLogFile );
ghFile = CreateFile( szLogPath, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL );
if( ghFile != INVALID_HANDLE_VALUE )
gbLog = TRUE;
}
// try to send the message
nRet = SendMailMessage( pMail );
if( nRet != 0 )
{
if( gbLog )
{
char szMsg[ MAX_LINE_SIZE ];
if( nRet < 0 )
sprintf( szMsg, "SMTP error %d in SendMail.\n",
-nRet );
else
sprintf( szMsg, "Socket error %d in SendMail.\n",
nRet );
LogMessage( szMsg );
}
}
// cleanup socket lib and log file
WSACleanup();
if( ghFile != INVALID_HANDLE_VALUE )
{
CloseHandle( ghFile );
ghFile = INVALID_HANDLE_VALUE;
gbLog = FALSE;
}
*pResult = nRet;
return ( *pResult == 0 );
}
// SendMailMessage - actually sends the message.This is a private
// function.
/////////////////////////////////////////////////////////////////
int SendMailMessage( SENDMAIL *pMail )
{
char szBuff[ MAX_LINE_SIZE + 1 ]; // transmit/receive buffer
char szUser[ MAX_NAME_SIZE + 1 ]; // user name buffer
char szName[ MAX_NAME_SIZE + 1 ]; // host name buffer
DWORD dwSize = MAX_NAME_SIZE;
SOCKET s;
struct hostent *ph;
struct sockaddr_in addr;
char szTime[ MAX_NAME_SIZE + 1 ]; // time related vars
time_t tTime;
struct tm *ptm;
struct timeb tbTime;
// connect to the SMTP port on remote host
if( (s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
return WSAGetLastError();
if( isdigit(*pMail->lpszHost) && strchr(pMail->lpszHost, '.') )
{
unsigned long iaddr = inet_addr( pMail->lpszHost );
ph = gethostbyaddr( (const char *)&iaddr, 4, PF_INET );
}
else
ph = gethostbyname( pMail->lpszHost );
if( ph == NULL )
return WSAGetLastError();
addr.sin_family = AF_INET;
addr.sin_port = htons( SMTP_PORT );
memcpy( &addr.sin_addr, ph->h_addr_list[0],
sizeof(struct in_addr) );
if( connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr)) )
return WSAGetLastError();
// receive signon message
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "220" ); );
// get user name and local host name
GetUserName( szUser, &dwSize );
gethostname( szName, MAX_NAME_SIZE );
// send HELO message
sprintf( szBuff, "HELO %s\r\n", szName );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "250" ); )
// send MAIL message
if( pMail->lpszSender )
{
sprintf( szBuff, "MAIL FROM: <%s", pMail->lpszSender );
if( strchr( pMail->lpszSender, '@' ) )
strcat( szBuff, ">\r\n" );
else
sprintf( szBuff + strlen( szBuff ), "@%s>\r\n", szName );
}
else
sprintf( szBuff, "MAIL FROM:<%s@%s>\r\n", szUser, szName );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "250" ); )
// send RCPT message
sprintf( szBuff, "RCPT TO: <%s>\r\n", pMail->lpszRecipient );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "25" ); )
// send DATA message
sprintf( szBuff, "DATA\r\n" );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "354" ); )
// construct date string
tTime = time( NULL );
ptm = localtime( &tTime );
strftime( szTime, MAX_NAME_SIZE, "%a, %d %b %Y %H:%M:%S %Z", ptm );
// find time zone offset and correct for DST
ftime( &tbTime );
if( tbTime.dstflag )
tbTime.timezone -= 60;
sprintf( szTime + strlen(szTime), " %2.2d%2.2d",
-tbTime.timezone / 60, tbTime.timezone % 60 );
// send mail headers
// Date:
sprintf( szBuff, "Date: %s\r\n", szTime );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
// X-Mailer:
VERIFY_RET_VAL( Send( s, gszMailerID, strlen(gszMailerID), 0 ); )
// Message-ID:
if( pMail->lpszMessageID )
{
sprintf( szBuff, "Message-ID: %s\r\n", pMail->lpszMessageID );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
}
// To:
sprintf( szBuff, "To: %s", pMail->lpszRecipient );
if( pMail->lpszRecipientName )
sprintf( szBuff + strlen(szBuff), " (%s)\r\n",
pMail->lpszRecipientName );
else
strcat( szBuff, "\r\n" );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
// From:
if( pMail->lpszSender )
{
sprintf( szBuff, "From: %s", pMail->lpszSender );
if( pMail->lpszSenderName )
sprintf( szBuff + strlen(szBuff), " (%s)\r\n",
pMail->lpszSenderName );
else
strcat( szBuff, "\r\n" );
}
else
sprintf( szBuff, "From: %s@%s\r\n", szUser, szName );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
// Reply-To:
if( pMail->lpszReplyTo )
{
sprintf( szBuff, "Reply-To: %s", pMail->lpszReplyTo );
if( pMail->lpszReplyToName )
sprintf( szBuff + strlen(szBuff), " (%s)\r\n",
pMail->lpszReplyToName );
else
strcat( szBuff, "\r\n" );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
}
// Subject:
sprintf( szBuff, "Subject: %s\r\n", pMail->lpszSubject );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
/////////////////////////////////////////////////////////
// 08/13/98 rlb
// empty line needed after headers, RFC822
strcpy(szBuff, "\r\n");
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
/////////////////////////////////////////////////////////
// send message text
VERIFY_RET_VAL( Send( s, pMail->lpszMessage, \
strlen(pMail->lpszMessage), 0 ); )
// send message terminator and receive reply
VERIFY_RET_VAL( Send( s, "\r\n.\r\n", 5, 0 ); )
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "250" ); )
// send QUIT message
sprintf( szBuff, "QUIT\r\n" );
VERIFY_RET_VAL( Send( s, szBuff, strlen(szBuff), 0 ); )
VERIFY_RET_VAL( Receive( s, szBuff, MAX_LINE_SIZE, 0, "221" ); )
closesocket( s );
return 0;
}
// Send - send the request to the SMTP server, and handle errors.
/////////////////////////////////////////////////////////////////
int Send( SOCKET s, const char *lpszBuff, int nLen, int nFlags )
{
int nCnt = 0;
while( nCnt < nLen )
{
int nRes = send( s, lpszBuff + nCnt, nLen - nCnt, nFlags );
if( nRes == SOCKET_ERROR )
return WSAGetLastError();
else
nCnt += nRes;
}
if( gbLog )
LogMessage( lpszBuff );
return 0;
}
// Receive - receive a reply from the SMTP server, and verify that
// the request has succeeded by checking against the specified
// reply code.
/////////////////////////////////////////////////////////////////
int Receive( SOCKET s, LPTSTR lpszBuff, int nLenMax, int nFlags,
LPCTSTR lpszReplyCode )
{
LPTSTR p;
int nRes = recv( s, lpszBuff, nLenMax, nFlags );
if( nRes == SOCKET_ERROR )
return WSAGetLastError();
else
*( lpszBuff + nRes ) = '\0';
if( gbLog )
LogMessage( lpszBuff );
// check reply code for success/failure
p = strtok( lpszBuff, "\n" );
while( p )
{
if( *(p + 3) == ' ' )
{
if( !strncmp(p, lpszReplyCode, strlen(lpszReplyCode)) )
return 0;
else
{
int nErr = 1;
sscanf( p, "%d", &nErr );
return -nErr;
}
}
else
p = strtok( NULL, "\n" );
}
return -1;
}
// LogMessage - log messages to log file.
/////////////////////////////////////////////////////////////////
void LogMessage( LPCTSTR lpszMsg )
{
DWORD dwRet;
if( ghFile != INVALID_HANDLE_VALUE )
WriteFile( ghFile, lpszMsg, strlen(lpszMsg), &dwRet, NULL );
}
// End //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -