企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 电子邮件系统 电子邮件系统应该如何设计? 可以在电脑上写一个程序,存储每个人的邮件,然后把服务器当做邮局 但是如果通过服务器进行中转的话,服务器怎么才能发到个人邮箱呢? 如果让服务器主动去连个人电脑,问题是个人电脑可能处于关机状态,而且IP地址会改变。所以服务器不能主动去连接。 也就是说可以在服务器上为每个人开辟一块空间,空间课程叫“用户名@服务器名 那么还需要开发一个客户端邮箱quickMail,可以向服务器上的邮箱发信,也可以从服务器上收信。 另外同样还需要服务器端的程序,用来接收邮件,存储起来,就叫QuickMailServer 电子邮件的格式为:发件人、收件人、抄送、密送、标题、正文 ## 协议 那么client如何与服务器进行通信了? 最简单的协议是: ![](http://p8a6vmhkm.bkt.clouddn.com/img/20181029113850.png?imageslim) 这个协议考虑到了端口问题,而且还考虑到了DATA中以什么作为发送数据的结尾。 不过有个小问题,数据在网络上传输,中文是不行的,需要进行编码,把他们变成ASCII码 比如Base64,可以把二进制的数据变成小写字母a-z,A-Z,数字0-9,符号+、/、=等字符组成的数据。这只是一种编码方式,而不是加密 比如“为了庆祝产品发布, 今晚在海底捞聚餐” 经过 base 64 编码就会变成这个样子: 5Li65LqG5bqG56Wd5Lqn5ZOB5Y+R5biD77yMIOS7iuaZmuWcqOa1t+W6leaNnuiBmumkkA== 这完全是 ASCII 码了。 可以定义收信的协议如下 ![](http://p8a6vmhkm.bkt.clouddn.com/img/20181029114547.png?imageslim) 这个协议考虑到了用户登录的问题,因为自己的邮箱应该是私密的。 我们可以为协议起一个名字: - 发信:Simple Mail Transfer Protocol , SMTP - 收信:Post Office Protocol ,POP协议 ## 让邮件支持附件 怎么给邮件加上附件呢?邮件的正文是文本格式的,但是word是二进制的。完全不同。 我们做计算机的,遇到问题的方法通常有两个: - 增加一个抽象层 - 分而治之 所以我们可以把原始问题划分成两个子问题: - 如何让正文和邮件区分开来。 - 如何把二进制数据加入邮件中 那么如何把正文和邮件区分开呢? 可以定义一个邮件内容类型`Content-type=plain-text`,那么这个邮件就是纯文本的,如果是`Content-type=mixed`,那么就代表文本+附件 这样的话,主要问题在于扩展性不好。 可以分为主类型和子类型, 其中主类性和子类型都可以扩展。 现阶段,如果主类型是Text,那么子类型可以是plain,代表纯文本也可以是别的东西。 如果主类型是Multipart,代表文件有多个部分,那么子类型可以是mixed 比如 - Content-type=text/plain,这是纯文本的邮件 - Content-type=multipart/mixed,这是一个由正文和附件混合组成的邮件。 > text除了plain还支持HTML,Multiaprt还支持alternative,related 那么客户端如何告诉服务器文件与附件的分隔呢? 可以让客户端加一个分隔符的属性: ``` Content-type=multipart/mixed; boundary="----=_NextPart_AEDGREGREWGREWGFDSFGSGFDSFTTRFSGGFD_001_0051_01A"; ``` 比如下面就是一封带附件的邮件: ``` // 定义这是一个混合的邮件, 每个部分的分隔符由 boundary 定义。 为了便于阅读, 我把这个 boundary 故意写的很简单, 实际复杂的多 Content-type=multipart/mixed; boundary="--A001_0051_01A"; // 以分隔符来开始邮件正文 ----A001_0051_01A // 这是 “为了庆祝产品发布, 今晚在海底捞聚餐” 的 base64 编码的结果 5Li65LqG5bqG56Wd5Lqn5ZOB5Y+R5biD77yMIOS7iuaZmuWcqOa1t+W6leaNnuiBmumkkA== ----A001_0051_01A Content-type:audio/wav name:"fly.wav" <这里是附件 1 的数据> ----A001_0051_01A Content-type: image/jpg name:"sky.jpg" <这里是附件 2 的数据> // 整个邮件结束的标记 ----A001_0051_01A ``` 那附件的编码怎么办? 这些附件无非就是二进制的数据, 完全可以像处理汉字那样用 base64 来编码啊! 扩展性, 我们可以给每一个部分加一个编码类型的属性? 例如: ``` Content-type: image/jpg name:"sky.jpg" encoding: base64 ``` ## 多个邮件服务器 现在邮箱的基本功能有了,但是Email只能在公司内部留转,如何在两个公司之间发邮件呢? 假设, 有两个公司, 他们的邮件服务器分别是 mailA.com 和 mailB.com , 当 userA@mailA.com 给 userB@mailB.com 发信的时候, 我们可以这么处理: 1. 用户 userA 通过 SMTP 把邮件发给 mailA.com 这个邮件服务器 2. mailA.com 发现目标用户 userB@mailB.com 并不在 自己的服务器上, 它就把信件暂时放到队列里。 3. mailA.com 从**队列**中取出邮件, 然后尝试向 mailB.com 投递 ,也是通过 SMTP, 如果发送失败, 就给 userA 发一个投递失败的消息。 4. mailB.com 接收到以后, 存到 userB 的邮箱里, userB 就可以通过 POP3 协议进行收取了 这里唯一做的变化就是让邮件服务器可以暂存邮件, 转发邮件。