当前位置: 首页 > news >正文

Delphi中怎样监视POP3信箱?

  本文将向大家介绍怎样编写自己的信箱监视程序,程序将直接调用WinSock函数来进行网络通信。除了具备WinSock 编程知识之外,还必须了解POP3协议。下面是对POP3的一个粗略的介绍,读者可以参看RFC1225更为详细地了解该协议。

一、关于POP3协议  

POP3服务器程序通常在TCP端口110提供服务。当客户想要使用服务时,它便与服务器建立一个TCP连接。一旦连接建立,POP3服务器就向客户发送一条欢迎消息。然后客户开始给服务器发送命令,服务器则给出相应的回答。POP3的命令由一个关键词或者关键词加参数组成。每个命令以回车换行(0xD0xA)作为结束标志。对于所有的命令,POP3服务器都会提供一个回答。服务器的回答由一个状态标志加一些附加信息组成。目前使用的两个标志是“+OK”和“-ERR”,分别表示客户的命令是否合法。所有的回答也是以回车换行结束。  

与本文讨论的话题相关的四个POP3命令是USER、PASS、LIST和QUIT。

USER命令
格式USERname

  其中name是用户在该POP3服务器上的用户标识。客户应该在接到服务器的欢迎消息后或者在上一个USER或者PASS失败之后可以发送此命令。

PASS命令
格式PASSstring

  其中string为该用户的密码。客户在发送了USER命令并且收到了+OK的回答之后方可发送此命令。如果用户名和密码都正确,服务器回答+OK,否则-ERR。

LIST命令
格式LIST

  如果该用户有邮件,则LIST命令会回答+OK,并列出所有邮件的标识符和大小(每个邮件一行),最后一个仅包含一个句点的行(0xD0xA0x2E)表示整个回答的结束。如果该用户没有邮件,有些服务器会返回-ERR,有些在可能返回一个+OK和一个仅包含一个句点的行。当然,客户必须在PASS命令通过之后客户程序才能给服务器发送LIST命令。

QUIT命令

 从POP3服务器上退出登录。

二、实现相关函数
  接下来我们按照POP3协议所定义的通信规则来实现一个名叫POP3CheckMail的函数,只要调用此函数,我们就可以检测信箱了。

  下面的代码是用与Delphi4兼容的Pascal语言实现的,我们必须包含WinSock单元,并且在调用下列函数之前初始化好WinSock动态连接库。初始化WinSock 动态连接库的代码如下:

  ifWSAStartup($002,wsadata)<>0thenHalt;

  POP3CheckMail的原型如下:

  functionPOP3CheckMail(Email,Password:String;varMailList:TStringList;var ErrorMsg:String):Bool;

  参数说明:

  Email和Password分别为用户的email信箱名和口令。

  变量参数MailList用于返回邮件的标识和大小,MailList.Count表示邮件的封数。

  变量参数ErrorMsg返回出错消息。

  以下是POP3CheckMail及其它所用到的函数的实现代码。

Connect_Server函数

  功能:与指定的主机建立一个TCP连接,返回一个Socket描述符。参数host指定主机的名字,Port指定端口号。

functionConnect_Server(host:string;Port:integer):integer;
vari:integer;
   p:^LongInt;
   phe:pHostEnt;
   sin:sockaddr_in;
begin
sin.sin_family:=AF_INET;
sin.sin_port:=htons(Port);
//GettheIPforhost,allowingfordotteddecimal
phe:=gethostbyname(pchar(host));
ifphe<>nil
thenbegin
    p:=Pointer(phe^.h_addr_list^);
    sin.sin_addr.s_addr:=p^;
    end
elsebegin
    i:=inet_addr(PChar(Host));
    ifi<>-1then sin.sin_addr.S_addr:=i
    end;
//createasocket
Result:=socket(PF_INET,SOCK_STREAM,0);
if(Result=INVALID_SOCKET)thenExit;
//connecttoserver
ifConnect(Result,sin,sizeof(sin))=SOCKET_ERROR
thenbegin{Errorhandling}end;
end;

Write_Socket函数

  功能:向Socket写入一个字符串。

functionWrite_Socket(sockfd:Integer;consts:string):Integer;
begin
result:=Winsock.Send(sockfd,pointer(s)^,Length(s),0)
end;

Socket_Readline函数

  功能:从Socket上读取一行。

functionSocket_Readline(sockfd:Integer):String;
//Readuntil#10
varS:String;buf:array[0..1]ofChar;
   n:Cardinal;
