Quoted-Printable
邮件正文 QP 编解码
关于 Quoted-Printable
· RFC 2045:MIME 标准的两种 Content-Transfer-Encoding 之一(另一种是 Base64)
· 设计目标:邮件正文里大部分是 ASCII 文本,仅少量非 ASCII 字符需转义 → 比 Base64 可读性高
· 编码规则:
- ASCII 可打印字符(33-126,除 = 外)直接保留
- 其他字节 → =XX(XX 是大写十六进制)
- = 自身 → =3D
- 每行 ≤ 76 字符,超长用 =\n 软换行
· 常见场景:旧邮件客户端的 Content-Transfer-Encoding: quoted-printable 头部 / vCard / iCal
· vs Base64:英文为主的文本用 QP 更紧凑 + 可读 / 二进制内容用 Base64 更高效
关于本工具
了解工具定位 · 使用场景 · 对比优势
将邮件正文中的非ASCII字符、特殊符号或长行编码为可打印的QP格式,或还原为原始文本。需要处理邮件编码的开发人员、手动查看乱码邮件的用户、或编写邮件发送脚本时,直接粘贴文本即可编解码。所有操作在浏览器本地完成,内容不上传服务器。
使用场景
邮件乱码修复
收到一封包含特殊符号或非 ASCII 字符的邮件,正文乱码显示为 `=E4=B8=AD=E6=96=87` 等格式。将乱码内容粘贴到工具解码区,一键还原为原始中文或日文文本,无需手动对照编码表逐行转换,快速恢复邮件可读性。
邮件模板开发
开发 HTML 邮件模板时,图片或样式中的特殊字符(如 `©`、`™`)在部分邮件客户端中显示异常。使用工具对模板内容进行 QP 编码,确保所有非 ASCII 字符被安全转换为 `=C2=A9` 等格式,避免字符截断或乱码。
旧系统数据迁移
从遗留的邮件系统或数据库导出用户信息时,字段中包含中文、俄语等字符,导出文件被 QP 编码保护。将编码后的数据粘贴到工具中批量解码,还原为可读的原始内容,省去逐条手动替换的繁琐操作。
协议调试与测试
测试 SMTP 或 POP3 协议交互时,原始通信日志中包含 QP 编码的邮件正文。将日志中的编码片段复制到工具解码,即时查看实际传输的文本内容,快速定位协议实现中的字符编码错误。
对比矩阵本工具 vs 竞品 vs 传统方法
| 维度 | 本工具 | 竞品 A (Online QP Converter) | 传统方法 (邮件客户端) |
|---|---|---|---|
| 数据隐私 | 纯浏览器端处理,文件/文本不上传服务器 | 需将文本粘贴至网页,存在数据被服务器记录的风险 | 依赖邮件客户端软件,数据存储在本地设备 |
| 处理速度 | 即时,1 秒内完成编解码 | 取决于服务器响应,通常 2-5 秒 | 取决于邮件客户端性能,通常即时但需手动操作 |
| 离线可用 | 完全离线,无需网络 | 必须联网 | 必须安装客户端,离线可用 |
| 批量处理 | 单次输入,支持大文本 | 单次输入,通常有字符数限制 | 支持批量邮件处理,但操作复杂 |
| 平台依赖 | 跨平台,任何现代浏览器 | 跨平台,任何现代浏览器 | 依赖特定操作系统(如 Outlook 仅 Windows/Mac) |
| 学习成本 | 零学习成本,粘贴即用 | 零学习成本,粘贴即用 | 需了解邮件客户端中 QP 编码的查看/导出功能 |
使用指南
上手步骤 · 输入输出 · 避坑提示
使用步骤
- 在「编码」输入框粘贴或输入原始文本(支持 ASCII 及非 ASCII 字符)
- 点击「编码」按钮,工具将文本转换为 Quoted-Printable 格式(=XX 编码)
- 在「解码」输入框粘贴 QP 编码字符串(如 =E4=BD=A0=E5=A5=BD)
- 点击「解码」按钮,工具还原为原始文本
- 点击「复制结果」按钮,将编码或解码结果复制到剪贴板
输入输出示例8 个典型场景,覆盖常规、边界与易错
| 输入 | 输出 | 说明 |
|---|---|---|
| Hello World! | Hello World! | 典型场景:纯 ASCII 文本,QP 编码后无变化 |
| 中文测试 | =E4=B8=AD=E6=96=87=E6=B5=8B=E8=AF=95 | 典型场景:中文字符被编码为 UTF-8 字节的十六进制 |
| a b c d | a b c d | 边界 case:制表符和换行符保持原样,不编码 |
| =E4=B8=AD=E6=96=87 | 中文 | 典型场景:解码时正确还原已编码的中文字符 |
| A line with a trailing space | A line with a trailing space=20 | 边界 case:行尾空格被编码为 =20,防止传输中被截断 |
| =E4=B8=AD=E6=96=87=E6=B5=8B=E8=AF=95 | 中文测试 | 典型场景:解码一段完整的 QP 编码文本 |
| Line1 Line2 | Line1 Line2 | 边界 case:CRLF 行结束符保持原样,不编码 |
| =3D | = | 易错 case:等号本身编码为 =3D,解码时还原为 = |
常见错误对照8 个常踩的坑 · 错误 → 修复
1. 把非 ASCII 字符直接放入 QP 编码结果
=E4=B8=AD=E6=96=87=E4=B8=AD=E6=96=87 是正确的 QP 编码,但用户误以为可以直接写中文QP 编码只允许 ASCII 字符,非 ASCII 字符必须用 =XX 形式编码。直接写中文会导致邮件客户端乱码或解析失败。
2. 把 QP 编码结果当作 Base64 解码
用 Base64 解码器处理 =E4=B8=AD用 QP 解码器处理 =E4=B8=ADQP 和 Base64 是完全不同的编码方案。QP 用 =XX 表示字节,Base64 用 A-Za-z0-9+/= 表示。混淆会导致乱码。
3. 编码时忘记处理空格
Hello World 编码为 Hello=20World(正确)但用户写成 Hello WorldHello World → Hello=20WorldQP 编码中,空格必须编码为 =20,而不是直接保留空格。否则某些邮件客户端会丢失空格或截断。
4. 解码时误把 = 当作普通字符
输入 =E4=B8=AD 但用户只粘贴了 E4B8AD(去掉 =)输入 =E4=B8=AD 完整字符串QP 编码中 = 是转义标记,去掉 = 后解码器无法识别字节边界,会输出乱码或报错。
5. 编码时行尾未加软换行(soft line break)
一行超过 76 个字符的 QP 编码结果(如 =E4=B8=AD=E5=9B=BD... 共 80 字符)每 76 个字符插入 = 加换行(RFC 2045 要求)QP 编码标准(RFC 2045)规定每行不超过 76 个字符。超长行会被邮件服务器截断或拒绝。
6. 把 QP 编码结果直接放入 HTML 页面
<p>=E4=B8=AD=E6=96=87</p><p>中文</p>QP 编码是邮件传输编码,不是 HTML 实体编码。在 HTML 中直接使用 QP 编码结果不会显示为中文,而是显示原始字符串。
7. 编码时把 = 本身当作普通字符
输入 3=5 编码为 3=35(错误)3=5 → 3=3D5QP 编码中 = 是转义字符,本身必须编码为 =3D。否则解码器会把 = 后的两个字符当作十六进制字节值。
8. 解码时误用 UTF-8 以外的编码
用 GBK 解码 =E4=B8=AD(这是 UTF-8 编码的 '中')用 UTF-8 解码 =E4=B8=ADQP 编码只处理字节,不处理字符编码。解码后必须用正确的字符编码(通常是 UTF-8)解释字节序列,否则显示乱码。
工作原理
公式推导 · 流程图解 · 依据出处
核心公式
编码: =XX (XX 为字节十六进制值); 解码: 将 =XX 还原为对应字节
变量说明
XX— 字节的十六进制表示(大写)=— 转义标识符,后跟两位十六进制
示例
编码:文本 "中文" 的 UTF-8 字节为 E4 B8 AD E6 96 87,编码后为 =E4=B8=AD=E6=96=87。解码:将 =E4=B8=AD=E6=96=87 还原为字节序列 E4 B8 AD E6 96 87,再解码为 UTF-8 文本 "中文"。
适用范围
适用于邮件正文(RFC 2045/2047),仅对非 ASCII 字节(>127)或特殊字符(如 =)进行编码。ASCII 可打印字符(33-126,除 = 外)保持原样。
原理图
开发者集成
3 种主流语言 · 复制即用
import quopri
# 编码:bytes → QP 字符串
text = "hello, 世界"
encoded = quopri.encodestring(text.encode("utf-8")).decode("ascii")
print(encoded) # hello, =E4=B8=96=E7=95=8C
# 解码:QP 字符串 → bytes
decoded = quopri.decodestring(encoded.encode("ascii")).decode("utf-8")
print(decoded) # hello, 世界package main
import (
"fmt"
"mime/quotedprintable"
"strings"
)
func main() {
// 编码
text := "hello, 世界"
var buf strings.Builder
w := quotedprintable.NewWriter(&buf)
w.Write([]byte(text))
w.Close()
encoded := buf.String()
fmt.Println(encoded) // hello, =E4=B8=96=E7=95=8C
// 解码
r := quotedprintable.NewReader(strings.NewReader(encoded))
decoded := make([]byte, len(text))
n, _ := r.Read(decoded)
fmt.Println(string(decoded[:n])) // hello, 世界
}// 浏览器环境(无标准库,用 TextEncoder/Decoder 模拟)
// 编码:非 ASCII 字符转为 =XX 格式
function qpEncode(str) {
return Array.from(new TextEncoder().encode(str))
.map(b => b > 127 || b === 61 ? '=' + b.toString(16).toUpperCase() : String.fromCharCode(b))
.join('');
}
// 解码:=XX 转回字节
function qpDecode(str) {
const bytes = str.replace(/=([0-9A-Fa-f]{2})/g, (_, h) => String.fromCharCode(parseInt(h, 16)));
return new TextDecoder().decode(new Uint8Array([...bytes].map(c => c.charCodeAt(0))));
}
const text = 'hello, 世界';
const encoded = qpEncode(text);
console.log(encoded); // hello, =E4=B8=96=E7=95=8C
const decoded = qpDecode(encoded);
console.log(decoded); // hello, 世界常见问题
7 个高频疑问
Quoted-Printable 编解码怎么用?我直接把邮件原文复制进去就行吗?
为什么我解码后的中文还是乱码?
这个工具处理大文件(比如 10MB 邮件正文)会卡死吗?
Quoted-Printable 和 Base64 编码有什么区别?什么时候用哪个?
我复制邮件里的 QP 编码段,但解码后缺字符或结果不对,是工具问题吗?
这个工具会把我输入的邮件内容上传到服务器吗?隐私安全吗?
为什么我编码后的结果比原文大了很多?正常吗?
相关工具
「Base 系列」下的其他工具