- 游戏开发
- 后端
【免费下载链接】kbengine
A MMOG engine of server.
KBEngine 的服务器端(baseapp、cellapp 等)由内嵌的 CPython 运行时驱动,其源码树随仓库完整保留在 kbe/src/lib/python 下(版本为 Python 3.7.3)。服务器脚本资产以 Python 编写,其中涉及玩家邮箱注册激活、找回密码等流程时,开发者常常需要程序化地解析、构造与序列化 MIME 邮件消息。本文以 email.rst 这份官方文档为主体,完整还原email包的定位、四大组件架构(对象模型、解析器、生成器、策略控制)、子模块地图与两套 API(现代 API 与 legacy compat32 API),并结合仓库内源码逐条印证关键类、默认参数与调用关系,帮助你在 KBEngine 脚本环境中正确而高效地处理邮件消息。
email 包只负责"消息本体",不负责投递
文档开篇即明确了一个最重要的边界:email包是一个管理邮件消息的库,它专门不设计用于向 SMTP(RFC 2821)、NNTP 或其他服务器发送邮件——发送是smtplib、nntplib等模块的职责。email包的目标是在解析、操纵与生成消息时尽可能符合 RFC,其遵循的规范包括:
- RFC 5233、RFC 6532(头部与正文的 UTF-8 处理);
- 与 MIME 相关的 RFC 2045、RFC 2046、RFC 2047、RFC 2183、RFC 2231。
这一点在当前仓库中可以得到一个有趣的印证:KBEngine 服务器自身的邮件投递走的是 C++ 实现而非 Pythonemail包。sendmail_threadtasks.cpp 中SendEMailTask::process使用 jwsmtp 库的mailer对象直接发送,SMTP 服务器、账号与密文都来自 email_service_defaults.xml(smtp_server、smtp_port、smtp_auth、username、password等节点,其中密码支持 kbe_private.key RSA 加密)。也就是说,"通过 SMTP 发出去"这一环由引擎 C++ 层完成;而当你在自己的服务器脚本里需要解析收到的原始邮件、构造 MIME 消息体、生成符合规范的字节流交给某条发送通道时,标准库email包就是工具。
文档同时说明,email包会尽力向应用隐藏各 RFC 的细节:概念上应用可以只把邮件视为"一个由 Unicode 文本与二进制附件构成的结构化树",无需关心序列化时的表示方式。但实践中仍需要了解 MIME 的一些高层结构,尤其是 MIME "content type" 的命名与形式,以及它如何标识 multipart 文档。文档指出这类知识通常只在较复杂的应用中需要,而且只需了解高层结构,不需要知道其底层表示细节——MIME content type 在现代互联网软件中应用广泛,多数程序员对此并不陌生。
文档末尾的 "See also" 还列出了与email包配套的传输类模块,可视为完整的邮件处理工具箱:
| 模块 | 用途 |
|---|---|
smtplib | SMTP(简单邮件传输协议)客户端 |
poplib | POP(邮局协议)客户端 |
imaplib | IMAP(Internet 消息访问协议)客户端 |
nntplib | NNTP(网络新闻传输协议)客户端 |
mailbox | 以多种标准格式在磁盘上创建、读取和管理消息集合 |
smtpd | SMTP 服务器框架(主要用于测试) |
这些模块在本仓库的 Python 树中均真实存在,例如 smtplib.py、smtpd.py。
四大组件:对象模型、解析器、生成器与策略
文档将email包的整体结构划分为三个主要组件,外加一个控制其他组件行为的第四个组件:
- 对象模型(object model)——包的核心。应用主要通过定义在
email.message子模块中的对象模型接口与包交互:向已有邮件提问、构造新邮件、或增删本身也使用同一套对象模型接口的邮件子组件。正如同邮件消息及其 MIME 子组件的本性一样,邮件对象模型是一个对象树,树中所有节点都提供email.message.EmailMessageAPI。 - 解析器(
email.parser)——把邮件消息的序列化版本(一个字节流)转换成一棵EmailMessage对象树。 - 生成器(
email.generator)——把一棵EmailMessage对象树重新序列化回字节流。文档特别提示:解析器与生成器也能处理文本字符流,但不推荐使用这种用法,因为太容易产生以某种方式不合法的消息。 - 控制组件(
email.policy)——每个EmailMessage、每个生成器、每个解析器都有一个与之关联的policy对象来控制其行为。通常应用只需在EmailMessage被创建时(直接实例化新邮件,或用解析器解析输入流)指定一次 policy 即可;但在用生成器序列化消息时也可以更换 policy。例如:从磁盘按通用方式解析一封邮件,再在发往邮件服务器时改用标准 SMTP 设置序列化。
从源码结构看,这四个组件与文档描述一一对应:
- 对象模型:Lib/email/message.py 中第 105 行的
class Message(legacy 基础类)与第 1159 行的class EmailMessage(现代 API 核心类); - 解析器:Lib/email/parser.py 第 17 行
class Parser,以及 Lib/email/feedparser.py 第 136 行class FeedParser; - 生成器:Lib/email/generator.py 第 26 行
class Generator与第 392 行class BytesGenerator; - 策略:Lib/email/policy.py 与 Lib/email/_policybase.py。
文档指出,自 Python 3.6 起(versionchanged标注)文档被重新组织与重写,以推广新的EmailMessage/EmailPolicyAPI——这也正是本仓库 3.7.3 版本中代码的形态。
email 包的子模块地图
文档正文给出了email包的完整文档目录(toctree),按"现代 API"与"legacy API"两组组织。这个目录同样就是email包的子模块结构,与仓库 Lib/email 目录下的源文件一一对应:
现代(unicode 友好)API:
| 文档/子模块 | 角色 | 对应源码 |
|---|---|---|
email.message | 对象模型,应用使用的主接口 | message.py |
email.parser | 字节流 → 消息对象树 | parser.py |
email.generator | 消息对象树 → 字节流 | generator.py |
email.policy | 控制其余组件的行为 | policy.py |
email.errors | 包可能抛出的异常 | errors.py |
email.headerregistry | 更精细操纵头部(headers)的工具 | headerregistry.py |
email.contentmanager | 更精细操纵 payload 的工具 | contentmanager.py |
email.examples | 基础 API 用法示例 | Doc 示例 |
其中headerregistry与contentmanager两个子组件除了"消费和生成非平凡消息"的实用功能外,还各自记录了扩展性 API(extensibility API),对高级应用很有价值。
Legacy API(以email.message.Message类一节为起点):
| 子模块 | 说明 |
|---|---|
email.message.Message(compat32) | 直接、更贴近邮件消息底层表示细节 |
email.mime | MIME 便捷构造类(text、multipart、nonmultipart 等) |
email.header | 头部解析/生成 |
email.charset | 字符集处理 |
email.encoders | CTE 编码器 |
email.utils | 地址、日期等工具函数 |
email.iterators | 消息迭代器 |
文档对 legacy 部分有一句关键定位:compat32API不向应用隐藏 RFC 细节,对需要操作在那个层级的应用来说是有用的工具,同时也服务于出于向后兼容原因仍在使用email.policy.compat32API 的旧应用。
从 Lib/email/init.py 的__all__可见包对外暴露的模块名,其中还包含feedparser(增量解析器,未在文档 toctree 单列)以及四个便捷函数message_from_string、message_from_bytes、message_from_file、message_from_binary_file(分别定义于该文件第 32、40、48、56 行),它们是"一行代码把字符串/字节/文件变成消息对象"的入口。
对象模型 EmailMessage:头部字典 + payload 树
文档正文(及紧随其后的email.message小节)描述了EmailMessage的概念模型:
- 一封邮件由**头部(headers)和payload(也称 content)**组成。头部是 RFC 5322 或 RFC 6532 风格的"字段名 + 值",冒号不属于名也不属于值;
- payload 可以是简单文本消息、二进制对象,或者一个结构化子消息序列——每个子消息有自己的头部和自己的 payload。当消息的 MIME 类型形如
multipart/*或message/rfc822时,就表明 payload 属于这种结构; - 概念模型是:一个头部的有序字典,加上一个表示 RFC 5322 正文的 payload(可能是子
EmailMessage对象列表)。除常规的字典式头部访问方法外,还提供从头部读取专门信息(例如 MIME content type)、操作 payload、生成序列化版本、递归遍历对象树的方法; EmailMessage的字典式接口以头部名为键索引。
在仓库源码中,EmailMessage直接继承MIMEPart,其set_content覆写会在首次设置内容时自动补上MIME-Version: 1.0头(见 message.py 第 1159–1165 行附近),这正是"对象模型替你维护 RFC 细节"的一个具体例子。
策略(policy):驱动一切行为的控制对象
文档将email.policy称为"控制组件":每个消息、解析器、生成器都挂着一个 policy。从仓库源码可以读出具体的默认取值,方便你在脚本中显式定制:
基类策略 Lib/email/_policybase.py 第 162–165 行的类属性给出了核心默认值:
| 属性 | 默认值 | 作用 |
|---|---|---|
raise_on_defect | False | 发现 RFC 违规(defect)时是记录为 defect 还是抛错 |
linesep | '\n' | 序列化时使用的行分隔符 |
cte_type | '8bit' | 允许的 content transfer encoding 类型 |
max_line_length | 78 | 最大行长(不含 linesep) |
max_line_length在折叠头部时会被实际使用:_policybase.py第 367–369 行将maxlinelen传给头部编码逻辑,保证输出行宽合规。
现代 API 的 EmailPolicy(第 26 行起,源码中同样标注为 PROVISIONAL)在此基础上增加了:
| 属性 | 默认值 | 作用 |
|---|---|---|
utf8 | False | False时头部序列化为 ASCII,非 ASCII 字符用 encoded words(RFC 2047)编码;True时按 RFC 6532 直接以 UTF-8 序列化 |
refold_source | 'long' | 解析来源的头在重新生成时是否重折叠:none/long(仅超过max_line_length的行)/all |
header_factory | HeaderRegistry() | 可调用对象,把(name, value)变成带类型语义的头对象(地址、日期字段有专门处理);每个新实例会创建独立的 factory |
content_manager | raw_data_manager | 提供get_content/set_content,Message上的同名方法最终委托给它 |
文档强调的使用要点在此处成立:通常只需在创建EmailMessage时指定一次 policy;而序列化阶段可以替换 policy。一个典型场景——"从磁盘按通用设置解析、发往邮件服务器时按标准 SMTP 设置序列化"——正是 KBEngine 这类"脚本资产中处理玩家邮件"场景需要的能力:同一封消息对象,入库/落盘与对外发送可以用不同的 policy 分别序列化。
典型用法:最小示例与 MIME 构造
文档的示例章节(email.examples)与Doc/includes下的可运行脚本给出了email包最基础的用法模式。以 email-simple.py 为代表:
# Import smtplib for the actual sending function import smtplib # Import the email modules we'll need from email.message import EmailMessage # Open the plain text file whose name is in textfile for reading. with open(textfile) as fp: # Create a text/plain message msg = EmailMessage() msg.set_content(fp.read()) # me == the sender's email address # you == the recipient's email address msg['Subject'] = 'The contents of %s' % textfile msg['From'] = me msg['To'] = you # Send the message via our own SMTP server. s = smtplib.SMTP('localhost') s.send_message(msg) s.quit()注意其中体现的分工:EmailMessage负责消息本体(头部 +text/plainpayload),smtplib负责投递——与文档"email 包不发送邮件"的定位完全一致。同目录还有构造多部分消息的示例:email-mime.py(附件)、email-alternative.py(文本/HTML 二选一)与 email-dir.py(目录式消息),它们分别对应multipart/mixed与multipart/alternative两类最常见的 MIME 结构。
围绕这套 API,仓库还内置了完整的单元测试,可作为行为验证的权威依据:test_email 目录 下的test_message.py、test_parser.py、test_generator.py、test_policy.py、test_contentmanager.py、test_inversion.py(解析-生成互逆性测试)等,覆盖了对象模型、解析、生成、策略与内容管理的各个角落。
与 KBEngine 服务器邮箱体系的关系
最后把视角拉回项目本身。KBEngine 服务器的邮件服务由两部分构成:
- C++ 发送层:sendmail_threadtasks.cpp 中的
SendEMailTask以线程任务形式运行,通过 jwsmtp 的mailer发送,smtp_auth取值 1/2 分别映射到jwsmtp::mailer::LOGIN/PLAIN认证类型(源码第 17 行),并对模板中的${username}等占位符做替换(第 27 行); - 配置层:email_service_defaults.xml 定义 SMTP 服务器、认证信息,以及激活/重置密码/绑定三类邮件的
subject、deadline(如激活邮件有效期 259200 秒)与 HTML 模板(支持${backlink}占位链接),该文件路径由 kbengine_defaults.xml 中的<email_service_config>节点指向。
由此可以推断:email包在 KBEngine 生态中的位置是服务器脚本(Python)侧的消息处理工具——当你需要在脚本中解析玩家上传/收到的原始邮件字节流、拼装带附件的 MIME 结构、或按特定 policy 生成规范化字节流供 C++ 层或smtplib发送时,它提供的是标准库级的解析、对象模型与序列化能力;而"通过 SMTP 把信发出去"这一环,引擎自身已由 jwsmtp 完成。两者职责边界清晰,正呼应了文档开篇的那句定位。
小结
email包是"消息本体"库:解析、操纵、生成,不负责 SMTP/NNTP 投递(那是smtplib等的职责);- 四大组件——对象模型(
EmailMessage树)、parser、generator、policy——在 kbe/src/lib/python/Lib/email 中有完整、一一对应的实现; - policy 是贯穿解析与序列化的控制旋钮:
max_line_length=78、linesep='\n'、cte_type='8bit'、raise_on_defect=False是基类默认值,EmailPolicy增加utf8、refold_source、header_factory、content_manager; - 现代 API(
EmailMessage/EmailPolicy)与 legacycompat32API 并存,前者隐藏 RFC 细节,后者贴近底层表示,可按需要选用; - 行为可验证性由 Lib/test/test_email 的成套单测保障,示例可直接参考 Doc/includes 中的
email-*.py脚本。
- 游戏开发
- 后端
【免费下载链接】kbengine
A MMOG engine of server.
相关推荐
KBEngine 内置 Python 3.7.3 的 email.policy 模块:用 Policy 对象掌控邮件消息的解析与序列化
KBEngine 内置 Python 3.7.3 的 email.policy 模块:用 Policy 对象掌控邮件消息的解析与序列化 本文基于 KBEngin
游戏开发后端Python `email.message.Message` 与 compat32 API 源码级指南:KBEngine 内嵌 Python 3.7 邮件对象模型全解析
Python email.message.Message 与 compat32 API 源码级指南:KBEngine 内嵌 Python 3.7 邮件对象模型全
游戏开发后端KBEngine 内嵌 Python 标准库 email.message 模块详解:EmailMessage 对象模型与 MIME 消息处理实战
KBEngine 内嵌 Python 标准库 email.message 模块详解:EmailMessage 对象模型与 MIME 消息处理实战 本文基于当前仓
游戏开发后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考