我在 Linux 上运行带有 OpenSMTPD 和 Dovecot 的电子邮件服务器,并使用 Thunderbird 客户端通过 IMAP 访问电子邮件。当我在 Thunderbird 中删除电子邮件时,为什么磁盘空间使用量没有下降?
举例来说,一个用户的 mbox 文件存储在 /var/vmail/${domain}/$[user}/ 中:
$ ls
Archives Drafts inbox Sent Spam TrainSpam Trash
我不确定 mbox 文件是否是稀疏文件,因此du
,我期望它具有最准确的“有效”文件大小(这也显示了该问题)ls
,因此我将这个目录中所有文件的所有大小加了起来:
$ ls -al | grep vmail | awk '{print $5}' | paste -sd+ | bc
1119217444
接下来,我进入 Thunderbird,删除一封带有附件的大型电子邮件,该附件的大小为 1MB。Thunderbird 将其发送到“已删除”文件夹,然后我进入“已删除”文件夹,在那里将其删除,确认永久删除对话框并重新计算文件大小:
$ ls -al | grep vmail | awk '{print $5}' | paste -sd+ | bc
1119217443
所以它减少了 1 个字节。也许它只是将其标记为已删除?我如何才能真正恢复磁盘空间?我知道这可能并不简单,因为 mbox 文件只是一个巨大的平面文件。
答案1
在 MBOX 格式中,消息被一个接一个地存储在一个巨大的文件中,结构非常简单:
From [email protected] Sat Nov 10 06:00:00 2018
From: Author <[email protected]>
To: Recipient <[email protected]>
Subject: Sample message 1
Message body.
>From is escaped. Otherwise it would break the MBOX file.
From [email protected] Sat Nov 10 06:30:00 2018
From: Author <[email protected]>
To: Recipient <[email protected]>
Subject: Sample message 2
Another message body.
因此,从文件中间删除消息将导致重写文件的其余部分,这可能对性能和数据完整性都不利,因为如果写入中断,文件可能会损坏。
一种解决方案是将消息标记为已删除,而不是实际删除它,因为这样只需要修改一行,而文件的其余部分保持不变。这样以后可以将多个删除操作合并为一个操作。
MozillaZine 的文章压缩文件夹从 Thunderbird 的角度解释这一点:
当您在电子邮件客户端(例如 Thunderbird)中删除邮件时,它们并没有被物理删除。即使清空垃圾箱也无法清除它们。相反,它们会被标记为删除并隐藏起来。直到您“压缩”文件夹后,它们才会被物理删除。这是为提高大型文件夹的性能而做出的权衡。
Dovecot 的文章Mbox 邮箱格式解释 Dovecot 如何处理 MBOX 格式的问题。删除的内容存储在X-Status: D
添加到邮件头的标头中。
Dovecot 在 mbox 邮件中使用 C-Client(即 UW-IMAP、Pine)兼容标头来存储元数据。这些标头包括:
X-IMAPbase:
包含 UIDVALIDITY、最后使用的 UID 和使用的关键字列表X-IMAP:
与 X-IMAPbase 相同,但还指定该消息是“伪消息”X-UID:
消息分配的 UIDStatus:
R
(\Seen) 和O
(非 \Recent) 标记X-Status:
A
(\Answered)、F
(\Flagged)、T
(\Draft)和D
(\Deleted)标记X-Keywords:
消息的关键字Content-Length:
消息主体的长度(以字节为单位)只要存在这些标头,Dovecot 就会将其视为自己的私有元数据。它会对它们进行健全性检查,因此标头也可能被修改或完全删除。当 IMAP/POP3 客户端阅读邮件时,这些标头都不会发送给它们。
答案2
找到了 dovecot 命令:
$ doveadm expunge -u $user@$host mailbox Trash all