这篇文章原题为《Linux系统下mail命令》,发布于 2014 年。原文实际讲的是用本机 MTA 发送邮件,并没有解释怎样接收邮件;其中的真实收件地址、个人主目录、uuencode 附件和未知 HTTP 来源也不适合成为今天的操作示例。
本文把题目重建为一个安全的接收指南:先区分本地系统邮箱、远程 IMAP/POP3 与邮件发送,再用服务商官方参数、经过验证的 TLS、受限凭据和可回滚的单向同步完成最小测试。示例域名使用保留的 .invalid,必须替换成你自己的服务商官方值;不要直接执行占位配置。
文末保存历史正文的惰性归档。因隐私原因只替换了 6 处个人收件地址和 2 处个人主目录;未改动的原文仍保存在
source_export与 Git 历史中。归档内命令绝不能执行。
Table of Contents
先确定“接收”发生在哪里
| 需求 | 数据位置 | 合适工具 | 关键边界 |
|---|---|---|---|
| 读取服务器投递给本机 Unix 账户的邮件 | 本地系统邮箱或 mbox | 本机 mail/mailx 实现 |
不会自动连接互联网邮箱;退出语义会影响已读邮件位置 |
| 交互读取远程邮箱并保留服务器文件夹 | IMAP 服务端 | 支持 TLS 与服务商认证方式的当前 MUA,如 NeoMutt | IMAP 状态可能双向变化,先限制删除与标志同步 |
| 把远程邮箱同步成可备份的本地 Maildir | IMAP 与本地副本 | 当前 mbsync/isync |
同步不是备份;状态、删除与 expunge 必须单独控制 |
| 从服务器下载邮件的旧式工作流 | POP3 服务端到本地 | 仅在服务商明确支持且需求确实匹配时使用 | 默认行为因客户端而异,可能删除服务器副本或丢失文件夹语义 |
| 发送邮件 | MTA 或邮件提交服务 | SMTP submission 客户端/MTA | SMTP 是发送路径,不是收取协议;不在本文配置 |
先问服务商或管理员:IMAP 是否启用、主机名、隐式 TLS 端口、认证机制、用户名格式、OAuth 客户端政策、应用专用密码条件、配额、限速、保留策略、服务器端文件夹/标签语义,以及是否允许第三方命令行客户端。不要从论坛帖子复制端点,也不要把 SMTP 凭据误用于 IMAP。
本地 mailx 只读取本机邮箱
POSIX mailx 有发送和接收两种模式。无收件人参数时进入接收模式,默认读取当前 Unix 用户的系统邮箱;具体路径、包名和实现由系统决定。先做只读发现:
command -v mail
command -v mailx
如果两者都不存在,使用发行版当前受支持的软件包文档选择实现,不要安装年代久远的随机 RPM。若存在,先阅读本机手册并确认它操作的是 mbox、Maildir 还是其他后端。下面是 POSIX 风格的交互入口,不代表远程 IMAP 登录:
mailx
在交互提示符中,可以先只列标题、读取一个已批准的测试邮件,然后用不修改邮箱的退出命令:
headers
type 1
exit
POSIX 语义下,exit 不改动邮箱;quit 可能把已读系统邮件移入 mbox、落实删除或保存状态。不同实现可能扩展或改变行为,必须以本机 man mailx 为准。不要用 -u other-user 读取他人邮箱;那需要额外权限,也可能违反隐私与审计边界。
终端、滚屏缓冲、录屏和 shell 会话日志都可能显示发件人、主题与正文。只在受控终端读取,分享诊断前删除地址、主题、Message-ID、令牌和内容。
远程邮箱优先使用 IMAP 与现代 TLS
IMAP 管理服务器上的文件夹、消息和标志;POP3 更接近下载式访问;SMTP submission 用于发送。协议名不能互换。RFC 8314 为邮件访问推荐 TLS,并注册隐式 TLS 的 IMAPS 端口 993 与 POP3S 端口 995。STARTTLS 也可能由服务商支持,但不能降级到明文后继续认证。
| 配置项 | 安全要求 | 停止条件 |
|---|---|---|
| 主机与端口 | 只用服务商/管理员当前官方值;通常 IMAPS 993 | IP、短链、镜像教程或证书名称与主机不符 |
| TLS | 验证证书链、主机名和有效期,服从系统当前 TLS 策略 | 任何“忽略证书”“trust all”或降级 TLS 要求 |
| OAuth | 客户端受服务商批准,令牌范围最小、可撤销并存入密钥环 | 要求复制浏览器 cookie、在命令行粘贴令牌或扩大无关权限 |
| 应用专用密码 | 仅在服务商官方支持、MFA 已启用且 OAuth 不适用时 | 使用主账户密码、多人共用密码或无法单独撤销 |
| 本地账户 | 专用非特权用户,目录权限最小 | 以 root 日常读取或让其他用户可读配置/邮件 |
OAuth 令牌仍是秘密。RFC 7628 的优势是可授予有限访问并与长期账户密码分开撤销,不是把令牌公开到配置、进程参数或日志的许可。若服务商要求 OAuth,选择当前版本且原生支持 OAUTHBEARER/XOAUTH2 的客户端,严格按服务商注册流程授权;不要自己从网页会话提取令牌。
只探测 TLS,不发送凭据
在写客户端配置前,可以对服务商确认的 IMAPS 端点做一次 TLS 握手检查。以下 .invalid 主机故意不可用;替换前先确认本机 OpenSSL 支持这些参数:
openssl s_client -connect imap.example.invalid:993 -servername imap.example.invalid -verify_hostname imap.example.invalid -verify_return_error -brief </dev/null
通过条件是证书链和主机名验证成功,协议符合系统策略。此命令不登录邮箱,不证明凭据、权限或文件夹可用。证书失败时检查系统时间、DNS、代理、服务商状态和 CA 包;不要使用忽略验证参数,不要把未经独立核验的服务器叶证书添加为永久信任锚。
握手输出会暴露主机、证书主体和网络环境,工单中只保留必要字段。若网络受企业代理管理,应由管理员提供受管信任方案,而不是临时关闭校验。
用隔离配置做只拉取的 IMAP 试验
下面使用 mbsync 展示边界,不代表推荐特定发行版包或邮件服务商。先核对本机版本与官方手册。测试使用独立配置、Maildir 和状态目录,遇到同名路径就停止,绝不覆盖已有设置:
config="$HOME/.config/isyncrc-example"
mailroot="$HOME/Mail/example"
state="$HOME/.local/state/isync-example"
test ! -e "$config" && test ! -L "$config" || { echo "Stop: $config already exists"; exit 1; }
test ! -e "$mailroot" && test ! -L "$mailroot" || { echo "Stop: $mailroot already exists"; exit 1; }
test ! -e "$state" && test ! -L "$state" || { echo "Stop: $state already exists"; exit 1; }
umask 077
mkdir -p -- "$HOME/.config" "$HOME/.local/state"
install -d -m 700 -- "$mailroot" "$state"
install -m 600 /dev/null "$config"
用受信任的本地编辑器把以下内容写入刚创建的空文件。替换主机和用户名,但不要添加 Pass;交互运行时让客户端提示输入服务商批准的应用专用密码。若必须无人值守,改用经过审计的密钥环助手与 PassCmd,并先验证它不会把秘密写入参数、标准错误或日志。
IMAPAccount example
Host imap.example.invalid
Port 993
User user@example.invalid
TLSType IMAPS
SystemCertificates yes
IMAPStore example-remote
Account example
MaildirStore example-local
SubFolders Verbatim
Path ~/Mail/example/
Inbox ~/Mail/example/INBOX
Channel example-inbox
Far :example-remote:
Near :example-local:
Sync Pull New
Create Near
Remove None
Expunge None
SyncState ~/.local/state/isync-example/
这份配置只选择 INBOX,把新消息从远端拉到本地;不推送本地变化,不传播删除,不 expunge。它仍会在真正运行时读取邮件内容并在磁盘留下敏感副本。邮箱若使用 OAuth,就不要把访问令牌填进 Pass;应停止这个密码示例,改用客户端和服务商共同支持的 OAuth 流程。
先模拟,再执行一次有界同步
关闭 shell 跟踪和会话录制,不要加会打印协议负载或消息正文的 debug 选项。先检查文件权限和配置差异,再运行官方 --dry-run:
stat -c '%a %n' "$HOME/.config/isyncrc-example" "$HOME/Mail/example" "$HOME/.local/state/isync-example"
mbsync -c "$HOME/.config/isyncrc-example" --dry-run example-inbox
--dry-run 会连接、认证并查询状态,但不修改邮箱或同步状态;输出仍可能包含文件夹或消息元数据,不能公开粘贴。证书、认证、配额、权限或文件夹映射有任何异常就停止。不要反复重试触发锁定或限速。
获得批准后,只执行一次指定频道,不用 -a 同步所有配置:
mbsync -c "$HOME/.config/isyncrc-example" example-inbox
验收本地新消息数量、抽样哈希/大小、时间、附件与编码,并在服务商 Web 界面确认远端消息、标志和文件夹没有变化。不要用真实生产邮箱做第一轮;先用专用测试账户和无敏感内容的种子邮件。若首次邮箱很大,先由服务商管理员和客户端文档确认限量策略,不能靠中断进程猜测一致性。
本地阅读与同步相互分离
mbsync 负责复制,NeoMutt 等 MUA 负责阅读。先让 MUA 只打开新的本地 Maildir,不给它远端账户或发送配置,并确认删除、移动和已读标志不会被当前单向频道推回服务器。不同客户端的 Maildir 打开参数和状态行为不同,应使用该版本的官方手册,而不是假设 mailx 能读取 Maildir。
阅读前备份本地副本与同步状态。只展示标题的诊断也可能泄密,不在共享终端、CI 日志或截图中打开生产邮件。HTML 邮件、附件和外部图片均视为不可信内容:默认不执行脚本、不自动打开附件、不加载远程跟踪图片,并用独立安全工具检查可疑文件。
“同步成功”不等于“备份完成”。同步会复制状态或未来的删除;备份需要独立的版本、保留期、完整性验证和恢复演练。本文的试验特意关闭删除传播,直到负责人定义完整策略。
POP3 仅用于明确的下载式需求
POP3 不保留 IMAP 的完整文件夹与标志模型,客户端的“下载后删除”“在服务器保留副本”和 UIDL 行为会决定数据风险。只有服务商仍正式支持、业务明确需要 POP3、并且已验证保留与去重语义时才使用 POP3S 995 或受保护的 STARTTLS。
首次连接前用测试账户证明:服务器副本是否保留、多设备是否重复下载、UID 重置如何处理、附件与大邮件是否完整、失败重试是否重复,以及撤销凭据后本地数据如何保留。任何“端口 110 明文登录”“接受任意证书”或默认删除远端邮件的示例都应拒绝。
从 IMAP 改为 POP3 不是简单换端口,而是数据模型迁移。没有服务器导出、可恢复备份、测试矩阵和退休计划时不要切换。
秘密、权限与日志
- 不把密码、应用专用密码、访问/刷新令牌写进命令行、shell 历史、环境变量、截图、Git 或文章配置。
- 配置、Maildir、同步状态、OAuth 缓存和密钥环访问脚本只允许专用账户读取;备份也必须加密和限权。
- 优先 OAuth 的最小邮件读取范围;若范围无法细分,记录额外权限并由负责人接受风险。
- 只有服务商明确支持时才使用可单独撤销的应用专用密码;不复用主密码。
- 定时任务应使用独立服务账户、受限网络和受保护的密钥环,不能依赖解锁的个人桌面会话。
- 不启用会打印协议正文、认证交换、消息内容或附件的网络 debug;日志默认只保留时间、频道、结果码和脱敏计数。
- 邮件本身可能包含个人数据、机密、恶意 HTML 和附件;定义本地保留、删除、取证与事件响应流程。
如果秘密曾出现在参数、终端共享、日志或 Git 中,停止同步、撤销令牌/应用密码、检查访问记录并按事件流程轮换;只删除文件不能消除已泄漏副本。
故障分类与停止条件
| 现象 | 先收集的非秘密证据 | 安全下一步 | 禁止做法 |
|---|---|---|---|
| DNS/连接失败 | 官方主机名、解析结果、端口、时间、服务状态 | 核对网络与服务商公告 | 尝试随机 IP、代理或镜像端点 |
| TLS 验证失败 | 主机名、证书主体/期限、验证错误、系统时间 | 修复 DNS/时间/CA 或联系管理员 | 关闭证书/主机名验证 |
| 认证失败 | 机制名、客户端版本、服务商错误码、MFA/OAuth 状态 | 停止重试,核对官方认证政策并撤销可疑凭据 | 改用主密码、复制 cookie、公开 token |
| 文件夹缺失 | 脱敏文件夹名、namespace、订阅状态、权限 | 先只列清单并与服务商语义比对 | 自动创建/删除所有远端文件夹 |
| 重复或 UID 变化 | 频道、状态版本、UIDVALIDITY、脱敏计数 | 冻结状态和本地副本,查阅 mbsync 恢复说明 | 删除状态后盲目重跑 |
| 配额/限速 | 错误码、时间窗口、消息数量与大小汇总 | 降低频率并联系服务商 | 并发循环或无限重试 |
| 本地权限异常 | 数字权限、所有者、挂载和备份策略 | 停止读取,修复专用目录权限 | 用 root 日常运行或开放全局读权限 |
任何要求关闭 TLS、信任任意证书、把秘密写入配置/命令行、使用他人账户、绕过组织策略或在没有备份时传播删除的步骤,都是停止条件。
回滚、撤权与离职处理
试验失败时先禁用定时任务,保留配置、同步状态、日志摘要和本地 Maildir 的只读证据,不删除远端内容。由于频道是 Pull New、Remove None、Expunge None,正常试验不应改远端;仍要通过服务商 Web 界面核对。
回滚由明确负责人执行:撤销 OAuth 授权或应用专用密码;从密钥环移除对应条目;把试验目录移到权限受控的隔离区;恢复变更前配置;验证其他客户端仍能读取;按保留策略决定本地副本和状态的销毁时间。不要在命令中用宽泛通配符清理邮箱,也不要把删除本地副本误当作服务商数据删除。
人员离职或设备报废时,撤销凭据和客户端注册、终止任务、交接业务邮箱所有权、验证审计日志、加密擦除本地副本,并记录完成证据。个人主账号不应成为长期自动化依赖。
上线前清单
- 已确认本地系统邮箱、IMAP、POP3 与 SMTP 的职责边界。
- 主机、端口、认证、配额、文件夹语义和客户端许可来自服务商官方资料。
- TLS 证书链、主机名和有效期验证成功,没有降级或 trust-all 设置。
- OAuth 范围最小且可撤销,或使用服务商批准的独立应用密码;未使用主密码。
- 秘密不在参数、环境变量、配置明文、日志、截图或 Git 中。
- 客户端与依赖来自受支持的软件源,版本和功能已记录。
- 首次测试使用专用账户、种子邮件、独立目录和
--dry-run。 - 同步只拉取新邮件,不推送、删除或 expunge,直到另行评审。
- 本地目录、状态、备份和日志具备最小权限与明确保留期。
- 已验证消息完整性、远端不变、限速行为、失败重试和恢复。
- 有监控、负责人、停止条件、凭据撤销、回滚和离职流程。
参考资料
- POSIX/Open Group:`mailx` 的发送与接收模式
- RFC 9051:IMAP4rev2
- RFC 8314:邮件提交与访问使用 TLS
- RFC 7628:OAuth 的 SASL 机制
- isync 官方手册:`mbsync`
- NeoMutt:凭据 Account Command
- NeoMutt:IMAP 与 OAuth 配置项
- OpenSSL:`s_client` TLS 诊断
历史原文归档
以下是 source_export 中 2014 年可见正文的完整惰性归档,除隐私替换外未做改写或行尾调整。共将个人收件地址 6 处替换为 [historical recipient address redacted],个人主目录 2 处替换为 [historical home directory redacted];原始值仅保留于 source_export 和 Git 历史。HTTP 转载地址原样保留在围栏内作为来源证据,不是当前推荐链接。围栏内的发送、附件、安装和转载命令均已过时,绝不能执行。
在Linux系统下mail命令的测试
1. 最简单的一个例子:
mail -s test [historical recipient address redacted]
这条命令的结果是发一封标题为test的空信给后面的邮箱,如果你有mta并且后面的邮箱不会挡这种可能莫名奇妙的信的时候,就能收到这封信了。如果你不想被这种乱七八糟的事情干扰,后面的邮箱请使用本地帐户。
2. 第二个例子:
三种常用格式发信
mail -s test [historical recipient address redacted] #第一种方法,你可以把当前shell当成编辑器来用,编辑完内容后Ctrl-D结束
echo “mail content”|mail -s test [historical recipient address redacted] #第二种方法,我用的最多,可能是喜欢管道的缘故吧
mail -s test [historical recipient address redacted] < file #第三种方法,以file的内容为邮件内容发信
其实你很容易发现mail从标准输入读取文件内容并发信,我也只想让你知道这一点,到此,第二个例子结束。
3. 第三个例子,带附件的邮件
如果你的系统里没有uuencode命令的话,请先安装sharutils(yum install sharutils)
uuencode 需要两个参数,第一个是你要发送的文件(们),当然这个也可以用管道来做,第二个是显示的文件名
uuencode [historical home directory redacted]/a.gif a.gif|mail -s pictest [historical recipient address redacted]
tar czf – [historical home directory redacted]/ | uuencode home.tgz |mail -s pictest [historical recipient address redacted]
ps: 顺便补一句,slackware下的mail好像有一个-a参数,可以直接添加附件,我没有用过。
转自:http://www.svn8.com/linux/accidence/20091016/10858.html
