首页  编辑  

利用WinSock发送邮件

Tags: /超级猛料/Network.网络通讯/电子邮件/   Date Created:

unit SMTP_Connections;

// *********************************************************************

//     Unit Name                          : SMTP_Connections           *

//     Author               : Melih SARICA (Non ZERO)                  *

//     Date               : 01/17/2004                                 *

//**********************************************************************

interface

uses

 Classes, StdCtrls;

const

 WinSock = 'wsock32.dll';

 Internet = 2;

 Stream  = 1;

 fIoNbRead = $4004667F;

 WinSMTP = $0001;

 LinuxSMTP = $0002;

type

 TWSAData = packed record

   wVersion: Word;

   wHighVersion: Word;

   szDescription: array[0..256] of Char;

   szSystemStatus: array[0..128] of Char;

   iMaxSockets: Word;

   iMaxUdpDg: Word;

   lpVendorInfo: PChar;

 end;

 PHost = ^THost;

 THost = packed record

   Name: PChar;

   aliases: ^PChar;

   addrtype: Smallint;

   Length: Smallint;

   addr: ^Pointer;

 end;

 TSockAddr = packed record

   Family: Word;

   Port: Word;

   Addr: Longint;

   Zeros: array[0..7] of Byte;

 end;

function WSAStartup(Version:word; Var Data:TwsaData):integer; stdcall; far; external winsock;

function socket(Family,Kind,Protocol:integer):integer; stdcall; far; external winsock;

function shutdown(Socket,How:Integer):integer; stdcall; far; external winsock;

function closesocket(socket:Integer):integer; stdcall; far; external winsock;

function WSACleanup:integer; stdcall; far; external winsock;

function bind(Socket:Integer; Var SockAddr:TSockAddr; AddrLen:integer):integer; stdcall; far; external winsock;

function listen(socket,flags:Integer):integer; stdcall; far; external winsock;

function connect(socket:Integer; Var SockAddr:TSockAddr; AddrLen:integer):integer; stdcall; far; external winsock;

function accept(socket:Integer; Var SockAddr:TSockAddr; Var AddrLen:Integer):integer; stdcall; far; external winsock;

function WSAGetLastError:integer; stdcall; far; external winsock;

function recv(socket:integer; data:pchar; datalen,flags:integer):integer; stdcall; far; external winsock;

function send(socket:integer; var data; datalen,flags:integer):integer; stdcall; far; external winsock;

function gethostbyname(HostName:PChar):PHost; stdcall; far; external winsock;

function WSAIsBlocking:boolean; stdcall; far; external winsock;

function WSACancelBlockingCall:integer; stdcall; far; external winsock;

function ioctlsocket(socket:integer; cmd: Longint; var arg: longint): Integer; stdcall; far; external winsock;

function gethostname(name:pchar; size:integer):integer; stdcall; far; external winsock;

procedure _authSendMail(MailServer,uname,upass,mFrom,mFromName,mToName,Subject:string;mto,mbody:TStringList);

function ConnectServer(mhost:string;mport:integer):integer;

function ConnectServerwin(mhost:string;mport:integer):integer;

function DisConnectServer:integer;

function Stat: string;

function SendCommand(Command: String): string;

function SendData(Command: String): string;

function SendCommandWin(Command: String): string;

function ReadCommand: string;

function encryptB64(s:string):string;

var

 mconnHandle: Integer;

 mFin, mFOut: Textfile;

 EofSock: Boolean;

 mactive: Boolean;

 mSMTPErrCode: Integer;

 mSMTPErrText: string;

 mMemo: TMemo;

implementation

uses

 SysUtils, Sockets, IdBaseComponent,

 IdCoder, IdCoder3to4, IdCoderMIME, IniFiles;

var

 mClient: TTcpClient;

procedure _authSendMail(MailServer, uname, upass, mFrom, mFromName,

 mToName, Subject: string; mto, mbody: TStringList);

var

 tmpstr: string;

 cnt: Integer;

 mstrlist: TStrings;

 RecipientCount: Integer;

