ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 4039|回复: 6

[VBA程序开发] Winsock POP3教程

[复制链接]

TA的精华主题

TA的得分主题

发表于 2011-3-6 17:38 | 显示全部楼层 |阅读模式
一、
了解POP3
POP3简介
    POP3是Post Office Protocol - Version 3的简称,这个协议是目前绝大多数电子邮件程序使用的收邮件程序,通过该协议,电子邮件客户端程序可以登录到电子邮件服务器上接受电子邮件。POP3协议是一种脱机模型的协议,当客户端查询并下载电子邮件后,客户端就与服务器端断开连接,用户在客户端可以随意的删除、修改邮件的内容。

POP3的通信方式
    初始时,邮件服务器通过侦听TCP端口110开始POP3服务。当客户程序需要使用服务时,它将与邮件服务器建立TCP连接。当连接建立后,客户端就可以与服务器端进行通信,POP3的客户端与服务器端的通信采用ASCII形式的命令行方式来实现,客户端向用户发送一个POP3命令(POP3命令是大小写不敏感的),POP3命令由一个命令和一些参数组成。所有命令以一个CRLF对结束。命令和参数由可打印的ASCII字符组成,它们之间由空格间隔。命令一般是三到四个字母,每个参数却可达40个字符长。邮件服务器端接收响应,也会向客户端发送一个ASCII格式的响应消息。
    POP3响应由一个状态码和一个可能跟有附加信息的命令组成。所有响应也是由CRLF对结束。现在有两种状态码,"确定" ("+OK")和"失败" ("-ERR")(服务器返回的"+OK"或者"-ERR"必须是大写的)。
    邮件服务器返回的相应可以是单行的或者多行的文本,对于多行文本,没一行都是以一个回车换行(CRLF)符作为结尾,如果返回的响应中包含了符号"CRLF.CRLF"(其中"."的ASCII码为46),那么说明服务器返回的响应已经结束。
    在生命周期中,POP3会话有几个不同的状态。一旦TCP连接被打开,而且邮件服务器发送了确认信息,此过程就进入了“认证”(AUTHORIZATION)状态。在此状态中,客户必须向邮件服务器确认自己是其客户。一旦认证成功,邮件服务器就获取与客户邮件相关的资源,此时这一过程进入了“处理”(TRANSACTION)状态。在此状态中,客户提出服务请求,当客户发出QUIT命令时,此过程进入了“更新”(UPDATE)状态。在此状态中,邮件服务器释放在"操作"状态中取得的资源,并发送消息,终止连接。
    作为一个脱机模型的协议,邮件服务器必须有一个自动断开连接的计时器,这个计时器最少不能少于10分钟。超过这个时限后,邮件服务器不会进入“更新”状态而是直接断开TCP连接,同时不会对服务器上的消息做修改,也不会向客户端发送任何响应消息。


POP3得简单范例
    下面通过一个简单的范例来演示如何使用Winsock控件通过POP3协议来实现登录到邮件服务器然后退出。
    创建一个新工程,在其中添加一个TextBox,将它的Name设置为txtMSG,将MultiLine属性设置为True,将这个文本框的尺寸摄制的尽可能大。然后添加四个CommandButton控件,将他们的Name分别设置为cmdConnect、cmdLoggin、cmdList、cmdQuit,它们的作用分别是连接、登录、邮件列表和退出邮件服务器。然后添加一个Winsock控件,将Protocol属性设置为0 - sckTCPProtocol,将RemoteHost属性设置位POP3服务器的地址,例如POP.163.com,将RemotePort设置为服务器的POP3服务端口,一般是110,将LocalPort设置为一个未使用的端口,例如410。
    然后实现的代码如下:

Private Sub cmdConnect_Click()
    '连接到邮件服务器
    Winsock1.Connect
End Sub

Private Sub cmdList_Click()
    '列出邮件服务器上的邮件
    Winsock1.SendData "LIST" & vbCrLf
End Sub

Private Sub cmdLoggin_Click()
    '登录到邮件服务器
    Winsock1.SendData "USER xxxxx" & vbCrLf
    Winsock1.SendData "PASS aaaaa" & vbCrLf
End Sub

Private Sub cmdQuit_Click()
    '发送退出消息
    Winsock1.SendData "QUIT" & vbCrLf
End Sub


Private Sub Winsock1_Close()
    '关闭与服务器的连接
    Winsock1.Close
End Sub

Private Sub Winsock1_Connect()
    Debug.Print "connection "
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Dim s As String
   
    '获取服务器的响应信息
    s = Space(bytesTotal)
    Winsock1.GetData s
    txtMSG.Text = txtMSG.Text & "message: " & s
End Sub

Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal

HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
    '输出错误信息
    Debug.Print Description
    Debug.Print Number
End Sub

    要运行上面的代码,需要将上面的代码的:

    Winsock1.SendData "USER xxxxx" & vbCrLf
    Winsock1.SendData "PASS aaaaa" & vbCrLf


    中的xxxxx设置为登录POP3服务器的用户名,将aaaaa设置为登录POP3服务器的密码。

    运行程序,点击cmdConnect连接到POP3服务器,点击cmdLoggin登录到邮件服务器,点击cmdList将服务器上面的邮件列出来,点击cmdQuit退出登录。如果POP3地址设置正确,用户名和密码正确,在txtMSG中应该列出如下的内容:



    现在再看看上面的代码,在上面的代码中,点击cmdLoggin登录到邮件服务器,登录成功后邮件服务器会返回类似:+OK POP3 Welcome to quarkmail server version 1.2.1  这样的响应。这时的状态是“认证”状态,在这个状态下,客户端需要发送登录命令登录到邮件服务器,这里我们发送的是“USER”和“PASS”命令登录,登录成功后邮件服务器会返回 +OK 的成功响应,否则会返回 -ERR 的错误消息。
    登录成功后,这时的状态是“处理”状态,这时就可以通过发送例如“LIST”等命令来对邮件服务器上的邮件进行处理。
    在处理完邮件后,单击cmdQuit发送“QUIT”命令退出登录,在退出成功后,状态变为“更新”状态,同时邮件服务器会断开TCP连接,客户端得Winsock会接收到关闭连接的消息,所以需要在Winsock的Close事件中关闭客户端得TCP连接。
    在POP3协议中,对于客户端发送的命令,无论是有效的还是无效的命令,邮件服务器都必须对其作出响应,在我们的程序中,我们只需要在Winsock的DataArrival事件中获得服务器的响应消息并且根据POP3协议的规定对消息进行处理就可以了解邮件服务器在跟我们“说什么”。至于发送到邮件服务器的命令的详细解释以及邮件服务器响应的消息的含义,教程将在以后逐步的向大家介绍。

[ 本帖最后由 HHAAMM 于 2011-3-6 21:29 编辑 ]

TA的精华主题

TA的得分主题

 楼主| 发表于 2011-3-6 17:39 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
二、
获取邮件
LIST命令和RETR命令
    LIST命令和RETR命令只能在“处理”状态下执行,就是说只有在用户登录以后才可以执行这两个命令。
LIST命令获得邮件服务器中的邮件列表。该命令的格式如下:

    LIST [msg]

    其中参数msg是可选的参数,该参数指定要列举的邮件的编号,该参数不能指定为一个已经标记为删除的邮件的编号。
    如果没有指定参数而且命令调用成功,邮件服务器首先会返回服务器中的所有邮件列表,这个列表以一个+OK开头的字符串作为起始。对于

邮件服务器中的每一个邮件,邮件服务器都会返回一行字符串,为了便于分析,这行字符串应该由邮件编号 + 一个空格 + 邮件的尺寸 组成。

在邮件列表的结尾,邮件服务器会返回一个vbCRLF + "." + vbCRLF的字符串作为列表的结尾。例如在教程一中点击“邮件列表”按钮在文本框

中输出的字符串所示。
   
注意:不同的邮件服务器返回的内容可能有所不同,有些邮件服务器返回的信息会更多一些(例如在+OK后面返回总邮件数和邮件总尺寸等)。

但是标准的POP3协议所描述的返回内容只有上面这些,所以在开发过程中需要注意,不要把一些邮件服务器所返回的附加内容作为标准在你的

代码里面实现,这样的话可能在其他邮件服务器上面就通不过。


RETR命令获得邮件服务器中的邮件内容,该命令的格式如下:

    RETR msg

    其中参数msg是必选的参数,该参数指定要获得的邮件的编号,该参数不能指定为一个已经标记为删除的邮件的编号。
    如果命令调用成功,邮件服务器会返回指定的邮件的内容,返回的内容头一行是+OK,然后是邮件内容,最后是一个vbCRLF + "." +

vbCRLF的字符的串作为结尾。

    在Winsock编程中,对于LIST命令和RETR命令,服务器返回的内容是分多次返回的,所以会多次触发DataArrival事件,所以需要在程序中

设置命令状态,在发出LIST或者RETR命令后将程序的状态置于LIST或者RETR状态下,在这个状态下所有收到的内容都是服务器返回的响应的组

