本系列上一篇文章中我们就说到了,这一次我们要说 pop3 收信了。虽然我觉得应该先说完 mime 格式,不过估计大家已经不耐烦了 -- 怎么老在说发送啊?我们要看收取!
    好吧,来啦,来啦!收取邮件现在常用的有 pop3 和 imap 协议,不过从传统来说 pop3 受众要广得多。有了前面的基础,要实现 pop3 收信其实非常的简单。我们仍然用第一篇"网络命令的发送"中所说的方法来学习 pop3 协议。
    首先仍然是用 telnet 连接 pop3 对应的网络地址,这里是 telnet newbt.net 110,其中 pop3 的默认端口就是 110 ,以 newbt 邮箱为例子,很容易就能登录邮箱,用到的命令请看下图:

大家可以看到,比起 smtp 的登录来说是简单得多了,不需要回应对方的域名;甚至密码也不用进行 base64 编码(当然一定程度来说安全性不高,不过现在都有 ssl )。
好了照例又来个 163 邮箱的例子,照例又比 newbt 的麻烦一些:需要在域名前加上 "pop3." 的子域名(好在其他的内容差不多),这个 "pop3" 的子域名前缀和前面文章提到的"smtp"前缀一样并没有什么标准可言,即:
telnet pop3.163.com 110

完整的要发送的命令列表为:

user 您的用户名@邮箱域名( 邮箱的话后面不用加,只要用户名就行)
pass 您的密码
uidl
retr (按 retr 的结果,想收哪封就写哪个数字)

命令执行的结果如下图:

(成功登录163邮箱)

(uidl 命令会列出所有邮件的序号和唯一标识)

(retr命令的结果就是邮件内容,准确来说是邮件的 mime 源码)

完了。完了?是的,就是这样,其他的 pop3 命令用不着实现。不过对于过去的邮件客户端来说一般还会删除刚收取的邮件,那就再加两个命令:

dele (按 retr 的结果,想删除哪封就写哪个数字)
quit(有些邮箱退出后才真删除)

不过现在是手机时代,电脑和手机都应该能看到信,所以现在的实现就不要收取后删除了。

大家可以看到 pop3 的收取简直是简单得令人发指啊! ... 谁说不是呢 ... 只要掌握了第一篇发送网络命令的方法,其实大部分的网络通讯协议都会有这种感觉,所以我个人觉得我们这个系列文章中价值最高的就是第一篇文章。

要注意的是,这里的示例和传统的示例有一点区别,那就是我用的是 uidl 列出邮件,而传统的教程可能会用 list 命令。因为在具体的客户端编写中还会碰到一个问题:怎样不重复收取邮件呢?看到那个 uidl 命令的返回了吗?每一行回应的空格后面就是一封信的唯一标志。同时这个命令回应的结束符号和我们前面说的 smtp 发送的邮件内容结束符号是一样的也就是"."加前后的两个换行。具体区别可看 rfc 文档。
    这里有必要和大家说的一个问题就是 rfc 只是一个参考,要按它的要求全部实现的话其实大多数情况下是没有必要的,就好比所有的 C++ 编译器都没有完全实现全部的 C++ 标准一样。当然了还是要提供一下相关 rfc 文档的链接:
http://man.chinaunix.net/develop/rfc/RFC1939.txt
备用地址
http://newbt.net/ms/vdisk/show_bbs.php?id=1B938647F353291F60658D8FB893223F&pid=160

协议虽然很简单,但是大家有没有看到 retr 收信后的结果是一堆"乱码",这也就是我本不打算先说 pop3 协议的原因。这些并不是乱码,而是电子邮件的 mime 格式,另外 mime 还普遍使用在 http 协议中。mime 的格式相当复杂,电子邮件用到的又更是复杂,不过这是编写电子邮件程序必须经过的 ... 好了,我们在后面的文章再说吧。不过 mime 格式恐怕得花好几篇文章才能说完,还不一定能说清,大家要有心理准备 :)

因为还没有说到 mime 格式,写出具体的收信代码也没有什么意义,所以以后我们讲完 mime 再给出示例吧。不过有了前面的基础代码,相信大家要自己写出来也是易如反掌的事情。

-------------------------------------------------
版权声明:
本系列文章已授权百家号 "clq的程序员学前班" . 文章编排上略有差异.

一步一步从原理跟我学邮件收取及发送 12.telnet命令行收一封信pop3的更多相关文章

  1. 一步一步从原理跟我学邮件收取及发送 3.telnet命令行发一封信

    首先要感谢博客园管理员的及时回复,本系列的第二篇文章得以恢复到首页,这是对作者的莫大鼓励.说实在的本来我真的挺受打击的.好在管理员说只是排版上有些问题,要用代码块修饰下相关的信息.说来惭愧因为常年编码 ...

  2. 一步一步从原理跟我学邮件收取及发送 8.EHLO 命令详解

    我们在上一篇中解决了接收一行命令的问题后,就可以来具体的分析邮件发送过程中涉及到的 SMTP 协议内容了. 首先来看通讯过程中的第一个内容:服务器在客户端连接上来后会主动发送一个问好的信息,所以这第一 ...

  3. 一步一步从原理跟我学邮件收取及发送 2.邮箱的登录和绕不开的base64

    一步一步从原理跟我学邮件收取及发送 2.邮箱的登录和绕不开的base64 好了,经过本系列上一篇文章 "1.网络命令的发送",假设大家已经掌握了 email 电子邮件的命令发送的方 ...

  4. 一步一步从原理跟我学邮件收取及发送 4.不同平台下的socket

    既然是面向程序员的文章那当然不能只说说原理,一定要有实际动手的操作.    其实作为我个人的经历来说,对于网络编程,这是最重要的一章! 作为一位混迹业内近20年的快退休的程序员,我学习过很多的开发语言 ...

  5. 一步一步从原理跟我学邮件收取及发送 5.C语言的socket示例

    说到 C 语言版本的程序,首先要解决的问题就是兼容性. 作为 20 年开发有 10 多年是在服务端的程序员,我深刻地感受到服务端平台的两极分化之严重,linux 派对 windows 那是超级的不屑一 ...

  6. 一步一步从原理跟我学邮件收取及发送 10.四句代码说清base64

    经过前几篇的文章,大家应该都能预感到一定要讲解 base64 函数的内容了.是的,马上要到程序登录的代码,base64 是必须要实现的. base64 很早以前我就接触了,在项目中也很喜欢用.但每换一 ...

  7. 一步一步从原理跟我学邮件收取及发送 11.完整的发送示例与go语言

    经过了这个系列的前几篇文章的学习,现在要写出一个完整的 smtp 邮件发送过程简直易如反掌.    例如我们可以轻松地写出以下的纯 C 语言代码(引用的其他C语言文件请看文末的 github 地址): ...

  8. 一步一步从原理跟我学邮件收取及发送 9.多行结果与socket的阻塞

    前几篇的文章发表后,有网友留言说没有涉及到阻塞的问题吗?在 socket 的编程当中,这确实是个很重要的问题.结合目前我们文章的内容进度,我们来看看为什么说阻塞概念很重要. 接着上篇的内容,当我们发送 ...

  9. 一步一步从原理跟我学邮件收取及发送 13.mime格式与常见字符编码

    在前面的本系列文章中我们已经学会了邮件的发送和收取.但在收取中我们看到的是一串串的乱码,回忆前面的发送过程,我们会奇怪:我们前面的邮件是明文啊.为什么明文的邮件明明也可以正常工作,还要弄乱码似的字符串 ...

随机推荐

  1. C语言课程设计大整数运算

    该大整数运算系统用于对有符号的位数不超过500位的大整数进行加.减.乘.除四则运算和计算N(0<=N<=10000)的阶乘.注意事项 :    1.操作期间,进行四则运算时若大整数为正数请 ...

  2. C# 小笔记

    1,Using using (var ws = new WebSocket ("ws://dragonsnest.far/Laputa")) { ws.OnMessage += ( ...

  3. JAVA BASE64

    Base64编码说明:     Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式. 如果剩下的字符不足3个字节, ...

  4. C# 内置 DateTime类详解

    C# 内置 DateTime类详解 摘抄自微软官方文档,用来方便自己查阅:网址:https://msdn.microsoft.com/zh-cn/library/system.datetime(v=v ...

  5. shopnc验证码显示不了

    data/config文件编码问题,要utf-8无bom

  6. vue初学者

    先分享一波福利 vue学习视频    链接:https://pan.baidu.com/s/1ggSfE75 密码:7h2a        1.先安装 webpack vue-cli          ...

  7. TypeError: 'encoding' is an invalid keyword argument for this function

    python 2.7 问题 data_file = open("F:\\MyPro\\data.yaml", "r", encoding='utf-8') 运行 ...

  8. python_如何修改装饰器中参数?

    案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...

  9. JavaScript动画:offset家族和匀速动画详解(含轮播图的实现)

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. offset家族简介 我们知道,三大家族包括:offset/scroll ...

  10. php 通过curl获取远程数据,返回的是一个数组型的字符串,高手帮忙如何将这个数组类型的字符串变成数组。

    如 Array([0] => Array([0] => Array([kd_status] => 已签收[kd_time] => 2014-04-30 18:59:43 [b] ...