自己动手编写电子邮件接收程序

Author: 任晓磊 Date: 2000年 第10期

  2000年第1期发表了《自己动手编写电子邮件发送程序》一文后,相信很多朋友都拥有自己的个性化电子邮件发送程序了。今天,我就带大家学习用POP3协议收取邮件的方法。
#1  一、先试试手工收信
  同发信一样,你要用TELNET程序登录到POP3服务器,必要时可以打开“本地回现”选项,最好打开“选项”菜单下的“开始记录”项,用日志文件记录下你和服务器的交互信息,供以后分析用。连接时,注意把端口设为POP3协议默认的110号。
  连接成功,服务器会返回以下信息:
  +OK ...........
  字符+OK是POP3协议的返回信息。它的回应信息不像SMTP协议那样用丰富多变的数字表示,只有两个:+OK或者-ERR。其中,+OK表示连结成功,-ERR表示连结失败。
  接下来,输入
  USER <用户名>
  该命令告诉服务器你的用户名( 注意,有些服务器会区分字母大小写)。
  服务器返回+OK之后,输入
  PASS <口令>
  服务器返回+OK之后,还返回一些邮箱的统计信息,如:我的邮箱服务器返回
  +OK clyde has 2 messages
  不同的服务器返回的信息格式不太一样,所以我们可以用STAT命令来查看邮箱的情况。
  STAT命令的回应中有两个数字,分别表示邮件数量和邮件的大小。
  如果信箱里有信,就可以用RETR命令来获取邮件正文。RETR命令的格式是:
  RETR <邮件编号>
  如果返回结果第一行是+OK信息,表示成功。第二行起是邮件正文。最后一行和SMTP协议一样,是一个单独的英文句号,表示邮件的末尾部分。
  把邮件存储起来以后要用DELE命令删除邮箱中的邮件,要不然,你的信箱撑崩了可别怨我没告诉你。DELE命令的格式是:
  DELE <邮件编号>
  如果删错了,可以用RSET命令恢复所有删除的邮件。条件是你还没退出。一旦退出,就一切都晚了。
  全部完成以后,输入QUIT命令退出POP3服务器。
  另外,有一个UIDL命令,是提供一个供邮件程序使用的十六进制邮件识别码,它对我们没太大用处。
#1  二、自己编个小程序
  弄懂了POP3协议的原理,我们就可以用VB编一个小程序来完成这些工作。
  首先,在窗体上放上一个WINSOCK控件,取名POP3,一个按钮cmdStart和三个文本框,分别叫USER、PASS和SERVER,用以输入用户名、口令、服务器名等信息。
  在按钮的Click事件中启动WINSOCK控件的连接。
  Private Sub cmdStart_Click()
  POP3.RemoteHost = SERVER.Text
  POP3.RemotePort = 110
  Tag = ″conn″
  POP3.Connect
  End Sub
  对于处理邮件服务器的返回信息,有些编程爱好者喜欢用WAITFOR过程。我认为这种方法不妥。如果程序等的是+OK,但是服务器返回一个-ERR,那岂不是永远也等不到了?所以在DataArrival事件中通过判断返回的信息再进行响应的处理比较好。DataArrival事件的处理代码如下:
  Private Sub POP3_DataArrival(ByVal bytesTotal As Long)
  Dim DATA As String,StartAt As Integer,Length As Integer
  POP3.GetData DATA
   Select Case Left(DATA,1)
    Case ″+″  ′判断状态
     Select Case Tag  ′刚刚发送了哪条命令
      Case ″conn″   ′刚连接
       POP3.SendData ″USER ″ & USER & vbCrLf ′发送  ′用户名
       Tag = ″user″
      Case ″user″
       POP3.SendData ″PASS ″ & PASS & vbCrLf ′发送口令
       Tag = ″pass″
      Case ″pass″
       POP3.SendData ″STAT″ & vbCrLf
       Tag = ″stat″
      Case ″stat″  ′获取邮箱状态
       Total = Val(Mid(DATA,5,InStr(5,DATA,Chr(32)) - 5)) ′共有几封信
       If Total = 0 Then     ′如果没有信,退出
        Tag = ″quit″
        POP3.SendData ″quit″ & vbCrLf
        Exit Sub
       End If
       Current = 1  ′否则   ′开始接收
       POP3.SendData ″RETR 1″ & vbCrLf
       Tag = ″retr″
      Case ″retr″  ′接收到+OK以后初  ′始化邮件正文变量,准备接受正文
       MailText = ″″
      Case ″dele″  ′删除完毕
       Current = Current + 1
       If Current < Total Then  ′如果这 ′不是最后一封,接收下一封
        POP3.SendData ″RETR ″ & Current & vbCrLf
        Tag = ″retr″
       Else
        POP3.SendData ″QUIT″ & vbCrLf ′否则退出
        Tag = ″quit″
       End If
      Case ″quit″
       Tag = ″″
      End Select
     Case ″-″  ′如果错误,提示,退出
      MsgBox ″错误″ & DATA
      POP3.SendData ″quit″
      Tag = ″quit″   Case Else   ′其他数据,是邮件正文
      If Right(DATA,5) = vbCrLf & ″.″ & vbCrLf Then  ′最后是单独的一个句点,表示这是最后一部分
        MailText = MailText & Left(DATA,Len(DATA) - 5)
′获取邮件正文,并且保存邮件
        SaveMail
        POP3.SendData ″DELE ″ & Current & vbCrLf 
′删除该邮件
        Tag = ″dele″
      Else  ′不是最后一部分,仅获取正文,等待下一部分
        MailText = MailText & DATA
       End If
   End Select
  End Sub
  如果因为网络可能堵塞,邮件不能一次传过来。所以在接收邮件的那一段程序中须要判断接收到的是不是邮件的结尾,如果是的话就把邮件存盘,如果不是就继续接收。
#1  三、对邮件的保存和解码
  大家知道,绝大部分邮件都是经过Base64或者Quote-Printable编码的。这使邮件变得不可以直接阅读,必须对它解码才行。在邮件处理程序中,可调用SaveMail过程,用以保存已经收到的邮件。SaveMail过程的代码如下:
  Sub SaveMail()
  Open Current & ″.eml″ For Output As #1
  Print #1,MailText
  Close #1
  End Sub
  经过以上的处理,服务器上的邮件被保存成.EML的文件。这种文件可以直接由Outlook Express打开,也可以在Foxmail中导入,从而省去了我们在程序中解码的麻烦。
  以上程序在Win98,VB5中通过。