📄 smtpprot.pas
字号:
(Pos('>', FRcptName.Strings[FItemCount]) <> 0) then
ExecAsync(smtpRcptTo,
'RCPT TO:' + Trim(FRcptName.Strings[FItemCount]),
[250, 251], WhenDone)
else
ExecAsync(smtpRcptTo,
'RCPT TO:<' + Trim(FRcptName.Strings[FItemCount])+ '>',
[250, 251], WhenDone);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.RcptToDone;
begin
FState := smtpInternalReady;
RcptToNext;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.SetContentType(newValue : TSmtpContentType);
begin
if FContentType = newValue then
Exit;
FContentType := newValue;
if FContentType = smtpPlainText then
FContentTypeStr := 'text/plain'
else
FContentTypeStr := 'text/html';
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Data;
begin
FLineNum := 0;
FMoreLines := TRUE;
FItemCount := -1;
if not Assigned(FHdrLines) then
FHdrLines := TStringList.Create
else
FHdrLines.Clear;
if Length(Trim(FHdrReplyTo)) > 0 then
FHdrLines.Add('Reply-To: ' + FHdrReplyTo);
if Length(Trim(FHdrReturnPath)) > 0 then
FHdrLines.Add('Return-Path: ' + FHdrReturnPath);
FHdrLines.Add('From: ' + FHdrFrom);
FHdrLines.Add('To: ' + FHdrTo);
FHdrLines.Add('Subject: ' + FHdrSubject);
if Length(Trim(FHdrSender)) > 0 then
FHdrLines.Add('Sender: ' + FHdrSender)
else if Length(Trim(FHdrFrom)) > 0 then
FHdrLines.Add('Sender: ' + FHdrFrom);
FHdrLines.Add('Mime-Version: 1.0');
FHdrLines.Add('Content-Type: ' + FContentTypeStr + '; charset="' + FCharSet + '"');
FHdrLines.Add('Date: ' + Rfc822DateTime(Now));
TriggerProcessHeader(FHdrLines);
{ An empty line mark the header's end }
FHdrLines.Add('');
FFctPrv := smtpFctData;
ExecAsync(smtpData, 'DATA', [354], DataNext);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.DataNext;
var
MsgLine : array [0..1023] of char;
begin
{ If we have been disconnected, then do nothing. }
{ RequestDone event handler is called from socket SessionClose event. }
if not FConnected then begin
FWSocket.OnDataSent := nil;
Exit;
end;
Inc(FItemCount);
if FItemCount < FHdrLines.Count then begin
{ There are still header lines to send }
StrPCopy(@MsgLine, FHdrLines.Strings[FItemCount]);
TriggerHeaderLine(@MsgLine, SizeOf(MsgLine));
TriggerDisplay('> ' + StrPas(MsgLine));
FWSocket.OnDataSent := WSocketDataSent;
FWSocket.PutDataInSendBuffer(@MsgLine, strlen(MsgLine));
FWSocket.SendStr(#13+#10);
end
else begin
{ Now we need to send data lines }
if FMoreLines then begin
try
Inc(FLineNum);
TriggerGetData(FLineNum, @MsgLine, High(MsgLine), FMoreLines);
except
FMoreLines := FALSE;
end;
end;
if FMoreLines then begin
if MsgLine[0] = '.' then
Move(MsgLine[0], MsgLine[1], StrLen(MsgLine) + 1);
TriggerDisplay('> ' + StrPas(MsgLine));
FWSocket.OnDataSent := WSocketDataSent;
FWSocket.PutDataInSendBuffer(@MsgLine, StrLen(MsgLine));
FWSocket.SendStr(#13 + #10);
end
else begin
{ Send the last message line }
FWSocket.OnDataSent := nil;
ExecAsync(smtpData, '.', [250], nil);
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WSocketDataSent(Sender : TObject; Error : Word);
begin
FState := smtpInternalReady;
DataNext;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Abort;
begin
StateChange(smtpAbort);
FWSocket.CancelDnsLookup;
FWSocket.Abort;
StateChange(smtpReady);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Connect;
begin
CheckReady;
if FConnected then
raise SmtpException.Create('SMTP component already connected');
if not FHighLevelFlag then
FRequestType := smtpConnect; { 10/05/99 }
FRequestDoneFlag := FALSE;
FReceiveLen := 0;
FRequestResult := 0;
StateChange(smtpDnsLookup);
FWSocket.OnDataSent := nil;
FWSocket.OnDnsLookupDone := WSocketDnsLookupDone;
FWSocket.DnsLookup(FHost);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Quit;
begin
CheckReady;
FFctPrv := smtpFctQuit;
if not FConnected then begin
{ We are not connected, it's ok... }
FRequestType := smtpQuit;
FRequestDoneFlag := FALSE;
TriggerRequestDone(0);
Exit;
end;
ExecAsync(smtpQuit, 'QUIT', [221], nil); { Should I force a FWSocket.Close }
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.DoHighLevelAsync;
begin
{$IFDEF TRACE} TriggerDisplay('! HighLevelAsync ' + IntToStr(FRequestResult)); {$ENDIF}
if FState = smtpAbort then begin
{$IFDEF TRACE} TriggerDisplay('! Abort detected'); {$ENDIF}
FFctSet := [];
FHighLevelResult := 426;
FErrorMessage := '426 Operation aborted.';
end;
FNextRequest := DoHighLevelAsync;
if FRequestResult <> 0 then begin
{ Previous command had errors }
FHighLevelResult := FRequestResult;
if (FFctPrv = smtpFctQuit) or (not (smtpFctQuit in FFctSet)) then
FFctSet := []
else
FFctSet := [smtpFctQuit];
end;
if smtpFctConnect in FFctSet then begin
FFctPrv := smtpFctConnect;
FFctSet := FFctSet - [FFctPrv];
Connect;
Exit;
end;
if smtpFctHelo in FFctSet then begin
FFctPrv := smtpFctHelo;
FFctSet := FFctSet - [FFctPrv];
Helo;
Exit;
end;
if smtpFctVrfy in FFctSet then begin
FFctPrv := smtpFctVrfy;
FFctSet := FFctSet - [FFctPrv];
Vrfy;
Exit;
end;
if smtpFctMailFrom in FFctSet then begin
FFctPrv := smtpFctMailFrom;
FFctSet := FFctSet - [FFctPrv];
MailFrom;
Exit;
end;
if smtpFctRcptTo in FFctSet then begin
FFctPrv := smtpFctRcptTo;
FFctSet := FFctSet - [FFctPrv];
RcptTo;
Exit;
end;
if smtpFctData in FFctSet then begin
FFctPrv := smtpFctData;
FFctSet := FFctSet - [FFctPrv];
Data;
Exit;
end;
if smtpFctQuit in FFctSet then begin
FFctPrv := smtpFctQuit;
FFctSet := FFctSet - [FFctPrv];
Quit;
Exit;
end;
{$IFDEF TRACE} TriggerDisplay('! HighLevelAsync done'); {$ENDIF}
FFctSet := [];
FNextRequest := nil;
FRequestDoneFlag := FALSE;
TriggerRequestDone(FHighLevelResult);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.HighLevelAsync(
RqType : TSmtpRequest; Fcts : TSmtpFctSet);
begin
if FConnected and (smtpFctConnect in Fcts) then
raise SmtpException.Create('SMTP component already connected');
CheckReady;
FLastResponseSave := FLastResponse;
FStatusCodeSave := -1;
FRequestType := RqType;
FRequestResult := 0;
FFctSet := Fcts;
FFctPrv := smtpFctNone;
FHighLevelResult := 0;
FHighLevelFlag := TRUE;
FLastResponse := '';
FErrorMessage := '';
FRestartFlag := FALSE;
DoHighLevelAsync;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Open;
begin
HighLevelAsync(smtpOpen, [smtpFctConnect, smtpFctHelo]);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.Mail;
begin
HighLevelAsync(smtpMail, [smtpFctMailFrom, smtpFctRcptTo, smtpFctData]);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.WSocketSessionClosed(Sender : TObject; Error : WORD);
begin
FConnected := FALSE;
TriggerSessionClosed(Error);
TriggerRequestDone(WSAEINTR);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerHeaderLine(Line : PChar; Size : Integer);
begin
if Assigned(FOnHeaderLine) then
FOnHeaderLine(Self, Line, Size);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.TriggerGetData(
LineNum: Integer;
MsgLine: PChar;
MaxLen: Integer;
var More: Boolean);
begin
if not Assigned(FOnGetData) then
More := FALSE
else
FOnGetData(Self, LineNum, MsgLine, MaxLen, More);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.SetRcptName(newValue : TStrings);
var
I : Integer;
begin
FRcptName.Clear;
for I := 0 to newValue.Count - 1 do
FRcptName.Add(newValue.Strings[I]);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomSmtpClient.SetMailMessage(newValue : TStrings);
var
I : Integer;
begin
FMailMessage.Clear;
for I := 0 to newValue.Count - 1 do
FMailMessage.Add(newValue.Strings[I]);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TimeZoneBias : String;
{$IFDEF VER80} { Delphi 1 doesn't support timezone API }
begin
Result := '-0000';
end;
{$ELSE}
const
Time_Zone_ID_DayLight = 2;
var
TZI : tTimeZoneInformation;
TZIResult : Integer;
aBias : Integer;
begin
TZIResult := GetTimeZoneInformation(TZI);
if TZIResult = -1 then
Result := '-0000'
else begin
if TZIResult = Time_Zone_ID_DayLight then { 10/05/99 }
aBias := TZI.Bias + TZI.DayLightBias
else
aBias := TZI.Bias + TZI.StandardBias;
Result := Format('-%.2d%.2d', [Abs(aBias) div 60, Abs(aBias) mod 60]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -