📄 smtpprot.pas
字号:
function Base64Encode(Input : String) : String;
var
Final : String;
Count : Integer;
Len : Integer;
begin
Final := '';
Count := 1;
Len := Length(Input);
while Count <= Len do begin
Final := Final + Base64Out[(Byte(Input[Count]) and $FC) shr 2];
if (Count + 1) <= Len then begin
Final := Final + Base64Out[((Byte(Input[Count]) and $03) shl 4) +
((Byte(Input[Count+1]) and $F0) shr 4)];
if (Count+2) <= Len then begin
Final := Final + Base64Out[((Byte(Input[Count+1]) and $0F) shl 2) +
((Byte(Input[Count+2]) and $C0) shr 6)];
Final := Final + Base64Out[(Byte(Input[Count+2]) and $3F)];
end
else begin
Final := Final + Base64Out[(Byte(Input[Count+1]) and $0F) shl 2];
Final := Final + '=';
end
end
else begin
Final := Final + Base64Out[(Byte(Input[Count]) and $03) shl 4];
Final := Final + '==';
end;
Count := Count + 3;
end;
Result := Final;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function Base64Decode(Input : String) : String;
var
Final : String;
Count : Integer;
Len : Integer;
DataIn0 : Byte;
DataIn1 : Byte;
DataIn2 : Byte;
DataIn3 : Byte;
begin
Final := '';
Count := 1;
Len := Length(Input);
while Count <= Len do begin
DataIn0 := Base64In[Byte(Input[Count])];
DataIn1 := Base64In[Byte(Input[Count+1])];
DataIn2 := Base64In[Byte(Input[Count+2])];
DataIn3 := Base64In[Byte(Input[Count+3])];
Final := Final + Char(((DataIn0 and $3F) shl 2) +
((DataIn1 and $30) shr 4));
if DataIn2 <> $40 then begin
Final := Final + Char(((DataIn1 and $0F) shl 4) +
((DataIn2 and $3C) shr 2));
if DataIn3 <> $40 then
Final := Final + Char(((DataIn2 and $03) shl 6) +
(DataIn3 and $3F));
end;
Count := Count + 4;
end;
Result := Final;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{$I+} { Activate I/O check (EInOutError exception generated) }
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.InitUUEncode(var hFile: File; sFile: string);
var
OldFileMode : Byte;
begin
AssignFile(hFile, sFile);
OldFileMode := FileMode;
FileMode := 0; { Force readonly }
try
Reset(hFile, 1);
finally
FileMode := OldFileMode;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.DoUUEncode(var hFile: File; var sLine: string; var More: boolean);
var
Count : integer;
DataIn : array [0..2] of byte;
DataOut : array [0..80] of byte;
ByteCount : integer;
i : integer;
begin
Count := 0;
{$I-}
while not Eof(hFile) do begin
{$I+}
BlockRead(hFile, DataIn, 3, ByteCount);
DataOut[Count] := (DataIn[0] and $FC) shr 2;
DataOut[Count + 1] := (DataIn[0] and $03) shl 4;
if ByteCount > 1 then begin
DataOut[Count + 1] := DataOut[Count + 1] +
(DataIn[1] and $F0) shr 4;
DataOut[Count + 2] := (DataIn[1] and $0F) shl 2;
if ByteCount > 2 then begin
DataOut[Count + 2] := DataOut[Count + 2] +
(DataIn[2] and $C0) shr 6;
DataOut[Count + 3] := (DataIn[2] and $3F);
end
else begin
DataOut[Count + 3] := $40;
end;
end
else begin
DataOut[Count + 2] := $40;
DataOut[Count + 3] := $40;
end;
for i := 0 to 3 do
DataOut[Count + i] := Byte(Base64Out[DataOut[Count + i]]);
Count := Count + 4;
if Count > 59 then
break;
end;
DataOut[Count] := $0;
sLine := StrPas(@DataOut[0]);
{$I-}
More := not Eof(hFile);
{$I+}
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.EndUUEncode(var hFile: File);
begin
CloseFile(hFile);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{$IFDEF NOFORMS}
{ This function is a callback function. It means that it is called by }
{ windows. This is the very low level message handler procedure setup to }
{ handle the message sent by windows (winsock) to handle messages. }
function SmtpClientWindowProc(
ahWnd : HWND;
auMsg : Integer;
awParam : WPARAM;
alParam : LPARAM): Integer; stdcall;
var
Obj : TObject;
MsgRec : TMessage;
begin
{ At window creation asked windows to store a pointer to our object }
Obj := TObject(GetWindowLong(ahWnd, 0));
{ If the pointer doesn't represent a TCustomSmtpClient, just call the default procedure}
if not (Obj is TCustomSmtpClient) then
Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
else begin
{ Delphi use a TMessage type to pass parameter to his own kind of }
{ windows procedure. So we are doing the same... }
MsgRec.Msg := auMsg;
MsgRec.wParam := awParam;
MsgRec.lParam := alParam;
{ May be a try/except around next line is needed. Not sure ! }
TCustomSmtpClient(Obj).WndProc(MsgRec);
Result := MsgRec.Result;
end;
end;
{$ENDIF}
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TCustomSmtpClient.SmtpClientAllocateHWnd(Method: TWndMethod) : HWND;
begin
{$IFDEF NOFORMS}
Result := XSocketAllocateHWnd(Self);
SetWindowLong(Result, GWL_WNDPROC, LongInt(@SmtpClientWindowProc));
{$ELSE}
Result := WSocket.AllocateHWnd(Method);
{$ENDIF}
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.SmtpClientDeallocateHWnd(WHandle : HWND);
begin
{$IFDEF NOFORMS}
XSocketDeallocateHWnd(WHandle);
{$ELSE}
WSocket.DeallocateHWnd(WHandle);
{$ENDIF}
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
constructor TCustomSmtpClient.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
FWindowHandle := SmtpClientAllocateHWnd(WndProc);
FWSocket := TWSocket.Create(nil);
FWSocket.OnSessionClosed := WSocketSessionClosed;
FState := smtpReady;
FRcptName := TStringList.Create;
FMailMessage := TStringList.Create;
FPort := 'smtp';
FCharSet := 'iso-8859-1';
FAuthType := smtpAuthNone;
FLocalAddr := '0.0.0.0'; {bb}
SetContentType(smtpPlainText);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
destructor TCustomSmtpClient.Destroy;
begin
if Assigned(FWSocket) then begin
FWSocket.Destroy;
FWSocket := nil;
end;
if Assigned(FHdrLines) then begin
FHdrLines.Destroy;
FHdrLines := nil;
end;
FMailMessage.Destroy;
FRcptName.Destroy;
SmtpClientDeallocateHWnd(FWindowHandle);
inherited Destroy;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WndProc(var MsgRec: TMessage);
begin
with MsgRec do begin
case Msg of
WM_SMTP_REQUEST_DONE : WMSmtpRequestDone(MsgRec);
else
Result := DefWindowProc(Handle, Msg, wParam, lParam);
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WMSmtpRequestDone(var msg: TMessage);
begin
if Assigned(FOnRequestDone) then
FOnRequestDone(Self, FRequestType, Msg.LParam);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function GetInteger(Data : PChar; var Number : Integer) : PChar;
var
bSign : Boolean;
begin
Number := 0;
Result := StpBlk(Data);
if (Result = nil) then
Exit;
{ Remember the sign }
if Result^ in ['-', '+'] then begin
bSign := (Result^ = '-');
Inc(Result);
end
else
bSign := FALSE;
{ Convert any number }
while (Result^ <> #0) and (Result^ in ['0'..'9']) do begin
Number := Number * 10 + ord(Result^) - ord('0');
Inc(Result);
end;
{ Correct for sign }
if bSign then
Number := -Number;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.CheckReady;
begin
if not (FState in [smtpReady, smtpInternalReady]) then
raise SmtpException.Create('SMTP component not ready');
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerStateChange;
begin
if Assigned(FOnStateChange) then
FOnStateChange(Self);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerSessionConnected(ErrorCode : Word);
begin
if Assigned(FOnSessionConnected) then
FOnSessionConnected(Self, ErrorCode);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerSessionClosed(ErrorCode : Word);
begin
if Assigned(FOnSessionClosed) then
FOnSessionClosed(Self, ErrorCode);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -