郵件傳送庫原始碼

看雪資料發表於2004-09-20

  既然大家對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 (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

相關文章