/* WSMTPSrv.C - Windows SMTP Server V1.40a - WinSock 1.1 required * Handles multiple clients at one time for reliable and quick mail service. * Uses the Windows Sockets API for wide useability. Author: Ian Blenke Date: May 23, 1993 v1.30a June 24, 1993 8BITMIME capable. v1.40a June 28, 1993 Unlimited connection capability. Cleaner code. Linked lists. More bugs destroyed. */ #ifndef WSMTPSRV_H #define WSMTPSRV_H #include #include #include #include "WinSock.h" #include "Ctl3d.h" #include "Dialogs.h" #include "Net.h" #define USE_3D /**/// Uncomment this for 3d Dialog feel /*#define USE_TITLE /**/// Uncomment this for Dialog title // bytes sent/received debugging #define APP_NAME "WSMTPSRV" #define CLASS_NETWORK "SMTPClass" #define WSVERSION 0x101 #define DEFAULTMAILFILE "c:\\mail.txt" #define MAXLINE 128 #define MAXFILENAME 144 #define MAXSNDBUFF 2048 // I don't think this app will EVER need // this much of a Sending buffer. #define MAXITEMS 1000 // Limit the listbox size #define MAXCLIENTS 10 // Up this number if you need more #define INI_FILE "wsmtpsrv.ini" #define TIME_CHECK 30000 // 30000ms==30 seconds #define ID_TIMER 2600 // Misc. timer handle ;) // Miscellanous String Defines #define STRING_PREFIX "WSMTP" #define STRING_UNKNOWN "Unknown System" #define STRING_NOMAIL "WSMTPD v1.61" #define STRING_HAVEMAIL "WSMTPD v1.61 - Mail!" #define SECTION_MAIN "WinSMTPSrv" #define ENTRY_DEBUG "Debug" #define ENTRY_MAILPATH "Mail" // A server connection can be in 2 "states" #define STATE_WAIT_FOR_COMMAND 0 #define STATE_WAIT_FOR_DOT 1 // Extended SMTP flag values #define ESMTP_NONE 0 #define ESMTP_EHLO_USED 1 #define ESMTP_8BITMIME 2 #define ESMTP_SIZE 4 // Level of reporting #define LOG_LOW 0 #define LOG_MEDIUM 1 #define LOG_HIGH 2 #define LOG_TIME 8 // Use Time with the log entry /* SMTP Command structure - For easy parsing */ typedef struct { PSTR SMTPCommand; WORD SMTPCode; // Tokens for this field are in "Dialogs.h" } SMTPCODE; /* Odd hack to keep "phase" debug strings static */ typedef const PSTR PHASESTRING; /* For Vanities sake */ typedef HANDLE HCLIENT; /* Client structure for multiple connections */ /* All state flags/variables should be stored in here */ typedef struct tagSMTPCLIENT { SOCKET sSocket; // Socket handle of the connection HCLIENT hClient; // Handle to "this" client link SOCKADDR_IN saPeer; // Peer name char szPeer[MAXLINE]; // Room for the peer name HFILE hfFile; // Handle for the open .TMP file char szFile[MAXFILENAME]; // .TMP filename per message char szFrom[MAXLINE]; // Room for the Sender's ID char szTo[MAXLINE]; // Room for the Recipient's ID BOOL bHaveFrom; // Only let id sender once/message int iMessageType; // MAIL/SEND/SAML/SOML? BOOL iState; // SMTP State (2 states, 0 and 1) int iExtendedFlags; // ESMTP flags /* We need buffers to talk with - unique ones at that */ HANDLE hOutputBuffer; // Handle to output FIFO buffer LPSTR lpOutputBuffer; // FIFO buffer for output int fifoOutputStart; // Start of buffer where valid int fifoOutputStop; // End of buffer where valid int iInputSize; // Size of FIFO buffer for input HANDLE hInputBuffer; // Handle to input FIFO buffer LPSTR lpInputBuffer; // FIFO buffer for input int fifoInputStart; // Start of buffer where valid int fifoInputStop; // End of buffer where valid struct tagSMTPCLIENT FAR *lpPrevClient; // Link to previous client struct struct tagSMTPCLIENT FAR *lpNextClient; // Link to next client struct } SMTPCLIENT; /* estimated size per structure: 2+2+4+128+2+144+128+128+2+2+2+2+2+4+2+2+2+2+4+2+2+4+4 == 578 bytes/client Not including the separate buffers for each FIFO! Know the real bummer? As long as the socket remains open, the memory used for the buffers remain locked. Lets just hope noone makes a client that doesn't close connection and repetively re-connects. Can you say "Your Doctor Watson log is getting quite large"? */ typedef SMTPCLIENT FAR *LPSMTPCLIENT; /* GLOBALS */ LPSMTPCLIENT smtpClientsHead; // Head of Client's linked list /* Clients array for future multiple clients at a time support */ /* The SMTP Command Code lookup table */ /* Just keep adding in those new ones */ static SMTPCODE smtpCodesTable[] = { {"helo", CMDHELO}, /* helo -- be polite */ {"ehlo", CMDEHLO}, /* ehlo -- extended SMTP */ {"verb", CMDVERB}, /* onex -- sending one transaction only */ {"onex", CMDONEX}, /* verb -- go into verbose mode */ {"mult", CMDMULT}, /* mult -- multiple message query */ {"mail", CMDMAIL}, /* mail -- designate sender */ {"rcpt", CMDRCPT}, /* rcpt -- designate recipient */ {"data", CMDDATA}, /* data -- send message text */ {"rset", CMDRSET}, /* rset -- reset state */ {"vrfy", CMDVRFY}, /* vrfy -- verify address */ {"expn", CMDVRFY}, /* expn -- verify address */ {"help", CMDHELP}, /* help -- give usage info */ {"noop", CMDNOOP}, /* noop -- do nothing */ {"quit", CMDQUIT}, /* quit -- close connection and die */ {"tick", CMDTICK}, /* tick -- batch SMTP sync command */ {"turn", CMDTURN}, /* turn -- switch places */ {"send", CMDSEND}, /* send -- send message to screen */ {"saml", CMDSAML}, /* saml -- send AND mail */ {"soml", CMDSOML}, /* soml -- send OR mail */ /* * Implementation specific extensions. */ {"xwin3", CMDXWIN3}, /* xwin3 -- tell me you are a Win3 client */ /* * remaining commands are here only * to trap and log attempts to use them * And to laugh at the poor soul who does. */ {"showq", CMDDBGQSHOW},/* showq -- show send queue */ {"debug", CMDDBGDEBUG},/* debug -- set debug mode */ {(PSTR)NULL, CMDERROR} /* bad command */ }; #ifndef NET_C HINSTANCE hInst; int iLogLevel = LOG_LOW; extern BOOL bMailArrived; BOOL bConnectionQuit; #else BOOL bMailArrived = FALSE; // Icon Flag! extern int iLogLevel; extern HINSTANCE hInst; #endif // NET_C /* The main Dialog globals */ char szLocalHostName[MAXLINE]; OPENFILENAME ofnMailPath; static char szMailPathFilter[MAXLINE]; static char szLocalMailPath[MAXFILENAME]; char szAppName[40]; int iMaxSndBuf; // Maximum send buffer size int iMaxRcvBuf; // Maximum receive buffer size HWND hWndDlg; // Main dialog window HWND hWndMain; // Main "network" window /* PROTOTYPES */ UINT PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int); LRESULT CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK IconWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM); void smtpError(int, ...); void smtpLog(int, ...); BOOL smtpInit(PSTR); BOOL smtpServer(LPSMTPCLIENT); BOOL smtpParser(LPSMTPCLIENT, int, LPSTR); LPSMTPCLIENT smtpSocketToClient(SOCKET); void smtpAppendToFile(LPSMTPCLIENT, LPSTR, LPSTR); BOOL smtpDisplayFile(LPSMTPCLIENT, LPSTR); LPSTR smtpSkipWord(LPSMTPCLIENT, LPSTR, LPSTR); void smtpSendHelp(LPSMTPCLIENT, LPSTR); void smtpMakeHeader(LPSMTPCLIENT, HFILE, LPSTR, LPSTR, LPSTR); LPSMTPCLIENT smtpAddClient(SOCKET); BOOL smtpDestroyClient(LPSMTPCLIENT); BOOL smtpMailCheck(LPSTR); void smtpSendMessage(LPSMTPCLIENT, int, int, ...); int clientSendLine(LPSMTPCLIENT, LPSTR, int); int clientReceiveLine(LPSMTPCLIENT, LPSTR, int); int clientReceiveBlock(LPSMTPCLIENT, LPSTR, int); #endif /* WSMTPSRV_H */