begin

 if ConnectServerWin(Mailserver, 25) = 250 then

 begin

   Sendcommandwin('AUTH LOGIN ');

   SendcommandWin(encryptB64(uname));

   SendcommandWin(encryptB64(upass));

   SendcommandWin('MAIL FROM: ' + mfrom);

   for cnt := 0 to mto.Count - 1 do

     SendcommandWin('RCPT TO: ' + mto[cnt]);

   Sendcommandwin('DATA');

   SendData('Subject: ' + Subject);

   SendData('From: "' + mFromName + '" <' + mfrom + '>');

   SendData('To: ' + mToName);

   SendData('Mime-Version: 1.0');

   SendData('Content-Type: multipart/related; boundary="Esales-Order";');

   SendData('     type="text/html"');

   SendData('');

   SendData('--Esales-Order');

   SendData('Content-Type: text/html;');

   SendData('        charset="iso-8859-9"');

   SendData('Content-Transfer-Encoding: QUOTED-PRINTABLE');

   SendData('');

   for cnt := 0 to mbody.Count - 1 do

     SendData(mbody[cnt]);

   Senddata('');

   SendData('--Esales-Order--');

   Senddata(' ');

   mSMTPErrText := SendCommand(crlf + '.' + crlf);

   try

     mSMTPErrCode := StrToInt(Copy(mSMTPErrText, 1, 3));

   except

   end;

   SendData('QUIT');

   DisConnectServer;

 end;

end;

function Stat: string;

var

 s: string;

begin

 s := ReadCommand;

 Result := s;

end;

function EchoCommand(Command: string): string;

begin

 SendCommand(Command);

 Result := ReadCommand;

end;

function ReadCommand: string;

var

 tmp: string;

begin

 repeat

   ReadLn(mfin, tmp);

   if Assigned(mmemo) then

     mmemo.Lines.Add(tmp);

 until (Length(tmp) < 4) or (tmp[4] <> '-');

 Result := tmp

end;

function SendData(Command: string): string;

begin

 Writeln(mfout, Command);

end;

function SendCommand(Command: string): string;

begin

 Writeln(mfout, Command);

 Result := stat;

end;

function SendCommandWin(Command: string): string;

