📄 smtpprot.pas
字号:
if Len <= 0 then
Exit;
FReceiveBuffer[FReceiveLen + Len] := #0;
FReceiveLen := FReceiveLen + Len;
while FReceiveLen > 0 do begin
I := Pos(#13#10, FReceiveBuffer);
if I <= 0 then
break;
if I > FReceiveLen then
break;
FLastResponse := Copy(FReceiveBuffer, 1, I - 1);
TriggerResponse(FLastResponse);
{$IFDEF DUMP}
FDumpBuf := '>|';
FDumpStream.WriteBuffer(FDumpBuf[1], Length(FDumpBuf));
FDumpStream.WriteBuffer(FLastResponse[1], Length(FLastResponse));
FDumpBuf := '|' + #13#10;
FDumpStream.WriteBuffer(FDumpBuf[1], Length(FDumpBuf));
{$ENDIF}
{$IFDEF VER80}
{ Add a nul byte at the end of string for Delphi 1 }
FLastResponse[Length(FLastResponse) + 1] := #0;
{$ENDIF}
FReceiveLen := FReceiveLen - I - 1;
if FReceiveLen > 0 then
Move(FReceiveBuffer[I + 1], FReceiveBuffer[0], FReceiveLen + 1);
if FState = smtpWaitingBanner then begin
DisplayLastResponse;
p := GetInteger(@FLastResponse[1], FStatusCode);
if p^ = '-' then
Continue; { Continuation line, ignore }
if FStatusCode <> 220 then begin
SetErrorMessage;
FRequestResult := FStatusCode;
FWSocket.Close;
Exit;
end;
StateChange(smtpConnected);
TriggerSessionConnected(ErrorCode);
if Assigned(FWhenConnected) then
FWhenConnected
else begin
TriggerRequestDone(0);
end;
end
else if FState = smtpWaitingResponse then begin
if Assigned(FNext) then
FNext
else
raise SmtpException.Create('Program error: FNext is nil');
end
else begin
{ Unexpected data received }
DisplayLastResponse;
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WSocketSessionConnected(Sender: TObject; ErrorCode: Word);
begin
{ Do not trigger the client SessionConnected from here. We must wait }
{ to have received the server banner. }
if ErrorCode <> 0 then begin
FLastResponse := '500 ' + WSocketErrorDesc(ErrorCode) +
' (Winsock error #' + IntToStr(ErrorCode) + ')';
FStatusCode := 500;
FConnected := FALSE;
{ --Jake Traynham, 06/12/01 Bug - Need to set FRequestResult so High }
{ Level Open will exit out. (See also }
{ TriggerRequestDone bug.) }
FRequestResult:= 500;
SetErrorMessage;
TriggerRequestDone(ErrorCode);
FWSocket.Close;
StateChange(smtpReady);
end
else begin
FConnected := TRUE;
StateChange(smtpWaitingBanner);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WSocketDnsLookupDone(
Sender : TObject;
ErrorCode : Word);
begin
if ErrorCode <> 0 then begin
FLastResponse := '500 ' + WSocketErrorDesc(ErrorCode) +
' (Winsock error #' + IntToStr(ErrorCode) + ')';
FStatusCode := 500;
SetErrorMessage;
FRequestResult := ErrorCode;
TriggerSessionConnected(ErrorCode); { 07/09/03 }
TriggerSessionClosed(ErrorCode); { 07/09/03 }
TriggerRequestDone(ErrorCode);
end
else begin
FWSocket.Addr := FWSocket.DnsResult;
FWSocket.LocalAddr := FLocalAddr; {bb}
FWSocket.Proto := 'tcp';
FWSocket.Port := FPort;
FWSocket.OnSessionConnected := WSocketSessionConnected;
FWSocket.OnDataAvailable := WSocketDataAvailable;
StateChange(smtpConnecting);
try
FWSocket.Connect;
except
on E:Exception do begin
FLastResponse := '500 ' + E.ClassName + ': ' + E.Message;
FStatusCode := 500;
FRequestResult := FStatusCode;
SetErrorMessage;
{ TriggerRequestDone(FStatusCode); }
TriggerRequestDone(FWSocket.LastError); { Apr 01, 2002 }
end;
end
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.SendCommand(Cmd : String);
begin
TriggerCommand(Cmd);
TriggerDisplay('> ' + Cmd);
if FWSocket.State = wsConnected then
FWSocket.SendStr(Cmd + #13 + #10);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.ExecAsync(
RqType : TSmtpRequest;
Cmd : String; { Command to execute }
OkResponses : array of Word; { List of responses like '200 221 342' }
DoneAsync : TSmtpNextProc); { What to do when done }
var
I : Integer;
begin
CheckReady;
if not FConnected then
raise SmtpException.Create('SMTP component not connected');
if not FHighLevelFlag then
FRequestType := RqType;
for I := 0 to High(OkResponses) do
FOkResponses[I] := OkResponses[I];
FOkResponses[High(OkResponses) + 1] := 0;
FRequestDoneFlag := FALSE;
FNext := NextExecAsync;
FDoneAsync := DoneAsync;
StateChange(smtpWaitingResponse);
SendCommand(Cmd);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.NextExecAsync;
var
I : Integer;
p : PChar;
begin
DisplayLastResponse;
p := GetInteger(@FLastResponse[1], FStatusCode);
if p^ = '-' then
Exit; { Continuation line, nothing to do }
if FOkResponses[0] = 0 then begin
{ The list of ok responses is empty }
if FStatusCode >= 500 then begin
{ Not a good response }
FRequestResult := FStatusCode;
SetErrorMessage;
end
else
FRequestResult := 0;
end
else begin
{ We have a list of ok response codes }
for I := 0 to High(FOkResponses) do begin
if FOkResponses[I] = 0 then begin
{ No good response found }
FRequestResult := FStatusCode;
SetErrorMessage;
break;
end;
if FOkResponses[I] = FStatusCode then begin
{ Good response found }
FRequestResult := 0;
Break;
end;
end;
end;
if Assigned(FDoneAsync) then
FDoneAsync
else if (FRequestType <> smtpQuit) or (FConnected = FALSE) then
TriggerRequestDone(FRequestResult)
else begin
{ We have to wait until remote host close connection before }
{ calling TriggerRequestDone. See WSocketSessionClosed. }
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Helo;
var
I : Integer;
Buf : String;
begin
FFctPrv := smtpFctHelo;
if FSignOn = '' then
Buf := LocalHostName
else
Buf := FSignOn;
{ Replace any space by underscore }
for I := 1 to Length(Buf) do begin
if Buf[I] = ' ' then
Buf[I] := '_';
end;
ExecAsync(smtpHelo, 'HELO ' + Buf, [250], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Ehlo;
var
I : Integer;
Buf : String;
begin
FAuthTypesSupported.Clear;
FFctPrv := smtpFctEhlo;
if FSignOn = '' then
Buf := LocalHostName
else
Buf := FSignOn;
{ Replace any space by underscore }
for I := 1 to Length(Buf) do begin
if Buf[I] = ' ' then
Buf[I] := '_';
end;
ExecAsync(smtpEhlo, 'EHLO ' + Buf, [250], EhloNext);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.EhloNext;
begin
{ It's possible that some really old mail servers will disconnect you }
{ if you use the 'EHLO' command. If we've been disconnected, then do }
{ nothing. RequestDone event handler is called from socket }
{ SessionClose event. }
if not FConnected
then Exit;
if (FRequestResult = 0)
then FESmtpSupported := TRUE;
TriggerRequestDone(FRequestResult);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.DoAuthPlain;
var
AuthPlain : String;
begin
AuthPlain := FUserName;
AuthPlain := AuthPlain + #0;
if FFromName <> '' then { FromName should be set before calling Auth }
AuthPlain := AuthPlain + FFromName
else
AuthPlain := AuthPlain + FUserName;
AuthPlain := AuthPlain + #0;
AuthPlain := AuthPlain + FPassword;
AuthPlain := Base64Encode(A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -