主讲:上兴
邮件发送演示,演示直接根据RFC协议进行发信
演示利用空间中转邮件
1。直接根据RFC协议进行发信
/////////////////////////////////////////////////////////////////////////
首先将常用的网络操作单元集合为一个单元 Unit_MyWinSock.pas
////////////////////////////////////////////////////////////////////////
unit Unit_MyWinSock;
interface
uses
Windows, WinSock;
function GetIpbyHostName(Host: string): string;
function StartNet(host: string; port: integer; var FSocket: integer): Boolean;
procedure StopNet(Fsocket: integer);
function SendData(FSocket: integer; SendStr: string): integer;
function GetData(FSocket: integer): string;
implementation
function StrPas(const Str: PChar): string;
begin
Result := Str;
end;
function StrCopy(Dest: PChar; const Source: PChar): PChar;
asm
PUSH EDI
PUSH ESI
MOV ESI,EAX
MOV EDI,EDX
MOV ECX,0FFFFFFFFH
XOR AL,AL
REPNE SCASB
NOT ECX
MOV EDI,ESI
MOV ESI,EDX
MOV EDX,ECX
MOV EAX,EDI
SHR ECX,2
REP MOVSD
MOV ECX,EDX
AND ECX,3
REP MOVSB
POP ESI
POP EDI
end;
function StrLen(const Str: PChar): Cardinal; assembler;
asm
MOV EDX,EDI
MOV EDI,EAX
MOV ECX,0FFFFFFFFH
XOR AL,AL
REPNE SCASB
MOV EAX,0FFFFFFFEH
SUB EAX,ECX
MOV EDI,EDX
end;
{============================================================}
function GetIpbyHostName(Host: string): string;
{
功能描述:获取主机的IP地址
}
type
TaPInAddr = array[0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe: PHostEnt;
pptr: PaPInAddr;
i: Integer;
begin
Result := '';
phe := GetHostByName(pchar(Host));
if phe = nil then Exit;
pptr := PaPInAddr(Phe^.h_addr_list);
I := 0;
while pptr^[I] <> nil do
begin
if i = 0 then result := StrPas(inet_ntoa(pptr^[I]^));
Inc(I);
end;
end;
{============================================================}
function StartNet(host: string; port: integer; var FSocket: integer): Boolean;
{
功能描述:连接某IP地址
}
var
SockAddrIn: TSockAddrIn;
t: linger;
timeout: timeval;
r: TFDSet;
iTimeOut: integer;
ul, ul1: LongInt;
ret: integer;
begin
Result := False;
FSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if FSocket = invalid_socket then exit;
t.l_onoff := 1;
t.l_linger := 0;
setsockopt(FSocket, SOL_SOCKET, SO_LINGER, @t, sizeof(t)); {关闭Socket后立刻释放资源}
//set Recv and Send time out
iTimeOut := 6000; //设置发送超时6秒
if (setsockopt(FSocket, SOL_SOCKET, SO_SNDTIMEO, @iTimeOut, sizeof(TimeOut)) = SOCKET_ERROR) then Exit;
iTimeOut := 6000; //设置接收超时6秒
if (setsockopt(FSocket, SOL_SOCKET, SO_RCVTIMEO, @iTimeOut, sizeof(TimeOut)) = SOCKET_ERROR) then Exit;
//设置非阻塞方式连接
ul := 1;
ret := ioctlsocket(FSocket, FIONBIO, ul);
if (ret = SOCKET_ERROR) then Exit;
//连接
SockAddrIn.sin_addr.s_addr := inet_addr(PChar(host));
SockAddrIn.sin_family := PF_INET;
SockAddrIn.sin_port := htons(port);
ret := connect(FSocket, SockAddrIn, SizeOf(SockAddrIn));
//select 模型,即设置超时
FD_ZERO(r);
FD_SET(FSocket, r);
timeout.tv_sec := 5; //连接超时5秒
timeout.tv_usec := 0;
ret := select(0, nil, @r, nil, @timeout);
if (ret <= 0) then
begin
closesocket(FSocket);
Exit;
end;
//一般非锁定模式套接比较难控制,可以根据实际情况考虑 再设回阻塞模式
ul1 := 0;
ret := ioctlsocket(FSocket, FIONBIO, ul1);
if (ret = SOCKET_ERROR) then
begin
closesocket(FSocket);
Exit;
end;
Result := True;
end;
{============================================================}
procedure StopNet(Fsocket: integer);
{
功能描述:关闭一个Socket
}
begin
closesocket(FSocket);
end;
{============================================================}
function SendData(FSocket: integer; SendStr: string): integer;
{
功能描述:通过指定Socket发送字符数据
}
var
DataBuf: array[0..4096] of char;
err: integer;
begin
strcopy(DataBuf, pchar(SendStr));
err := send(FSocket, DataBuf, strlen(DataBuf), MSG_DONTROUTE);
Result := err;
end;
{============================================================}
function GetData(FSocket: integer): string;
{
功能描述:获取指定Socket的字符数据
}
const
MaxSize = 1024;
var
DataBuf: array[0..MaxSize] of char;
err: integer;
begin
err := recv(FSocket, DataBuf, MaxSize, 0);
Result := Strpas(DataBuf);
end;
{
const
MaxSize = 1024;
var
DataBuf: array[0..MaxSize - 1] of char;
S: string;
iRet: integer;
begin
S := '';
repeat
FillChar(DataBuf, MaxSize, #0);
iRet := recv(FSocket, DataBuf, MaxSize, 0);
S := S + Strpas(DataBuf);
until iRet <= 0;
Result := S;
end;
}
{============================================================}
var
Re: integer;
Wsa: TWSAData;
initialization
Re := WSAStartup($101, Wsa); //初始化Wsock32.dll,如果是2.2版本,则使用MakeWord(2,2),
if Re <> 0 then Halt;
finalization
WSACleanUp;
end.
////////////////////////////////////////////////////////////////////////////////////
和Base64编码Delphi版本 BASE64.pas
/////////////////////////////////////////////////////////////////////////////////////
unit BASE64;
interface
uses Classes;
//BaseTable为BASE64码表
const BaseTable:string='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function EncodeStringBase64(Source:string):string;
function DecodeStringBASE64(Source:string):string;
function EncodeStreamBASE64(Encoded: TMemoryStream ; Decoded: TMemoryStream): Integer;
implementation
{对参数TMemoryStrema中的字节流进行Base64编码,编码后的结果保存在Encoded中,函数返回编码长度}
function EncodeStreamBASE64(Encoded: TMemoryStream ; Decoded: TMemoryStream): Integer;
const
_Code64: String[64] =('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');
var
I: LongInt;
B: array[0..2279] of Byte;
J, K, L, M, Quads: Integer;
Stream: string[76];
EncLine: String;
begin
Encoded.Clear;
Stream := '';
Quads := 0;
{为提高效率,每2280字节流为一组进行编码}
J := Decoded.Size div 2280;
Decoded.Position := 0;
{对前J*2280个字节流进行编码}
for I := 1 to J do
begin
Decoded.Read(B, 2280);
for M := 0 to 39 do
begin
for K := 0 to 18 do
begin
L:= 57*M + 3*K;
Stream[Quads+1] := _Code64[(B[L] div 4)+1];
Stream[Quads+2] := _Code64[(B[L] mod 4)*16 + (B[L+1] div 16)+1];
Stream[Quads+3] := _Code64[(B[L+1] mod 16)*4 + (B[L+2] div 64)+1];
Stream[Quads+4] := _Code64[B[L+2] mod 64+1];
Inc(Quads, 4);
if Quads = 76 then
begin
Stream[0] := #76;
EncLine := Stream+#13#10;
Encoded.Write(EncLine[1], Length(EncLine));
Quads := 0;
end;
end;
end;
end;
{对以2280为模的余数字节流进行编码}
J := (Decoded.Size mod 2280) div 3;
for I := 1 to J do
begin
Decoded.Read(B, 3);
Stream[Quads+1] := _Code64[(B[0] div 4)+1];
Stream[Quads+2] := _Code64[(B[0] mod 4)*16 + (B[1] div 16)+1];
Stream[Quads+3] := _Code64[(B[1] mod 16)*4 + (B[2] div 64)+1];
Stream[Quads+4] := _Code64[B[2] mod 64+1];
Inc(Quads, 4);
{每行76个字符}
if Quads = 76 then
begin
Stream[0] := #76;
EncLine := Stream+#13#10;
Encoded.Write(EncLine[1], Length(EncLine));
Quads := 0;
end;
end;
{“=”补位}
if (Decoded.Size mod 3) = 2 then
begin
Decoded.Read(B, 2);
Stream[Quads+1] := _Code64[(B[0] div 4)+1];
Stream[Quads+2] := _Code64[(B[0] mod 4)*16 + (B[1] div 16)+1];
Stream[Quads+3] := _Code64[(B[1] mod 16)*4 + 1];
Stream[Quads+4] := '=';
Inc(Quads, 4);
end;
if (Decoded.Size mod 3) = 1 then
begin
Decoded.Read(B, 1);
Stream[Quads+1] := _Code64[(B[0] div 4)+1];
Stream[Quads+2] := _Code64[(B[0] mod 4)*16 + 1];
Stream[Quads+3] := '=';
Stream[Quads+4] := '=';
Inc(Quads, 4);
end;
Stream[0] := Chr(Quads);
if Quads > 0 then
begin
EncLine := Stream+#13#10;
Encoded.Write(EncLine[1], Length(EncLine));
end;
Result := Encoded.Size;
end;
function FindInTable(CSource:char):integer;
begin
result:=Pos(string(CSource),BaseTable)-1;
end;
////
{对参数Source字符串进行Base64编码,返回编码后的字符串}
function DecodeStringBASE64(Source:string):string;
var
SrcLen,Times,i:integer;
x1,x2,x3,x4,xt:byte;
begin
result:='';
SrcLen:=Length(Source);
Times:=SrcLen div 4;
for i:=0 to