Esmtp邮件发送程序

        发送邮件使用的是SMTP协议,也称简单邮件传输协议。现在在网上搜到的代码或者例子大都是SMTP协议的,但是而今大多数邮件服务器都已经采用验证式的STMP协议了,所以这些代码或者例子常常得到无法调试成功的结果,这给了我们初学者一个不小的打击。其实所谓验证式的SMTP协议,只不过是在原来的SMTP协议的基础上加上了一个用户密码验证,验证后的协议内容跟原来别无二致。这种新的验证式SMTP协议称为ESMTP,也即扩展简单邮件传输协议。
        之所以要扩展SMTP协议,是为了防止垃圾邮件的日益泛滥,阻止未经验证的垃圾邮件制造者随意使用这项服务。但我个人认为ESMTP并没达到目的(粗浅认识),现在的免费邮箱一大把,随便注册一个一样可以发一大堆垃圾邮件啊。(不过由于是经过了验证的,经过服务器的垃圾邮件过滤就可以把你这个邮箱帐号给~~,"反正是黑名单吧")。
    ESMTP协议是一种C/S应答式协议,邮件客户端发送一个请求,服务器返回相应的内容。
    C:连接服务器...   (通过connect函数)
    S:220
    C:HELO username
    S:250
    C:AUTH LOGIN
    S:334
    C:Base64(username)    (经过Base64编码后的用户名)
    S:334
    C:Base64(password)    (经过Base64编码后的密码)
    S:235
    C:MAIL FROM: <XiaoMing@163.com>    ()
    S:250
    C:RCPT TO: <XiaoHong@163.com>      ()
    S:250
    C:DATA
    S:354
    C:
    S:250
    C:
    S:221

.386
.model flat, stdcall
option casemap:none

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
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/user32.lib
includelib /masm32/lib/comdlg32.lib
includelib /masm32/lib/wsock32.lib

.const
IDI_MAIN    equ 1
IDC_EDIT_ATTACHMENT equ 3008
IDC_BUTTON_BROWSE equ 3009

DlgMain              equ 1
IDC_EDIT_SMTPSERVER equ 1
IDC_EDIT_USERNAME    equ 2
IDC_EDIT_PASSWORD    equ 3
IDC_EDIT_FROM     equ 4
IDC_EDIT_TO      equ 5
IDC_EDIT_SUBJECT    equ 6
IDC_EDIT_CONTENT    equ 7
IDC_BUTTON_SEND  equ 8
IDC_VAl              equ 9

TCP_PORT equ 25

MAIL_HELO   equ  1
MAIL_LOGIN  equ  2
MAIL_USER   equ  3
MAIL_PASS   equ  4
MAIL_FROM   equ  5
MAIL_RCPT   equ  6
MAIL_DATA   equ  7
MAIL_DOT    equ  8
MAIL_QUIT   equ  9

.data

;下面是为了方便调试,预设的各项参数:
sz1     db "smtp.163.com", 0
;sz2     db "zhangyuming123456", 0
;sz3     db "789789", 0
;sz4     db "zhangyuming123456@163.com", 0
;sz5     db "zhangyuming123456@163.com", 0
;sz6     db "最近如何?", 0
;sz7     db "你好吗?", 0

szCaption         db "ESMTP邮件发送程序",0
szServerIPErr     db "SMTP服务器地址解析失败!",0
szConnectErr      db "连接服务器出错!",0
szSendOK          db    "邮件发送成功!",0
szSendErr         db    "邮件发送失败!",0

szHeloFmt            db    "HELO %s", 13, 10, 0
szLoginFmt           db    "AUTH LOGIN", 13, 10, 0
szUserPassFmt        db    "%s", 13, 10, 0
szFromFmt            db    "MAIL FROM: <%s>", 13, 10,0
szRcptFmt            db    "RCPT TO: <%s>", 13, 10, 0
szDataFmt            db    "DATA", 13, 10,0
szQuitFmt            db    "QUIT",13,10,0
szTextFmt            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:text/plain;Charset=GB2312", 13, 10
                     db    "Content-Transfer-Encoding:8bit", 13, 10, 13, 10
                     db    "%s", 13, 10,13,10, ".",13, 10, 0

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

szFmt db  "%d",0

.data?
hInstance   dd ?
hSocket    dd ?
hWinMain          dd ?
szServer  db  256  dup  (?)
szUser    db  256  dup  (?)
szPass    db  256  dup  (?)
szFrom    db  256  dup  (?)
szRcpt    db  256  dup  (?)
szSubject db  256  dup  (?)
szText    db  30000  dup  (?)
szBuf1    db  65536  dup  (?)

.code
Base64Encode    proc    uses ebx edi esi source:DWORD, destination:DWORD
    LOCAL    sourcelen:DWORD

    invoke lstrlen, source
    mov sourcelen, eax

    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

_GetText proc uses ebx esi

        invoke GetDlgItemText,hWinMain,IDC_EDIT_SMTPSERVER,addr szServer,256
        invoke GetDlgItemText,hWinMain,IDC_EDIT_USERNAME,addr szUser,256
        invoke GetDlgItemText,hWinMain,IDC_EDIT_PASSWORD,addr szPass,256
        invoke GetDlgItemText,hWinMain,IDC_EDIT_FROM,addr szFrom,256
        invoke GetDlgItemText,hWinMain,IDC_EDIT_TO,addr szRcpt,256
        invoke GetDlgItemText,hWinMain,IDC_EDIT_SUBJECT,addr szSubject,256
        invoke GetDlgItemText,hWinMain,IDC_EDIT_CONTENT,addr szText,30000
        ret
_GetText endp

_EnableCtrl proc _State
    local nID
   
    mov nID,1
    .while nID<=8
        invoke GetDlgItem,hWinMain,nID
        invoke EnableWindow,eax,_State
        inc nID
    .endw

    ret
_EnableCtrl endp

_WaitFor proc _nNum
    local @szBuf[1024]:BYTE
    local @stFdSet:fd_set,@stTimeval:timeval
    ;local @nNum
   
    mov @stFdSet.fd_count,1
    push hSocket
    pop @stFdSet.fd_array
    mov @stTimeval.tv_sec,60
    mov @stTimeval.tv_usec,0              
    invoke select,0,addr @stFdSet,NULL,NULL,addr @stTimeval
    .if eax==0 || eax==SOCKET_ERROR
        invoke MessageBox,hWinMain,addr szSendErr,addr szCaption,MB_OK
        invoke _EnableCtrl,TRUE
        invoke ExitThread,NULL
        ;邮件发送失败
    .endif
    invoke recv,hSocket,addr @szBuf,sizeof @szBuf,0
    invoke MessageBox,hWinMain,addr @szBuf,addr szCaption,MB_OK
    mov BYTE ptr @szBuf[3],0
   
    invoke SetDlgItemText,hWinMain,IDC_VAl,addr @szBuf
    invoke GetDlgItemInt,hWinMain,IDC_VAl,NULL,FALSE
   
    ;mov @nNum,eax
    ;invoke wsprintf,addr @szBuf,addr szFmt,@nNum
    ;invoke MessageBox,NULL,addr @szBuf,NULL,MB_OK
    ;invoke wsprintf,addr @szBuf,addr szFmt,_nNum
    ;invoke MessageBox,NULL,addr @szBuf,NULL,MB_OK
    ;mov eax,@nNum
    .if eax != _nNum     
        invoke MessageBox,hWinMain,addr szSendErr,addr szCaption,MB_OK
        invoke _EnableCtrl,TRUE
        invoke ExitThread,NULL
        ;邮件发送失败
    .endif
   
    ret
_WaitFor endp

_SendCmd proc _StateID
   
    mov eax,_StateID
    .if eax==MAIL_HELO
        invoke wsprintf,addr szBuf1,addr szHeloFmt,addr szUser
    .elseif eax==MAIL_LOGIN
        invoke lstrcpy,addr szBuf1,addr szLoginFmt
    .elseif eax==MAIL_USER
        invoke Base64Encode,addr szUser,addr szBuf1
        ;invoke MessageBox,NULL,addr @szBuf1,NULL,MB_OK
        invoke wsprintf,addr szBuf1,addr szUserPassFmt,addr szBuf1
    .elseif eax==MAIL_PASS
        invoke Base64Encode,addr szPass,addr szBuf1
        ;invoke MessageBox,NULL,addr @szBuf1,NULL,MB_OK
        invoke wsprintf,addr szBuf1,addr szUserPassFmt,addr szBuf1
    .elseif eax==MAIL_FROM
        invoke wsprintf,addr szBuf1,addr szFromFmt,addr szFrom
    .elseif eax==MAIL_RCPT
        invoke wsprintf,addr szBuf1,addr szRcptFmt,addr szRcpt
    .elseif eax==MAIL_DATA
        invoke lstrcpy,addr szBuf1,addr szDataFmt
    .elseif eax==MAIL_DOT
        invoke wsprintf,addr szBuf1,addr szTextFmt,addr szFrom,addr szRcpt,addr szSubject,addr szText
    .else
        invoke lstrcpy,addr szBuf1,addr szQuitFmt
    .endif
   
    invoke lstrlen,addr szBuf1
    invoke send,hSocket,addr szBuf1,eax,0
    invoke MessageBox,hWinMain,addr szBuf1,addr szCaption,MB_OK
    .if eax==SOCKET_ERROR
        invoke MessageBox,hWinMain,addr szSendErr,addr szCaption,MB_OK
        invoke _EnableCtrl,TRUE
        invoke ExitThread,NULL
        ;邮件发送失败
    .endif
       
    ret
