![]() |
#2
zklhp2008-09-19 15:49
|
作者:zklhp 于2008-9-19上传
--------------------------------------------------------------------------------
我是汇编通讯的忠实读者,看汇编通讯一年了,也写个程序,也算是为杂志做点贡献吧。写的不好,还望各位高手指点。
看第五期时,我就对《用汇编语言写ESMTP电子邮件发送程序》很感兴趣。可程序提示发送成功后,并没有收到邮件,当时也没再深究,
后来再试,又能成功发送了,真是@#%。现在放假了,又想起那个程序,就研究了一下ESMTP发邮件的过程,顺便完善了一下谢平的程序。
只有本站会员才能查看附件,请 登录
帖一下我的写的发送线程函数吧。排版可能不太好,建议用masmplus直接看工程。

.code
_SendProc proc uses ebx edi esi _Param:DWORD
local @hSocket:DWORD
local @stWsadata:WSADATA
local @stSin:sockaddr_in
local @szRcvBuffer[1024]:BYTE
local @szSend[4096]:BYTE
local @szBuffer[2048]:BYTE
invoke WSAStartup, 202h, addr @stWsadata
invoke socket, AF_INET, SOCK_STREAM, 0
.if eax == INVALID_SOCKET
invoke WSAGetLastError
invoke wsprintf,addr @szBuffer,CTXT('创建套接字出错 错误码 %x',0dh,0ah),eax
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szBuffer
invoke MessageBox,hWinMain,CTXT('发送失败!'),CTXT('错误'),0
jmp @exit
.endif
mov @hSocket, eax
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('创建套接字成功!',0dh,0ah)
invoke RtlZeroMemory,addr @stSin,sizeof @stSin
mov @stSin.sin_family, AF_INET
invoke htons, 25 ;默认端口是25
mov @stSin.sin_port, ax
invoke gethostbyname,offset szSmtpAddr
.if eax
mov eax, [eax + hostent.h_list]
mov eax, [eax]
mov eax, [eax]
mov @stSin.sin_addr, eax
.endif
;建立连接
invoke connect,@hSocket, addr @stSin, sizeof @stSin
.if eax == SOCKET_ERROR
invoke WSAGetLastError
invoke wsprintf,@szBuffer,CTXT('连接服务器出错 错误码 %x',0dh,0ah),eax
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szBuffer
invoke MessageBox,hWinMain,CTXT('发送失败!'),CTXT('错误'),0
jmp @exit
.endif
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('连接到服务器成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送“ehlo local”
invoke lstrlen,offset szEhlo
invoke send, @hSocket, addr szEhlo, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 ehlo local 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送“auth login”
;好象大多数免费邮箱都支持login验证方式 支持cram-md5的却没找到~~~ 这里只用login吧
invoke lstrlen,addr szAuth
invoke send, @hSocket, addr szAuth, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 auth login 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
lea esi,@szRcvBuffer
add esi,4
invoke lstrlen,esi
mov edi,eax
;要把最后的\r\t除去
dec edi
dec edi
;貌似这样比 sub edi,2 省个字节 呵呵
invoke RtlZeroMemory,addr @szBuffer,sizeof @szBuffer
invoke _Base64Decode,esi,addr @szBuffer,edi
invoke wsprintf,addr @szRcvBuffer,CTXT('334 %s',0dh,0ah),addr @szBuffer ;我们自己把他解码还原
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送用户名
invoke lstrlen,offset szUserName
invoke _Base64Encode,offset szUserName,addr @szBuffer,eax
invoke wsprintf,addr @szSend,CTXT('%s',0dh,0ah),addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送用户名成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
lea esi,@szRcvBuffer
add esi,4
invoke lstrlen,esi
mov edi,eax
dec edi
dec edi ;貌似这样比 sub edi,2 省个字节 呵呵
invoke RtlZeroMemory,addr @szBuffer,sizeof @szBuffer
invoke _Base64Decode,esi,addr @szBuffer,edi
invoke wsprintf,addr @szRcvBuffer,CTXT('334 %s',0dh,0ah),addr @szBuffer ;我们自己把他解码还原
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送密码
invoke lstrlen,offset szPassWord
invoke _Base64Encode,offset szPassWord,addr @szBuffer,eax
invoke wsprintf,addr @szSend,CTXT('%s',0dh,0ah),addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送密码成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
invoke StrStr,addr @szRcvBuffer,CTXT('235')
.if eax == 0 ;没有就是验证不通过
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('验证失败!',0dh,0ah)
invoke WSACleanup
invoke GetDlgItem,hWinMain,IDC_BTN_SEND
invoke EnableWindow,eax,TRUE
xor eax,eax
dec eax
ret
.endif
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('验证成功!',0dh,0ah)
;发送“mail from”
invoke GetDlgItemText,hWinMain,IDC_EDT_SENDADDR,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szMailFrom,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 mail from 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送“rcpt to”
invoke GetDlgItemText,hWinMain,IDC_EDT_RCPTADDR,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szRcptTo,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 rcpt to 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送“data”
invoke lstrlen,addr szData
invoke send, @hSocket, addr szData, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 data 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送“from”
invoke GetDlgItemText,hWinMain,IDC_EDT_SENDADDR,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szFrom,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 from 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke Sleep,1000
;发送“to”
invoke GetDlgItemText,hWinMain,IDC_EDT_RCPTADDR,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szTo,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 to 成功!',0dh,0ah)
;发送主题
invoke GetDlgItemText,hWinMain,IDC_EDT_SUB,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szSubject,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送主题成功!',0dh,0ah)
;发送"Reply-TO"
invoke RtlZeroMemory,addr @szSend,sizeof @szSend
invoke RtlZeroMemory,addr @szBuffer,sizeof @szBuffer
invoke GetDlgItemText,hWinMain,IDC_EDT_SENDADDR,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szReplyTo,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 Reply-TO 成功!',0dh,0ah)
;发送空行
invoke lstrlen,addr szCrLf
invoke send, @hSocket, addr szCrLf,eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送空行成功!',0dh,0ah)
;发送邮件正文
invoke RtlZeroMemory,addr @szSend,sizeof @szSend
invoke RtlZeroMemory,addr @szBuffer,sizeof @szBuffer
invoke GetDlgItemText,hWinMain,IDC_EDT_CONTENT,addr @szBuffer,sizeof @szBuffer
invoke wsprintf,addr @szSend,addr szContent,addr @szBuffer
invoke lstrlen,addr @szSend
invoke send, @hSocket, addr @szSend,eax, 0
;发送“.”
invoke lstrlen,addr szDot
invoke send, @hSocket, addr szDot, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 . 成功!',0dh,0ah)
invoke RtlZeroMemory,addr @szRcvBuffer,sizeof @szRcvBuffer
invoke recv, @hSocket, addr @szRcvBuffer,sizeof @szRcvBuffer,0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,addr @szRcvBuffer
;发送“quit”
invoke lstrlen,addr szQuit
invoke send, @hSocket, addr szQuit, eax, 0
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('发送 quit 成功!',0dh,0ah)
;断开连接
invoke closesocket, @hSocket
invoke SendDlgItemMessage,hWinMain,IDC_EDT_DEBUG,EM_REPLACESEL,0,CTXT('与服务器连接断开!',0dh,0ah)
invoke MessageBox,hWinMain,CTXT('发送成功!'),CTXT('提示'),0
@exit:
invoke WSACleanup
invoke GetDlgItem,hWinMain,IDC_BTN_SEND
invoke EnableWindow,eax,TRUE
xor eax,eax
ret
_SendProc endp
开始,我以为验证时要用到CRAM-MD5 等算法,可用telnet一试才知道,免费邮箱大多支持login验证方式,就简化了这个函数,
用一种简单的方式判断验证成功,省了不少时间,呵呵。
其他的都不用说了,很简单,看代码都能看懂。
总结一下,这个程序的存在的缺点有:
1. 界面处理写的太烂,不怎么规矩。
2. 发送函数过于简陋,支持的验证方法少。
3. 对线程的处理不太好,对发送错误的情况考虑不太好。
4. 不支持发送附件。
我的汇编还很菜,程序中的错误还请各位高手指出。在程序的写作过程中得到了很多高手的无私帮助,在此一并表示感谢。也感谢
老罗和谢平为我的程序提供范例,为本程序的写作铺平道路。
最后,感谢Aogosoft为我们这些汇编爱好者提供这样一个交流的平台,希望高手们多多支持汇编通讯,让汇编通讯越办越好!
参考:
1. 罗云彬的《Windows环境下32位汇编语言程序设计》
2. 老罗的《用汇编语言编写ESMTP邮件发送程序》
3. 汇编通讯第五期《用汇编语言写ESMTP电子邮件发送程序》
4.https://hi.bccn.net/space-64405-do-blog-id-2002.html 在命令行下发送Email。
5.http://dev. ESMTP身份验证机制探索手记。
6.自己写的几个函数:
https://bbs.bccn.net/thread-227380-1-1.html BASE64编码函数。
https://bbs.bccn.net/thread-228639-1-1.html BASE64解码函数。
https://bbs.bccn.net/thread-227039-1-1.html CRAM-MD5算法实现函数,并没用上。
https://bbs.bccn.net/thread-226811-1-1.html MD5 算法实现函数,并没用上。
[[it] 本帖最后由 zklhp 于 2008-9-20 11:49 编辑 [/it]]