成部分,直到收到结束字符串vbCRLF + "." + vbCRLF。


    下面是如何通过Winsock发送LIST命令和RETR命令获得邮件列表以及获取邮件内容,在教程一的窗体中再增加一个CommandButton按钮,

Name属性为:cmdRETR。


Enum enumPOPCommand
    popUSER = 1
    popPASS = 2
    popQUIT = 3
    popLIST = 4
    popDELETE = 5
    popRETR = 6
    popNONE = 999
End Enum

Private m_Command As enumPOPCommand
Private m_MailLists As New Collection
Private m_Messages As String
Private m_MailMessage As String
Private m_MessageCout As Integer

Sub strListsToCollection(strLists As String, coll As Collection)
    Dim s() As String
    Dim i As Integer
    Dim count As Integer
   
    s = Split(strLists, vbCrLf)
   
    '获得邮件列表和邮件数
    For i = LBound(s) To UBound(s)
        If (Trim(s(i)) <> "") And (Trim(s(i)) <> ".") Then
            coll.Add Trim(s(i))
            count = count + 1
        End If
    Next i
   
    MsgBox "共" & count & "个邮件!"
End Sub

Private Sub cmdConnect_Click()
    '连接到邮件服务器
    Winsock1.Connect
End Sub

Private Sub cmdList_Click()
    '列出邮件服务器上的邮件
    Winsock1.SendData "LIST" & vbCrLf
    '切换当前状态
    m_Command = popLIST
End Sub

Private Sub cmdLoggin_Click()
    '登录到邮件服务器
    Winsock1.SendData "USER chenrui@applevb.com" & vbCrLf
    Winsock1.SendData "PASS xxxxxx" & vbCrLf
End Sub

Private Sub cmdQuit_Click()
    '发送退出消息
    m_Command = popQUIT
    Winsock1.SendData "QUIT" & vbCrLf
End Sub


Private Sub cmdRETR_Click()
    Dim i
      
    '获得服务器上面的第二封邮件
    m_Command = popRETR
    m_MailMessage = ""
    Winsock1.SendData "RETR 2" & vbCrLf
End Sub

Private Sub Winsock1_Close()
    '关闭与服务器的连接
    Winsock1.Close
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Dim s As String
    Dim i As Integer
   
    '获取服务器的响应信息
    s = Space(bytesTotal)
    Winsock1.GetData s
    txtMSG.Text = txtMSG.Text & "message: " & s
   
    Select Case m_Command
        '邮件列表LIST状态
        Case enumPOPCommand.popLIST
            If Left$(s, 4) = "+OK " Then
                m_Messages = ""
            ElseIf Left$(s, 4) = "+ERR" Then
                m_Command = popNONE
            Else
                m_Messages = m_Messages + s
                If InStr(1, s, vbCrLf & "." & vbCrLf) > 0 Then
                    strListsToCollection m_Messages, m_MailLists
                    m_Command = popNONE
                End If
            End If
            
        '获取邮件RETR状态
        Case enumPOPCommand.popRETR
            If Left$(s, 4) = "+OK " Then
                m_MailMessage = ""
            ElseIf Left$(s, 4) = "+ERR" Then
                m_Command = popNONE
            Else
                m_MailMessage = m_MailMessage + s
                If InStr(1, s, vbCrLf & "." & vbCrLf) > 0 Then
                    m_Command = popNONE
                    txtMSG = m_MailMessage
                End If
            End If
    End Select
End Sub

[ 本帖最后由 HHAAMM 于 2011-3-6 21:29 编辑 ]

TA的精华主题

TA的得分主题

 楼主| 发表于 2011-3-6 17:40 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
SMTP&ESMTP&POP3 简要命令
SMTP命令:
HELO fqdn  识别发送SMTP主机
MAIL FROM:<sender>  识别邮件发件人
RCPT TO:<recipient> 识别邮件收信人信息
DATA    指示发送主机邮件数据发送已经准备好
RSET    中断当前邮件传输
VRFY string  允许发送主机在发送邮件前验证收件人的有效性
HELP    列出接收主机能支持的SMTP命令
QUIT    中断并关闭SMTP会话
TURN    触发收信服务器发送队列中的消息到发信服务器

ESMTP命令:

ATRN    只有会话是被验证的才运行
ETRN    指定邮件传递的远程主机
PIPELINING   允许SMTP命令批量发送而不需要得到回应
CHUNKING     允许更有效的发送大的MIME邮件
X-EXPS GSSAPI NTLM LOGIN  使用一种有效的认证机制,Kerberos和NTLM
X-EXPS=LOGIN  使用一种认证机制支持兼容Exchange Server5.5的NTLM
X-LINK2STATE  指定支持Exchange 2000连接状态命令
XEXCH50    用于在邮件中传输Exchang特定的内容
STARTTLS   在SMTP客户和服务器之间提供SSL连接

POP3命令:

USER name   提供用户名
PASS string 提供用户密码
STAT        提供邮箱状态
LIST        列举出邮件的项目
RETR msg    读取邮件
DELE msg    将邮件标记为删除
NOOP        不做任何事情,仅返回一个回应
RSET        中断当前操作,将标记为删除的邮件恢复
QUIT        退出POP3会话

[ 本帖最后由 HHAAMM 于 2011-3-6 21:30 编辑 ]

TA的精华主题

TA的得分主题

 楼主| 发表于 2011-3-6 20:35 | 显示全部楼层
邮件的内容传输编码:使用base64

TA的精华主题

TA的得分主题

发表于 2011-6-7 14:15 | 显示全部楼层

请问:为什么新浪服务器登不进去咧?

版主:
 你好!
 用你的程序,登录163正常。
 但登录sina就无法验证户名密码(Connect状态为7)
 但利用你的作品《写的用VB写的邮件阅读工具》,登录Sina是正常的。能告诉我为什么吗?
 请教了!

TA的精华主题

TA的得分主题

发表于 2011-6-8 13:21 | 显示全部楼层
版主:
为什么getdata 得到的是乱码呢 
如:xPrKx7fx09DV4tH5tcS40Mrco6zJ7bHfvqG53NPQtq7N4tPvtcTIy7LFo6y1q8i0w7uw7LeowvrX
48T6tcS3rdLr0OjH86O/DQq08LC4uty88rWlo6y6w7XEt63S66OsuPzSqtPQusO1xNeo0rWxs76w
o6ENCsvmxOPS66Os1tC5+ret0uvQrbvhyq6087et0uvG89K11q7Su6Os07XT0NbQufrX7rbgtcS4
99DQ0rW499Pv0dS3rdLr16iyxaOos6y5/TbN8sP7o6mjrNPD16jStbGzvrC1xLet0uvXqLLFzqrE
+szhuam/7L3doaK+rbzDtcS3rdLrt/7O8aGjDQrE+rXEy/nT0Let0uvOysziv8nS1M2ouf2hsMvm
xOPS66GxyMu5pLet0uvN+NW+d3d3LnN1aW5peWkuY29ttcO1vbDv1vqho8T6v8nS1NTazfjJz8q1
z9bPwrWloaK5wLzboaLWp7i2oaLK1bjltcTSu9W+yr21xLet0uu3/s7xoaMNCs6qwvrX47K7zay/
zbuntcS3rdLr0OjH86OsobDL5sTj0uuhsczYsfDNxrP20tTPwszYyau3rdLrt/7O8aO6DQoqyOfE
+tDo0qrX7r/sy9m2yLXEt63S66OsxOO/ydLU0aHU8aGwNTDX1jjUqtOi0++/7L3dt63S66Gxo7uy
6b+0z+rH6Q0KKsjnxPqzpMbavq28w7XEt63S66OsxPq/ydLU0aHU8aGwsPzUwrf+zvGhsaOo06LT
7zE4MNSqo6zI1S+6q9PvMzAw1KqjrLeoL7btMzIw1KqjrLXCL9LitPPA+yAzNDDUqqOpo7uy6b+0
z+rH6Q0KKsjnxPq+rbOj09C3rdLr0OjH86OsobDL5sTj0uuhsc/W1f3NxrP2s+TWtdPFu9277rav
o6zP1tTazqrE+rXEobDL5sTj0uuhsdXKu6ez5Na1o6y8tL/Jz+3K3LPkMTAwMMvNMTAwtcTTxbvd
xbaho7Lpv7TP6sfpDQrOqsT6zOG5qb/svd3XqNK1tcS3rdLrt/7O8dK71rHKx87Sw8fFrMGmtcTE
v7Hqo6ENCg0K0rLPo837xPq9q87Sw8e1xMjIs8C0q7KluPjE+rXEx9fT0aOsvd+zz8baxc7E+rXE
zca89qGjDQq0y9bCDQrL5sTj0usNCnd3dy5zdWluaXlpLmNvbQ0Kv827p7f+zvE6MDA4Ni0xMC04
NTgwNjUxMg0KRS1tYWlsOnNlcnZpY2VAc3Vpbml5aS5jb20=

TA的精华主题

TA的得分主题

发表于 2017-4-26 22:26 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
收藏,以后参阅。谢谢
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-24 02:05 , Processed in 0.032303 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表