begin

 Writeln(mfout, Command + #13);

 Result := stat;

end;

function FillBlank(Source: string; number: Integer): string;

var

 a: Integer;

begin

 Result := '';

 for a := Length(trim(Source)) to number do

   Result := Result + ' ';

end;

function IpToLong(ip: string): Longint;

var

 x, i: Byte;

 ipx: array[0..3] of Byte;

 v: Integer;

begin

 Result := 0;

 Longint(ipx) := 0;  

 i := 0;

 for x := 1 to Length(ip) do

   if ip[x] = '.' then  

   begin

     Inc(i);

     if i = 4 then Exit;

   end  

 else  

 begin

   if not (ip[x] in ['0'..'9']) then Exit;

   v := ipx[i] * 10 + Ord(ip[x]) - Ord('0');

   if v > 255 then Exit;

   ipx[i] := v;

 end;

 Result := Longint(ipx);

end;

function HostToLong(AHost: string): Longint;

var

 Host: PHost;

begin

 Result := IpToLong(AHost);

 if Result = 0 then  

 begin

   Host := GetHostByName(PChar(AHost));

   if Host <> nil then Result := Longint(Host^.Addr^^);

 end;

end;

function LongToIp(Long: Longint): string;

var

 ipx: array[0..3] of Byte;

 i: Byte;

begin

 Longint(ipx) := long;

 Result       := '';

 for i := 0 to 3 do Result := Result + IntToStr(ipx[i]) + '.';

 SetLength(Result, Length(Result) - 1);

end;

procedure Disconnect(Socket: Integer);

begin

 ShutDown(Socket, 1);

 CloseSocket(Socket);

end;

function CallServer(Server: string; Port: Word): Integer;

var

 SockAddr: TSockAddr;

begin

 Result := socket(Internet, Stream, 0);

 if Result = -1 then Exit;

 FillChar(SockAddr, SizeOf(SockAddr), 0);

 SockAddr.Family := Internet;

 SockAddr.Port := swap(Port);

 SockAddr.Addr := HostToLong(Server);

 if Connect(Result, SockAddr, SizeOf(SockAddr)) <> 0 then  

 begin

   Disconnect(Result);

   Result := -1;

 end;

end;

function OutputSock(var F: TTextRec): Integer; far;

begin

 if F.BufPos <> 0 then  

 begin

   Send(F.Handle, F.BufPtr^, F.BufPos, 0);

   F.BufPos := 0;

 end;

 Result := 0;

end;

function InputSock(var F: TTextRec): Integer; far;

var

 Size: Longint;

begin

 F.BufEnd := 0;

 F.BufPos := 0;

 Result := 0;

 repeat

   if (IoctlSocket(F.Handle, fIoNbRead, Size) < 0) then  

   begin

     EofSock := True;

     Exit;

   end;

 until (Size >= 0);

 F.BufEnd := Recv(F.Handle, F.BufPtr, F.BufSize, 0);

 EofSock  := (F.Bufend = 0);

end;

function CloseSock(var F: TTextRec): Integer; far;

begin

 Disconnect(F.Handle);

 F.Handle := -1;

 Result   := 0;

end;

function OpenSock(var F: TTextRec): Integer; far;

begin

 if F.Mode = fmInput then  

 begin

   EofSock := False;

   F.BufPos := 0;

   F.BufEnd := 0;

   F.InOutFunc := @InputSock;

   F.FlushFunc := nil;

 end  

 else  

 begin

   F.Mode := fmOutput;

   F.InOutFunc := @OutputSock;

   F.FlushFunc := @OutputSock;

 end;

 F.CloseFunc := @CloseSock;

 Result := 0;

end;

procedure AssignCrtSock(Socket:integer; Var Input,Output:TextFile);

begin

 with TTextRec(Input) do

 begin

   Handle := Socket;

   Mode := fmClosed;

   BufSize := SizeOf(Buffer);

   BufPtr := @Buffer;

   OpenFunc := @OpenSock;

 end;

 with TTextRec(Output) do

 begin

   Handle := Socket;

   Mode := fmClosed;

   BufSize := SizeOf(Buffer);

   BufPtr := @Buffer;

   OpenFunc := @OpenSock;

 end;

 Reset(Input);

 Rewrite(Output);

end;

function ConnectServer(mhost: string; mport: Integer): Integer;

var

 tmp: string;

begin

 mClient := TTcpClient.Create(nil);

 mClient.RemoteHost := mhost;

 mClient.RemotePort := IntToStr(mport);

 mClient.Connect;

 mconnhandle := callserver(mhost, mport);

 if (mconnHandle<>-1) then

 begin

   AssignCrtSock(mconnHandle, mFin, MFout);

   tmp := stat;

   tmp := SendCommand('HELO bellona.com.tr');

   if Copy(tmp, 1, 3) = '250' then

   begin

     Result := StrToInt(Copy(tmp, 1, 3));

   end;

 end;

end;

function ConnectServerWin(mhost: string; mport: Integer): Integer;

var

 tmp: string;

begin

 mClient := TTcpClient.Create(nil);

 mClient.RemoteHost := mhost;

 mClient.RemotePort := IntToStr(mport);

 mClient.Connect;

 mconnhandle := callserver(mhost, mport);

 if (mconnHandle<>-1) then

 begin

   AssignCrtSock(mconnHandle, mFin, MFout);

   tmp := stat;

   tmp := SendCommandWin('HELO bellona.com.tr');

   if Copy(tmp, 1, 3) = '250' then

   begin

     Result := StrToInt(Copy(tmp, 1, 3));

   end;

 end;

end;

function DisConnectServer: Integer;

begin

 closesocket(mconnhandle);

 mClient.Disconnect;

 mclient.Free;

end;

function encryptB64(s: string): string;

var

 hash1: TIdEncoderMIME;

 p: string;

begin

 if s <> '' then

 begin

   hash1 := TIdEncoderMIME.Create(nil);

   p := hash1.Encode(s);

   hash1.Free;

 end;

 Result := p;

end;

end.