begin
buf[0]:=#0;buf[1]:=#0;S:=‘';
n:=recv(sockfd,Buf,1,0);
whilen>0dobegin
          buf[1]:=#0;
          S:=S+buf;
          if(buf[0]=#10)thenBreak;
          n:=recv(sockfd,buf,1,0);
        end;
Result:=Trim(S);
end;

Pop3Response函数

  功能:读取POP3服务器的一行返回信息,如果是“+OK”则函数返回TURE,如果是“-ERR”则返回FALSE。

functionPop3Response(Sockfd:Integer):Bool;
var S:string;
begin
 S:=socket_readline(sockfd);
 ifcopy(s,1,3)=‘+OK'thenResult:=True
 else{ifcopy(s,1,4)=‘-ERR'then}Result:=False;
end;

POP3CheckMail函数

  功能:检测名字为email的信箱,如果有新邮件,则通过变量参数MailList将每一封邮件的大小返回。

functionPOP3CheckMail
(Email,Password:String;varMailList:
 TStringList;varErrorMsg:String):Bool;
varsockfd,i:integer;
   S,Host,User:String;
begin
Result:=False;ErrorMsg:=‘';
ifMailList=nilthenExit;
S:=Trim(Email);
i:=Pos(‘@',Email);
User:=Trim(Copy(S,1,i-1));
Host:=Trim(Copy(S,i+1,Length(Email)-i));
MailList.Clear;
if(user=‘')or(host=‘')thenbegin 
ErrorMsg:=‘Invalidemailaddress.';exit;end;
if(Host[1]=‘[')and(Host[Length(host)]=‘]')
thenbeginHost[1]:=‘';Host[Length(host)]:=#0;end;
Host:=Trim(host);
sockfd:=Connect_Server(Host,110);
ifnotPop3Response(sockfd)thenbeginErrorMsg:=
‘Cannotconnecttoserver';exit;end;
Write_Socket(sockfd,‘USER'+User+#13#10);
IFNOTPOP3Response(sockfd)thenbeginErrorMsg:=
‘USERfailed';Exit;end;
Write_Socket(sockfd,‘PASS'+Password+#13#10);
IFNOTPOP3Response(sockfd)thenbeginErrorMsg:=
‘PASSfailed';Exit;end;
Write_Socket(sockfd,‘LIST'#13#10);
POP3Response(sockfd);
whiletruedobegin
   s:=Socket_readline(sockfd);
   ifs=‘.'thenBREAK;
   MailList.Add(S);
end;
Write_Socket(sockfd,‘QUIT'#13#10);
Closesocket(sockfd);
Result:=True;
end;

三、邮件的检测
  下面我们来看一个使用POP3CheckMail函数的简单示例。

var MailList:TstringList;
    ErrorMsg:String;
...
MailList:=TstringList.Create;
POP3CheckMail(‘simon_liu@263.net', 
‘mypassword',MailList,ErrorMsg);
IfMailList.Count>0then
MessageBox(0,Pchar(‘Youhave'+IntToStr
(MailList.Count)+‘newmessages!'), 
‘NewMessage!',MB_ICONINFORMATION)
ElseifErrorMsg=‘'thenMessageBox
(0,‘Nomessage!',‘',0)
ElseMessageBox(0,Pchar(ErrorMsg),‘Error',0);
MailList.Free;

  如果你仔细阅读了POP3CheckMail函数的实现代码,你会发现此函数除了可以获取邮件的封数之外,还可以获得每一封邮件的大小。你可以通过POP3CheckMail 函数的变量参数MailList的Strings数组来获取邮件的大小。

  实现了POP3CheckMail函数,再在此基础上编写一个POP3信箱的监视程序就变得很简单了。你可以通过一个定时器来定期地调用POP3CheckMail函数,这样你就可以监视某个email信箱了。假若你想要同时监视多个email信箱,只要为每一个信箱创建一个线程并且在线程中定期调用POP3CheckMail函数即可。你的程序中如果没有使用Delphi的控件,那么一个完整的信箱监视程序可能只有60K左右。

转载于:https://www.cnblogs.com/myamanda/articles/1636865.html

相关文章:

  • ubuntu的第三方站点remastersys无法访问
  • 业务系统设计之二:系统主控设计(上)
  • ROS 全自动算号器 1.1下载
  • 女性排毒养颜美容的14个技巧 - 健康程序员,至尚生活!
  • 汇编语言学习笔记-接收鼠标消息
  • IE新0day漏洞(979352)(又称极光零日漏洞)***将扩散
  • 苹果高清HD编辑系统
  • 支持firefox 3.6的onenote插件
  • 家长早放手,孩子早当家
  • CCNA笔记
  • vPower系列1: vMotion-没有vMotion,虚拟化只是玩具
  • 51 地图基本接口(三)
  • 从java的类装载器看安全
  • 在WPF中弹出右键菜单时判断鼠标是否选中该项
  • 唱响艾泽拉斯_职业篇
  • 【css3】浏览器内核及其兼容性
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • express + mock 让前后台并行开发
  • Gradle 5.0 正式版发布
  • HTTP--网络协议分层,http历史(二)
  • java 多线程基础, 我觉得还是有必要看看的
  • java中的hashCode
  • Linux gpio口使用方法
  • React组件设计模式(一)
  • 测试如何在敏捷团队中工作?
  • 基于web的全景—— Pannellum小试
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 小李飞刀:SQL题目刷起来!
  • 一文看透浏览器架构
  • 源码安装memcached和php memcache扩展
  • 做一名精致的JavaScripter 01:JavaScript简介
  • ​520就是要宠粉,你的心头书我买单
  • ​flutter 代码混淆
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (七)Java对象在Hibernate持久化层的状态
  • (三)docker:Dockerfile构建容器运行jar包
  • (转) ns2/nam与nam实现相关的文件
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .equals()到底是什么意思?
  • .net 4.0发布后不能正常显示图片问题
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .net core控制台应用程序初识
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .Net 高效开发之不可错过的实用工具
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .Net6使用WebSocket与前端进行通信
  • :O)修改linux硬件时间
  • ??eclipse的安装配置问题!??
  • @ModelAttribute使用详解
  • [ C++ ] STL---仿函数与priority_queue