unit UnitSmtpLogin;
interface
uses NMSMTP,classes,Sysutils;
type
EIdException = class(Exception);
TIdCardinalBytes = record
case Integer of
0: (
Byte1: Byte;
Byte2: Byte;
Byte3: Byte;
Byte4: Byte
;
1: (Whole: Cardinal);
end;
function login(smtp:TNMSMTP;user,password:string):boolean;
var
//MIME:
CodingTable: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
//UUE: CodingTable: string = '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_';
//XXE: CodingTable: string = '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
//MIME:
FillChar: char = '=';
//UUE: CodingTable[1] or '~'
//XXE: CodingTable[1] or '~'
implementation
procedure EncodeUnit(const AIn1, AIn2, AIn3: Byte; var VOut: Cardinal);
var
LUnit: TIdCardinalBytes;
begin
LUnit.Byte1 := Ord(CodingTable[((AIn1 SHR 2) and 63) + 1]);
LUnit.Byte2 := Ord(CodingTable[(((AIn1 SHL 4) or (AIn2 SHR 4)) and 63) + 1]);
LUnit.Byte3 := Ord(CodingTable[(((AIn2 SHL 2) or (AIn3 SHR 6)) and 63) + 1]);
LUnit.Byte4 := Ord(CodingTable[(Ord(AIn3) and 63) + 1]);
VOut := LUnit.Whole;
end;
function Encode2(ASrcStream: TStream; const ABytes: integer = MaxInt): string;
var
LIn1, LIn2, LIn3: Byte;
LSize: integer;
LStartPos: integer;
LUnit: TIdCardinalBytes;
begin
//TODO: Make this more efficient. Profile it to test, but maybe make single calls to ReadBuffer
//then pull from memory
if (ABytes <> MaxInt) and ((ABytes mod 3) > 0) then begin
raise EIdException.Create('Uneven size in Encode.');
end;
Result := '';
LStartPos := ASrcStream.Position;
while (ASrcStream.Position < ASrcStream.Size) and (ASrcStream.Position - LStartPos < ABytes)
do begin
ASrcStream.ReadBuffer(LIn1, 1);
if ASrcStream.Position < ASrcStream.Size then begin
ASrcStream.ReadBuffer(LIn2, 1);
if ASrcStream.Position < ASrcStream.Size then begin
ASrcStream.ReadBuffer(LIn3, 1);
LSize := 3;
end else begin
LIn3 := 0;
LSize := 2;
end;
end else begin
LIn2 := 0;
LSize := 1;
end;
EncodeUnit(LIn1, LIn2, LIn3, LUnit.Whole);
Result := Result + Chr(LUnit.Byte1) + Chr(LUnit.Byte2) + Chr(LUnit.Byte3) + Chr(LUnit.Byte4);
if LSize < 3 then begin
Result[Length(Result)] := FillChar;
if LSize = 1 then begin
Result[Length(Result) - 1] := FillChar;
end;
end;
end;
end;
function Encode(const ASrc: string): string;
var
LSrcStream: TStringStream;
begin
LSrcStream := TStringStream.Create(ASrc); try
Result := Encode2(LSrcStream);
finally FreeAndNil(LSrcStream); end;
end;
function login(smtp:TNMSMTP;user,password:string):boolean;
const crlf = #13#10;
var
s:string;
begin
result:=false;
try
s:='auth LOGIN'+crlf;
smtp.SendBuffer(pchar(s),length(s));
s:=smtp.ReadLn;
if copy(s,1,3)<>'334' then exit; //Fail
s:=Encode(user)+crlf;
smtp.SendBuffer(pchar(s),length(s));
s:=copy(smtp.ReadLn,1,3);
if (s<>'334')and(s<>'235') then exit; //Fail
s:=Encode(password)+crlf;
smtp.SendBuffer(pchar(s),length(s));
s:=copy(smtp.ReadLn,1,3);
if (s<>'235') then exit; //Fail
result:=true;
except
end;
end;
end.