Unit SMTP

From Ultibo.org
Revision as of 06:24, 21 March 2017 by Ultibo (Talk | contribs)

Jump to: navigation, search

Return to Unit Reference


Description


Ultibo SMTP interface unit

To be documented

Constants



SMTP specific constants SMTP_*
SMTP_LINE_END = Chr(13) + Chr(10); CR LF
 
SMTP_BUFFER_SIZE = SIZE_4K;  


SMTP status constants SMTP_STATUS_*
SMTP_STATUS_NONE = 0;  
SMTP_STATUS_CONN = 1;  
SMTP_STATUS_HELO = 2;  
SMTP_STATUS_AUTH = 3;  
SMTP_STATUS_MAIL = 4;  
SMTP_STATUS_RCPT = 5;  
SMTP_STATUS_DATA = 6;  
SMTP_STATUS_QUIT = 7;  
 
SMTP_MAX_STATUS = 7;  


SMTP command constants SMTP_COMMAND_*
SMTP_COMMAND_HELO = 'HELO';  
SMTP_COMMAND_EHLO = 'EHLO';  
SMTP_COMMAND_TIME = 'TIME';  
SMTP_COMMAND_NOOP = 'NOOP';  
SMTP_COMMAND_AUTH = 'AUTH';  
SMTP_COMMAND_MAIL = 'MAIL';  
SMTP_COMMAND_RCPT = 'RCPT';  
SMTP_COMMAND_VRFY = 'VRFY';  
SMTP_COMMAND_BEGIN_DATA = 'DATA';  
SMTP_COMMAND_END_DATA = '.';  
SMTP_COMMAND_RSET = 'RSET';  
SMTP_COMMAND_QUIT = 'QUIT';  


SMTP sub command constants SMTP_SUB_COMMAND_*
SMTP_SUB_COMMAND_MAIL_FROM = 'FROM:';  
SMTP_SUB_COMMAND_RCPT_TO = 'TO:';  


SMTP string constants SMTP_STRING_*
SMTP_STRING_CONTINUE = '-';  
 
SMTP_STRING_CONN_SUCCESS = '220 ';  
SMTP_STRING_QUIT_SUCCESS = '221 ';  
SMTP_STRING_HELO_SUCCESS = '250 ';  
SMTP_STRING_EHLO_SUCCESS = '250 ';  
SMTP_STRING_TIME_SUCCESS = '250 ';  
SMTP_STRING_NOOP_SUCCESS = '250 ';  
SMTP_STRING_CONT_SUCCESS = '250-';  
SMTP_STRING_AUTH_SUCCESS = '235 ';  
SMTP_STRING_AUTH_CHALLENGE = '334 ';  
SMTP_STRING_MAIL_SUCCESS = '250 ';  
SMTP_STRING_RCPT_SUCCESS = '250 ';  
SMTP_STRING_VRFY_SUCCESS = '250 ';  
SMTP_STRING_BEGIN_DATA_SUCCESS = '354 ';  
SMTP_STRING_END_DATA_SUCCESS = '250 ';  
SMTP_STRING_RSET_SUCCESS = '250 ';  
 
SMTP_STRING_WRITE_FAILURE = '451 ';  
SMTP_STRING_COMMAND_FAILURE = '500 ';  
SMTP_STRING_SYNTAX_FAILURE = '501 ';  
SMTP_STRING_LOGON_FAILURE = '501 ';  
SMTP_STRING_SEQUENCE_FAILURE = '503 ';  
SMTP_STRING_AUTH_FAILURE = '504 ';  
SMTP_STRING_RCPT_FAILURE = '553 ';  
SMTP_STRING_VRFY_FAILURE = '550 ';  
SMTP_STRING_SIZE_FAILURE = '552 ';  
SMTP_STRING_FORWARD_FAILURE = '551 ';  
SMTP_STRING_PERMISSION_FAILURE = '571 ';  
 
SMTP_STRING_CONN_OK = 'Ultibo SMTP server (version ' + ULTIBO_RELEASE_VERSION + ')';  
SMTP_STRING_HELO_OK = 'Ultibo SMTP server - Hello, ';  
SMTP_STRING_EHLO_HEAD_OK = 'Ultibo SMTP server - Hello ';  
SMTP_STRING_EHLO_TAIL_OK = '; ESMTPs are: ';  
SMTP_STRING_AUTH_OK = 'Authenticated OK';  
SMTP_STRING_MAIL_OK = 'Sender OK - send RCPTs';  
SMTP_STRING_MAIL_SIZE_HEAD_OK = 'Sender and size (';  
SMTP_STRING_MAIL_SIZE_TAIL_OK = ') OK - send RCPTs';  
SMTP_STRING_RCPT_OK = 'Recipient OK - send RCPT or DATA';  
SMTP_STRING_VRFY_OK = 'OK - ';  
SMTP_STRING_BEGIN_DATA_OK = 'OK, send data, end with CRLF.CRLF';  
SMTP_STRING_END_DATA_OK = 'Data received OK';  
SMTP_STRING_RSET_OK = 'Command processed OK';  
SMTP_STRING_QUIT_OK = 'Ultibo SMTP server closing connection';  
SMTP_STRING_TIME_OK = 'Time is ';  
SMTP_STRING_NOOP_OK = 'OK';  
 
SMTP_STRING_BAD_COMMAND = 'Command unrecognized';  
SMTP_STRING_BAD_SYNTAX = 'Bad syntax in command';  
SMTP_STRING_BAD_SEQUENCE = 'Bad sequence of commands';  
SMTP_STRING_BAD_AUTH = 'Unrecognized authentication type';  
SMTP_STRING_BAD_LOGON = 'Authentication failed';  
SMTP_STRING_BAD_MAIL = 'Unknown sender';  
SMTP_STRING_BAD_RCPT = 'Unknown recipient';  
SMTP_STRING_BAD_VRFY = 'Mailbox not found';  


SMTP logging constants SMTP_LOG_*
SMTP_LOG_LEVEL_DEBUG = LOG_LEVEL_DEBUG; SMTP debugging messages
SMTP_LOG_LEVEL_INFO = LOG_LEVEL_INFO; SMTP informational messages
SMTP_LOG_LEVEL_ERROR = LOG_LEVEL_ERROR; SMTP error messages
SMTP_LOG_LEVEL_NONE = LOG_LEVEL_NONE; No SMTP messages


Type definitions



SMTP client notify event

TSMTPClientNotifyEvent = procedure(const ARequest:String) of Object;

SMTP host event

TSMTPHostEvent = function(AConnection:TSMTPConnection):Boolean of Object;

SMTP count event

TSMTPCountEvent = function(AConnection:TSMTPConnection):Boolean of Object;

SMTP notify event

TSMTPNotifyEvent = procedure(AConnection:TSMTPConnection; const ARequest:String) of Object;

SMTP request event

TSMTPRequestEvent = function(AConnection:TSMTPConnection; const ARequest:String; var AReply:String):Boolean of Object;

SMTP authenticate event

TSMTPAuthenticateEvent = function(AConnection:TSMTPConnection; const AMethod,AUsername,APassword:String; var AReply:String):Boolean of Object;

SMTP connection event

TSMTPConnectionEvent = procedure(AConnection:TSMTPConnection) of Object;


Class definitions



SMTP buffer

TSMTPBuffer = class(TObject)

public
constructor Create(ASize:LongWord);  
destructor Destroy; override;  
private
FLock:TCriticalSectionHandle;  
 
FData:Pointer;  
FSize:LongWord;  
FCount:LongWord;  
FStart:LongWord;  
 
function AcquireLock:Boolean;  
function ReleaseLock:Boolean;  
 
function GetCount:LongWord;  
public
property Count:LongWord read GetCount;  
 
function ReadData:Char;  
function WriteData(AChar:Char):Boolean;  
 
function WriteLock(var ASize:LongWord):Pointer;  
function WriteUnlock(ACount:LongWord):Boolean;  

SMTP client

TSMTPClient = class(TWinsock2TCPClient)

public
constructor Create;  
destructor Destroy; override;  
private
FOnRequest:TSMTPClientNotifyEvent;  
FOnReply:TSMTPClientNotifyEvent;  
 
FOnRequestStart:TNotifyEvent;  
FOnRequestEnd:TNotifyEvent;  
 
FAuthenticated:Boolean;  
FBuffer:TSMTPBuffer; Buffer for received data
protected
function GetReply(var AReply:String):Boolean;  
function SendRequest(const ARequest:String):Boolean;  
public
property OnRequest:TSMTPClientNotifyEvent read FOnRequest write FOnRequest;  
property OnReply:TSMTPClientNotifyEvent read FOnReply write FOnReply;  
 
property OnRequestStart:TNotifyEvent read FOnRequestStart write FOnRequestStart;  
property OnRequestEnd:TNotifyEvent read FOnRequestEnd write FOnRequestEnd;  
 
property Authenticated:Boolean read FAuthenticated;  
property Buffer:TSMTPBuffer read FBuffer;  
 
function DoConn(const AHost,APort:String; var AReply:String):Boolean;  
function DoHelo(const AHost:String; var AReply:String):Boolean;  
function DoEhlo(const AHost:String; var AReply:String):Boolean;  
function DoAuth(const AProtocol,AUsername,APassword:String; var AReply:String):Boolean;  
function DoMail(const ASender:String; var AReply:String):Boolean;  
function DoRcpt(const AReceiver:String; var AReply:String):Boolean;  
function DoVrfy(const AAddress:String; var AReply:String):Boolean;  
function DoBeginData(var AReply:String):Boolean;  
function DoSendData(const AData:String):Boolean;  
function DoEndData(var AReply:String):Boolean;  
function DoQuit(var AReply:String):Boolean;  
function DoRset(var AReply:String):Boolean;  
function DoTime(var AReply:String):Boolean;  
function DoNoop(var AReply:String):Boolean;  

SMTP connection

TSMTPConnection = class(TListObject)

public
constructor Create;  
destructor Destroy; override;  
private
FLock:TCriticalSectionHandle;  
 
FHandle:LongWord;  
FRxByteCount:Int64; Bytes Recv Count from Connection
FTxByteCount:Int64; Bytes Sent Count to Connection
FRequestCount:Int64; Requests Recv Count from Connection
FReplyCount:Int64; Replies Sent Count to Connection
FRequestTime:TDateTime; Last Request Time
FReplyTime:TDateTime; Last Reply Time
FRemoteAddress:String; Address of Remote Client
FStatus:LongWord; None,Conn,Auth,Helo,Mail,Rcpt,Data etc
 
FAuthenticated:Boolean; Current authentication state
FUsername:String; Current Username
FPassword:String; Current Password
 
FThread:TThread; TWinsock2TCPServerThread
FBuffer:TSMTPBuffer; Buffer for received data
 
function AcquireLock:Boolean;  
function ReleaseLock:Boolean;  
 
procedure SetHandle(AHandle:LongWord);  
function GetRxByteCount:Int64;  
procedure SetRxByteCount(const ARxByteCount:Int64);  
function GetTxByteCount:Int64;  
procedure SetTxByteCount(const ATxByteCount:Int64);  
function GetRequestCount:Int64;  
procedure SetRequestCount(const ARequestCount:Int64);  
function GetReplyCount:Int64;  
procedure SetReplyCount(const AReplyCount:Int64);  
function GetRequestTime:TDateTime;  
procedure SetRequestTime(const ARequestTime:TDateTime);  
function GetReplyTime:TDateTime;  
procedure SetReplyTime(const AReplyTime:TDateTime);  
function GetRemoteAddress:String;  
procedure SetRemoteAddress(const ARemoteAddress:String);  
procedure SetStatus(AStatus:LongWord);  
 
procedure SetAuthenticated(AAuthenticated:Boolean);  
function GetUsername:String;  
procedure SetUsername(const AUsername:String);  
function GetPassword:String;  
procedure SetPassword(const APassword:String);  
 
procedure SetThread(AThread:TThread);  
public
property Handle:LongWord read FHandle write SetHandle;  
property RxByteCount:Int64 read GetRxByteCount write SetRxByteCount;  
property TxByteCount:Int64 read GetTxByteCount write SetTxByteCount;  
property RequestCount:Int64 read GetRequestCount write SetRequestCount;  
property ReplyCount:Int64 read GetReplyCount write SetReplyCount;  
property RequestTime:TDateTime read GetRequestTime write SetRequestTime;  
property ReplyTime:TDateTime read GetReplyTime write SetReplyTime;  
property RemoteAddress:String read GetRemoteAddress write SetRemoteAddress;  
property Status:LongWord read FStatus write SetStatus;  
 
property Authenticated:Boolean read FAuthenticated write SetAuthenticated;  
property Username:String read GetUsername write SetUsername;  
property Password:String read GetPassword write SetPassword;  
 
property Thread:TThread read FThread write SetThread;  
property Buffer:TSMTPBuffer read FBuffer;  
 
procedure IncrementRxByteCount(const ARxByteCount:Int64);  
procedure IncrementTxByteCount(const ATxByteCount:Int64);  
procedure IncrementRequestCount;  
procedure IncrementReplyCount;  

SMTP listener

TSMTPListener = class(TWinsock2TCPListener)

public
constructor Create;  
private
FOnConnected:TSMTPConnectionEvent;  
FOnDisconnected:TSMTPConnectionEvent;  
 
FOnCheckHost:TSMTPHostEvent;  
FOnCheckCount:TSMTPCountEvent;  
 
FOnRequest:TSMTPNotifyEvent;  
FOnReply:TSMTPNotifyEvent;  
 
FOnConn:TSMTPRequestEvent;  
FOnHelo:TSMTPRequestEvent;  
FOnEhlo:TSMTPRequestEvent;  
FOnAuth:TSMTPAuthenticateEvent;  
FOnMail:TSMTPRequestEvent;  
FOnRcpt:TSMTPRequestEvent;  
FOnVrfy:TSMTPRequestEvent;  
FOnBeginData:TSMTPRequestEvent;  
FOnData:TSMTPRequestEvent;  
FOnEndData:TSMTPRequestEvent;  
FOnQuit:TSMTPRequestEvent;  
FOnRset:TSMTPRequestEvent;  
FOnTime:TSMTPRequestEvent;  
FOnNoop:TSMTPRequestEvent;  
protected
procedure DoConnect(AThread:TWinsock2TCPServerThread); override;  
procedure DoDisconnect(AThread:TWinsock2TCPServerThread); override;  
 
function DoCheckHost(AThread:TWinsock2TCPServerThread):Boolean; virtual;  
function DoCheckCount(AThread:TWinsock2TCPServerThread):Boolean; virtual;  
 
function DoExecute(AThread:TWinsock2TCPServerThread):Boolean; override;  
 
procedure DoConn(AThread:TWinsock2TCPServerThread);  
procedure DoHelo(AThread:TWinsock2TCPServerThread; const AHost:String);  
procedure DoEhlo(AThread:TWinsock2TCPServerThread; const AHost:String);  
procedure DoAuth(AThread:TWinsock2TCPServerThread; const AParams:String);  
procedure DoMail(AThread:TWinsock2TCPServerThread; const ASender:String);  
procedure DoRcpt(AThread:TWinsock2TCPServerThread; const ARecipient:String);  
procedure DoVrfy(AThread:TWinsock2TCPServerThread; const AAddress:String);  
procedure DoBeginData(AThread:TWinsock2TCPServerThread);  
procedure DoData(AThread:TWinsock2TCPServerThread; const AData:String);  
procedure DoEndData(AThread:TWinsock2TCPServerThread);  
procedure DoQuit(AThread:TWinsock2TCPServerThread);  
procedure DoRset(AThread:TWinsock2TCPServerThread);  
procedure DoTime(AThread:TWinsock2TCPServerThread);  
procedure DoNoop(AThread:TWinsock2TCPServerThread);  
 
function GetRequest(AThread:TWinsock2TCPServerThread;var ARequest:String):Boolean;  
function SendReply(AThread:TWinsock2TCPServerThread;const AReply:String):Boolean;  
public
property OnConnected:TSMTPConnectionEvent read FOnConnected write FOnConnected;  
property OnDisconnected:TSMTPConnectionEvent read FOnDisconnected write FOnDisconnected;  
 
property OnCheckHost:TSMTPHostEvent read FOnCheckHost write FOnCheckHost;  
property OnCheckCount:TSMTPCountEvent read FOnCheckCount write FOnCheckCount;  
 
property OnRequest:TSMTPNotifyEvent read FOnRequest write FOnRequest;  
property OnReply:TSMTPNotifyEvent read FOnReply write FOnReply;  
 
property OnConn:TSMTPRequestEvent read FOnConn write FOnConn;  
property OnHelo:TSMTPRequestEvent read FOnHelo write FOnHelo;  
property OnEhlo:TSMTPRequestEvent read FOnEhlo write FOnEhlo;  
property OnAuth:TSMTPAuthenticateEvent read FOnAuth write FOnAuth;  
property OnMail:TSMTPRequestEvent read FOnMail write FOnMail;  
property OnRcpt:TSMTPRequestEvent read FOnRcpt write FOnRcpt;  
property OnVrfy:TSMTPRequestEvent read FOnVrfy write FOnVrfy;  
property OnBeginData:TSMTPRequestEvent read FOnBeginData write FOnBeginData;  
property OnData:TSMTPRequestEvent read FOnData write FOnData;  
property OnEndData:TSMTPRequestEvent read FOnEndData write FOnEndData;  
property OnQuit:TSMTPRequestEvent read FOnQuit write FOnQuit;  
property OnRset:TSMTPRequestEvent read FOnRset write FOnRset;  
property OnTime:TSMTPRequestEvent read FOnTime write FOnTime;  
property OnNoop:TSMTPRequestEvent read FOnNoop write FOnNoop;  


Public variables



SMTP logging

SMTP_DEFAULT_LOG_LEVEL:LongWord = SMTP_LOG_LEVEL_DEBUG; Minimum level for SMTP messages. Only messages with level greater than or equal to this will be printed.
SMTP_LOG_ENABLED:Boolean;


Function declarations



Initialization functions

procedure SMTPInit;
Description: To be documented
Note None documented


SMTP helper functions

procedure SMTPLog(Level:LongWord; const AText:String);
Description: To be documented
Note None documented


procedure SMTPLogInfo(const AText:String);
Description: To be documented
Note None documented


procedure SMTPLogError(const AText:String);
Description: To be documented
Note None documented


procedure SMTPLogDebug(const AText:String);
Description: To be documented
Note None documented


Return to Unit Reference