_SendCmd endp

_SendThread proc lParam
     local @stSin:sockaddr_in
    
     invoke _GetText
     invoke _EnableCtrl,FALSE
    
     invoke RtlZeroMemory,addr @stSin,sizeof @stSin
     ;invoke _GetHostIP,eax
     invoke gethostbyname , addr szServer
                        mov eax, [eax + 12]
                        mov eax, [eax]
                        mov eax, [eax]
                       
     .if eax==0
        invoke MessageBox,hWinMain,addr szServerIPErr,addr szCaption,MB_OK
        JMP smtp_ERROR
        ;SMTP服务器地址错误
     .endif
     mov @stSin.sin_addr,eax
     mov @stSin.sin_family,AF_INET
     invoke htons,TCP_PORT
     mov @stSin.sin_port,ax
     invoke socket,AF_INET,SOCK_STREAM,0
     mov hSocket,eax
     invoke connect,hSocket,addr @stSin,sizeof @stSin
     .if eax==SOCKET_ERROR
         invoke MessageBox,hWinMain,addr szConnectErr,addr szCaption,MB_OK
         JMP smtp_ERROR
         ;邮件发送失败
     .endif
    
     invoke _WaitFor,220
     invoke _SendCmd,MAIL_HELO
    
     invoke _WaitFor,250
     invoke _SendCmd,MAIL_LOGIN
    
     invoke _WaitFor,334
     invoke _SendCmd,MAIL_USER
    
     invoke _WaitFor,334
     invoke _SendCmd,MAIL_PASS
    
     invoke _WaitFor,235
     invoke _SendCmd,MAIL_FROM
    
     invoke _WaitFor,250
     invoke _SendCmd,MAIL_RCPT
    
     invoke _WaitFor,250
     invoke _SendCmd,MAIL_DATA
    
     invoke _WaitFor,354
     invoke _SendCmd,MAIL_DOT
    
     invoke _WaitFor,250
     invoke _SendCmd,MAIL_QUIT
    
     invoke _WaitFor,221
    
     invoke MessageBox,hWinMain,addr szSendOK,addr szCaption,MB_OK
    
     invoke closesocket,hSocket
     invoke _EnableCtrl,TRUE
     ret
smtp_ERROR:
     invoke MessageBox,hWinMain,addr szSendErr,addr szCaption,MB_OK
     invoke _EnableCtrl,TRUE
     ret
_SendThread endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
        LOCAL @stWsa: WSADATA
 .if uMsg == WM_CLOSE
  invoke WSACleanup
  invoke EndDialog, hWnd, 0

 .elseif uMsg == WM_INITDIALOG
  push hWnd
  pop hWinMain
  invoke WSAStartup,101h,addr @stWsa
  
  invoke LoadIcon, hInstance, IDI_MAIN
  invoke SendMessage, hWnd, WM_SETICON, ICON_SMALL, eax

  ;下面是为了方便调试,填入预设的各项参数:
  invoke SetDlgItemText, hWnd, IDC_EDIT_SMTPSERVER, addr sz1
  ;invoke SetDlgItemText, hWnd, IDC_EDIT_USERNAME, addr sz2
  ;invoke SetDlgItemText, hWnd, IDC_EDIT_PASSWORD, addr sz3
  ;invoke SetDlgItemText, hWnd, IDC_EDIT_FROM, addr sz4
  ;invoke SetDlgItemText, hWnd, IDC_EDIT_TO, addr sz5
  ;invoke SetDlgItemText, hWnd, IDC_EDIT_SUBJECT, addr sz6
  ;invoke SetDlgItemText, hWnd, IDC_EDIT_CONTENT, addr sz7
  
  invoke GetDlgItem,hWnd,IDC_VAl
  invoke ShowWindow,eax,SW_HIDE
  
 .elseif uMsg == WM_COMMAND
            mov eax,wParam
            .if ax==IDC_BUTTON_SEND
                push ecx
                invoke CreateThread,NULL,0,Offset _SendThread,0,NULL,esp
                pop ecx
                invoke CloseHandle,eax
            .endif 
 .else
  mov eax, FALSE
  ret
 .endif
 mov eax, TRUE
 ret
WndProc endp

Start:
 invoke GetModuleHandle, NULL
 mov hInstance, eax
 invoke DialogBoxParam, hInstance, DlgMain, 0, WndProc, 0
 invoke ExitProcess, eax
 
 end Start

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值