?? smtpprot.pas
字號:
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
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(Error : Word);
begin
if Assigned(FOnSessionConnected) then
FOnSessionConnected(Self, Error);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerSessionClosed(Error : Word);
begin
if Assigned(FOnSessionClosed) then
FOnSessionClosed(Self, Error);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerRequestDone(Error: Word);
begin
if not FRequestDoneFlag then begin
FRequestDoneFlag := TRUE;
if (Error = 0) and Assigned(FNextRequest) then begin
if FState <> smtpAbort then
StateChange(smtpInternalReady);
FNextRequest;
end
else begin
StateChange(smtpReady);
{ Restore the lastresponse saved before quit command }
if FHighLevelFlag and (FStatusCodeSave >= 0) then begin
FLastResponse := FLastResponseSave;
FStatusCode := FStatusCodeSave;
end;
FHighLevelFlag := FALSE;
PostMessage(Handle, WM_SMTP_REQUEST_DONE, 0, Error);
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.StateChange(NewState : TSmtpState);
begin
if FState <> NewState then begin
FState := NewState;
TriggerStateChange;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerDisplay(Msg : String);
begin
if Assigned(FOnDisplay) then
FOnDisplay(Self, Msg);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.DisplayLastResponse;
begin
TriggerDisplay('< ' + FLastResponse);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WSocketDataAvailable(Sender: TObject; Error: Word);
var
Len : Integer;
I : Integer;
p : PChar;
begin
Len := FWSocket.Receive(@FReceiveBuffer[FReceiveLen],
sizeof(FReceiveBuffer) - FReceiveLen);
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(Error);
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; Error: Word);
begin
{ Do not trigger the client SessionConnected from here. We must wait }
{ to have received the server banner. }
if Error <> 0 then begin
FLastResponse := '500 ' + WSocketErrorDesc(Error) +
' (Winsock error #' + IntToStr(Error) + ')';
FStatusCode := 500;
FConnected := FALSE;
SetErrorMessage;
TriggerRequestDone(Error);
FWSocket.Close;
StateChange(smtpReady);
end
else begin
FConnected := TRUE;
StateChange(smtpWaitingBanner);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WSocketDnsLookupDone(Sender: TObject; Error: Word);
begin
if Error <> 0 then begin
FLastResponse := '500 ' + WSocketErrorDesc(Error) +
' (Winsock error #' + IntToStr(Error) + ')';
FStatusCode := 500;
SetErrorMessage;
TriggerRequestDone(Error);
end
else begin
FWSocket.Addr := FWSocket.DnsResult;
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);
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
TriggerRequestDone(FRequestResult);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Helo;
begin
FFctPrv := smtpFctHelo;
if FSignOn = '' then
ExecAsync(smtpHelo, 'HELO ' + LocalHostName, [250], nil)
else
ExecAsync(smtpHelo, 'HELO ' + FSignOn, [250], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Vrfy;
begin
FFctPrv := smtpFctVrfy;
ExecAsync(smtpVrfy, 'VRFY ' + FHdrTo, [250], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.MailFrom;
begin
FFctPrv := smtpFctMailFrom;
if (Pos('<', FFromName) <> 0) and (Pos('>', FFromName) <> 0) then
ExecAsync(smtpMailFrom, 'MAIL FROM:' + Trim(FFromName), [250], nil)
else
ExecAsync(smtpMailFrom,
'MAIL FROM:<' + Trim(FFromName) + '>', [250], nil)
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Rset;
begin
FFctPrv := smtpFctRset;
ExecAsync(smtpRset, 'RSET', [250], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.RcptTo;
begin
if FRcptName.Count <= 0 then
raise SmtpException.Create('RcptName list is empty');
FItemCount := -1;
RcptToNext;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.RcptToNext;
var
WhenDone : TSmtpNextProc;
begin
Inc(FItemCount);
if FItemCount >= (FRcptName.Count - 1) then
WhenDone := nil
else
WhenDone := RcptToDone;
FFctPrv := smtpFctRcptTo;
if (Pos('<', FRcptName.Strings[FItemCount]) <> 0) and
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -