• 标 题:邮件发送库源代码
  • 作 者:nbw
  • 时 间:004-09-20,23:49
  • 链 接:http://bbs.pediy.com

  既然大家对QQ那么支持.我就把这个也放上来吧. 我那个QQ教程里面讲的是把密码存放在本地文件中.现在,你可以发到网上了...
服务器返回的验证正确的信息好象有些问题.不过不影响使用.
  支持密码验证,不过不支持匿名发送.
  现在崇尚纯"技术研究",所以大家也不要跟我要这个库和具体如何放在QQ里面了.我也没做过.....
  另外感谢风水,虽然他不来这里看帖子.
;***********************************************
;程序名称:ESmtp发送动态连接库
;作者:nbw
;日期:2004-5-20
;出处:http://www.vxer.com
;注意事项:如欲转载,请保持本程序的完整,并注明
;本动态连接库由老罗(www.luocong.com)的LCMailer改编而来.在此表示感谢
;一并感谢EA和[NE365]的所有弟兄
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\wsock32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\wsock32.lib
includelib \masm32\lib\masm32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Base64Encode         proto    :DWORD, :DWORD, :DWORD

.const
MAXNUMequ2048
MAXFILESIZEequ87380
.data
szCaption            db    "ESmtp dull by nbw, 2004-5-20", 0;对话框提示信息
szErrNoDll           db    "装载winsock.dll时出错!", 0;加载winsock库出错.
szErrSocket          db    "建立socket时出错!", 0
szErrConnect         db    "进行连接时出错!", 0
szErrAuth            db    "用户名/密码 验证失败!", 0;用户验证错误
szSuccessSend        db    "发送成功!", 0
szHeloFmt            db    "EHLO %s", 13, 10, 0
szAuth               db    "AUTH LOGIN", 13, 10, 0;AUTH LOGIN命令.告诉服务器,要进行验证了。
szUsernameFmt        db    "%s", 13, 10, 0;用户名格式
szPasswordFmt        db    "%s", 13, 10, 0;用户密码格式
szHeaderFmt          db    "MAIL FROM:%s", 13, 10;邮件发送者和接收者格式
                    db    "RCPT TO:%s", 13, 10, 0
szBody1Fmt           db    "DATA", 13, 10
                    db    "From:%s", 13, 10
                    db    "To:%s", 13, 10
                    db    "Subject:%s", 13, 10
                    db    "MIME_Version:1.0", 13, 10
                    db    "Content-type:multipart/mixed;Boundary=nboy.cnwlt.com", 13, 10, 13, 10
                    db    "--nboy.cnwlt.com", 13, 10
                    db    "Content-type:text/plain;Charset=GB2312", 13, 10
                    db    "Content-Transfer-Encoding:8bit", 13, 10, 13, 10
                    db    "%s", 13, 10, 13, 10, 0
;szBody2              db    "--nboy.cnwlt.com", 13, 10, 0
;szBody3              db    "Content-Type:application/octet-stream;Name=", 0
;szBody4              db    13, 10, 0
;szBody5              db    "Content-Disposition:attachment;FileName=", 0
;szBody6              db    13, 10, 0
;szBody7              db    "Content-Transfer-Encoding:Base64", 13, 10, 13, 10, 0
;szBody8              db    13, 10, 13, 10, 0
szBodyEnd            db    "--nboy.cnwlt.com--"
                    db    13, 10, "." , 13, 10, 0
szQuit               db    "QUIT", 13, 10, 0
reply_val            dd    0;处理服务器返回的消息.判断用户名和密码是否正确
wsadata              WSADATA        <>;用于Winsock函数,进行初始化
sin                  sockaddr_in    <>

;Base64 -> ASCII mapping table
base64_alphabet      db    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

.data?
hInstance            dd    ?
hSocket              dd    ?;Socket句柄
pContent     dd   ?;保存发送主体的内存的句柄
szBuffer             db    MAXNUM    dup(?);
szBuf1               db    MAXNUM    dup(?);处理用户名,用户密码等中间变量
szBuf2               db    MAXNUM    dup(?);
szBuf3               db    MAXNUM    dup(?);
szHelo               db    MAXNUM    dup(?);定义Hello变量,用于以后发送EHLO <Domain>\r\n命令
szUsername           db    MAXNUM    dup(?);用户名
szPassword           db    MAXNUM    dup(?);用户密码
szHeader             db    MAXNUM    dup(?);邮件发送者和接收者

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的入口函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DllEntryproc_hInstance,_dwReason,_dwReserved

moveax,TRUE
ret

DllEntryEndp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的导出函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Esmtpproc_hWnd,_lpSmtpServer,_lpUserName,_lpPassword,_lpFrom,_lpTo,_lpSubject,_lpContent
;_lpUserName是Base64_Username\r\n 中的用户名
;_lpPassword是Base64_Password\r\n 中的用户密码
;_lpFrom是发送者邮件._lpTo是收邮件者地址
;_lpSubject是邮件主题. _lpContent是邮件内容.
;以下是初始化 winsock :
pushad
;*********************************************
nop;:1000101090                      nop
nop
nop
;*********************************************
;以下是初始化 winsock :
invoke WSAStartup, 101h, addr wsadata
.if eax != NULL
invoke MessageBox, _hWnd, addr szErrNoDll, addr szCaption, MB_OK
.else
invoke socket, AF_INET, SOCK_STREAM, 0
.if eax == INVALID_SOCKET
invoke MessageBox, _hWnd, addr szErrSocket, addr szCaption, MB_OK or MB_ICONHAND
.else
mov hSocket, eax
mov sin.sin_family, AF_INET
invoke htons, 25
mov sin.sin_port, ax

invoke gethostbyname, _lpSmtpServer;获取邮件服务器
.if eax==0
popad
xoreax,eax
ret
.endif

mov eax, [eax + 12]
mov eax, [eax]
mov eax, [eax]
mov sin.sin_addr, eax
invoke connect, hSocket, addr sin, sizeof sin
.if eax!=0
popad
xoreax,eax
ret
.endif
.if eax < 0
invoke MessageBox, _hWnd, addr szErrConnect, addr szCaption, MB_OK or MB_ICONHAND;连结未成功
popad
xoreax,eax
ret
.else
invoke RtlZeroMemory, addr szBuffer, MAXNUM;分配全零内存空间.
invoke RtlZeroMemory, addr szBuf1, MAXNUM
invoke RtlZeroMemory, addr szBuf2, MAXNUM
invoke RtlZeroMemory, addr szBuf3, MAXNUM
;发送 Helo :
invoke wsprintf, addr szHelo, addr szHeloFmt, _lpSmtpServer
invoke lstrlen, addr szHelo
invoke send, hSocket, addr szHelo, eax, 0
invoke RtlZeroMemory, addr szBuffer, MAXNUM

;发送 Auth :
invoke lstrlen, addr szAuth
invoke send, hSocket, addr szAuth, eax, 0

;发送 username:
invoke lstrlen, _lpUserName;获取UserName的长度
invoke Base64Encode,  _lpUserName, addr szBuf1, eax
invoke wsprintf, addr szUsername, addr szUsernameFmt, addr szBuf1
invoke lstrlen, addr szUsername
invoke send, hSocket, addr szUsername, eax, 0
invoke RtlZeroMemory, addr szBuf1, MAXNUM
invoke RtlZeroMemory, addr szBuffer, MAXNUM

;发送 password:
invoke lstrlen, _lpPassword;获取密码的长度
invoke Base64Encode, _lpPassword, addr szBuf1, eax
invoke wsprintf, addr szPassword, addr szPasswordFmt, addr szBuf1
invoke lstrlen, addr szPassword
invoke send, hSocket, addr szPassword, eax, 0
invoke RtlZeroMemory, addr szBuf1, MAXNUM
invoke RtlZeroMemory, addr szBuffer, MAXNUM

;获得服务器返回的消息:
invoke RtlZeroMemory, addr szBuffer, MAXNUM
invoke recv, hSocket, addr szBuffer, MAXNUM, 0

;得到返回消息的前三个数字:
mov byte ptr [szBuffer + 3], 0
invoke atodw, addr szBuffer
mov reply_val, eax
invoke RtlZeroMemory, addr szBuffer, MAXNUM

;判断用户名/密码是否正确:
.if reply_val != 220
invoke MessageBox, _hWnd, addr szErrAuth, addr szCaption, MB_OK or MB_ICONHAND
popad
xoreax,eax
ret
.else
;发送 Header :
invoke wsprintf, addr szHeader, addr szHeaderFmt,  _lpFrom,  _lpTo
invoke lstrlen, addr szHeader
invoke send, hSocket, addr szHeader, eax, 0

;准备好 Body1 的内容:
;分配内存:
;(这里为了方便,只分配了 10000000 个字节,
;其实应该根据实际需要进行动态分配,否则有可能会导致错误)
invoke LocalAlloc, LPTR, 10000000
mov pContent, eax
invoke wsprintf, pContent, addr szBody1Fmt, _lpFrom , _lpTo , _lpSubject, _lpContent

;连接 "\r\n.\r\n" 到 Content 中:
invoke lstrcat, pContent, addr szBodyEnd

;发送 Content :
invoke lstrlen, pContent
invoke send, hSocket, pContent, eax, 0
invoke LocalFree, pContent
;发送“QUIT”:
invoke send, hSocket, addr szQuit, 4, 0
.endif
.endif
invoke closesocket, hSocket;关闭Socket连接
.endif
invoke WSACleanup;释放
.endif
popad
moveax,TRUE
ret
_Esmtpendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;**********************************************************
;函数功能:进行Base64编码
;入口参数:
;    source            =    传入的字符串
;    sourcelen        =    传入的字符串的长度
;出口参数:
;    destination        =    返回的编码
;**********************************************************
Base64Encode    proc    uses ebx edi esi source:DWORD, destination:DWORD, sourcelen:DWORD

   mov  esi, source
   mov  edi, destination
@@base64loop:
   xor eax, eax
   .if sourcelen == 1
lodsb                        ;source ptr + 1
mov ecx, 2                   ;bytes to output = 2
       mov edx, 03D3Dh              ;padding = 2 byte
       dec sourcelen                ;length - 1
   .elseif sourcelen == 2
       lodsw                        ;source ptr + 2
       mov ecx, 3                   ;bytes to output = 3
       mov edx, 03Dh                ;padding = 1 byte
       sub sourcelen, 2             ;length - 2
   .else
       lodsd
       mov ecx, 4                   ;bytes to output = 4
       xor edx, edx                 ;padding = 0 byte
       dec esi                      ;source ptr + 3 (+4-1)
       sub sourcelen, 3             ;length - 3 
   .endif

   xchg al,ah                       ;flip eax completely
   rol  eax, 16                     ;can this be done faster
   xchg al,ah

   @@:
   push  eax
   and   eax, 0FC000000h            ;get the last 6 high bits
   rol   eax, 6                     ;rotate them into al
   mov   al,  byte ptr [offset base64_alphabet + eax]        ;get encode character
   stosb                            ;write to destination
   pop   eax
   shl   eax, 6                     ;shift left 6 bits
   dec   ecx
   jnz   @B                         ;loop

   cmp   sourcelen, 0
   jnz   @@base64loop               ;main loop

   mov   eax, edx                   ;add padding and null terminate
   stosd

   ret
Base64Encode    endp

EndDllEntry