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

From: "test1@newbt.net" <test1@newbt.net>
To: "clq@newbt.net" <clq@newbt.net>
Subject: test
Date: Sun, Jan :: GMT Hello World.

从中我们可以看到,其实可以直接在"记事本"中把邮件直接写出来。这是因为电子邮件的格式是 mime 而最简单的 mime 格式并不复杂。mime 当然也是有 rfc 文档进行说明的,不过明显太过复杂,我们先不要管它,先直接直观的看看眼前的这个邮件的格式。前面几行比较简单,我们猜也能猜出来,无非是说明了邮件的发件人、收件人这样的信息。后面的内容也简单啊,不就是邮件内容嘛!但是这里就有一个 mime 初学者非常容易出错的地方,后面的内容不仅仅是电子邮件的内容那么简单。实际上它包含了分隔符。什么分隔符号?你会问。我要说这封邮件里包含了两部分:一部分是头信息,包括发件人、收件人、标题、日期;另一部分是内容 "Hello World." 你能从上面的内容中找到它们的分隔符号是什么吗?大部分的同学仔细看过都会说,我看得出来是两部分,但是分隔符号是什么我真不知道。这个就是直观感受和程序处理的区别了,一眼看过去我们似乎能知道是两部分,但具体的就要知道格式的标准了。在这里,它的标准说明是:分隔符号是一个空行,不过在程序中它应该或者说必须描述为 "字符串流中的第一个空行前是头信息" 我不能说之后的就是内容,虽然这封信里看起来是这样。只能说对于这封信来说后面的内容是具体的信息,可以用下图表示:

在继续往下说以前我们要明白 mime 实际上在 http 中和 email 中是不太一样的,学过 http 的 mime 内容的同学要注意了:mime 在电子邮件中要比 http 中复杂得多,虽然它们是同一个标准

这里要再提出一个问题,如果我们要写一个中文的标题应该怎么写?你会说,改 subject 那里为"中文标题"就可以啦。如果我们这样做的话,确实对方可以收到一封中文的邮件。但我要说的是这样做是错误的。

(错误的中文标题做法)

我们前面的文章已经说过了,中文的内容在传统上是要使用编码的,所以正确的标题应该是下面的这样:

这里使用的编码方式就是前面说过的 base64。不过在邮件编码中还有一种更传统的,那就是"quoted-printable"编码,例如以下的这封 facebook 的信件内容就是这种编码的。

所以我们就明白了,要处理好电子邮件的 mime 那么就要先处理好这些编码格式,幸好常用的编码就这两种,而 base64 我们前面又掌握了。所以我们只要再学会"quoted-printable"编码就可以了。

其实"quoted-printable"说来也很简单,基本上就是我们常用的 http 的网址的编码,即将一个不可打印字符按16进制转换成基本字符串,然后在前面加上"="号就可以了,所以一个普通字符转换后要变成三个字符,是比较占空间的。不过现在是地球村时代,我们要特别注意字符集的处理,具体处理我们下一篇用纯C的代码来做一个示例。好了这一次的内容就到这里了。

注:查看电子邮件源码的话,直接在163 这样的站点上是看不到的,可以搜索一下 foxmail4.2 (最新版本我没试过);也可以用笔者的 eemail ,不过早期版本 mime 标题部分不完善,请到以下地址下载最新版本:

http://newbt.net/ms/vdisk/show_bbs.php?id={B7106D5A-A5CB-3CFE-DFEB-4A4909A9B13A}&pid=43

这篇的内容稍少,不过不先搞清楚"quoted-printable"编码是不行的,所以还是得有这一章节。

--------------------------------------------------

版权声明:

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

一步一步从原理跟我学邮件收取及发送 13.mime格式与常见字符编码的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    本系列上一篇文章中我们就说到了,这一次我们要说 pop3 收信了.虽然我觉得应该先说完 mime 格式,不过估计大家已经不耐烦了 -- 怎么老在说发送啊?我们要看收取!    好吧,来啦,来啦!收取邮 ...

随机推荐

  1. Algorithms code

    一些值得回看的小算法. 最长的连续子数组 子数组数字不重复 int [] arr={1,2,3,4,7}; //输出4 int [] arr1={1,2,3,4,1,2,3,4,5,1}; //输出5 ...

  2. Angular 4 设置组件样式的几种方式

      你用Angular吗? 一.介绍 如何只改动最简单的css代码,呈现完全不一样的视图效果. 第一种:最基本的设置:   图1 代码 图2 界面运行效果图 平常,想给一个label或者p等标签添加样 ...

  3. Weblogic jsp页面编译出错,Weblogic jsp编译异常

    Weblogic jsp页面编译出错,Weblogic jsp编译异常 ======================== 蕃薯耀 2018年1月29日 http://www.cnblogs.com/f ...

  4. Oracle问题之ORA-01609、ORA-00362

    Oracle问题之ORA-01609: 日志 4 是线程 1 的当前日志 - 无法删除成员 Oracle问题之ORA-00362: 要求输入成员以组成组 4 中的有效日志文件

  5. 20170505 PHP实践中知识点

    1.json_encode 不转义 2.empty() 与 isset() 区别 在使用 php 编写页面程序时,我经常使用变量处理函数判断 php 页面尾部参数的某个变量值是否为空,开始的时候我习惯 ...

  6. oracle 配置 自启动 和 关闭

    今天在看oracle自启动脚本,突然有点时间,总结一下!!! 第一次写博客,大家随便看看就好,有错误麻烦提醒下,不喜欢别喷,主要是锻炼自己,形成写博客的好习惯. 刚毕业,现在还没转正,在干运维和自学d ...

  7. linux_NFS

    NFS是什么? 网络文件系统,又叫共享存储,通过网络连接让不同主机之间实现共享存储. 应用于存放图片.附件.视频等用户上传文件 相关同类应用:大型网站nfs有压力,使用moosefs(mfs),Ghu ...

  8. jdk源码->集合->ConcurrentHashMap

    类的属性 public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentM ...

  9. MyEclipse中Lombok的安装及使用

    lombok是一款通过注解的形式简化我们必须有又显得臃肿的代码的工具.最常用的就是@Data注解.实体类上用了这个注解,实体类的各个属性就不需要书写get和set方法. 安装步骤: 1.关闭Myecl ...

  10. android EditText与TextView几个常用的属性

    android:maxLength="100"输入框最多输入的字数. android:maxEms="10"每行最多输入字符个数 android:textcol ...