使用 Mutt 清理你的收件箱
教 Mutt 又一个技巧:如何使用简单的宏来过滤你的收件箱中的邮件。
我长期使用 Mutt,并且在 Linux Journal 中多次撰写关于它的文章。尽管许多人可能认为在 2018 年使用基于命令行的电子邮件客户端很奇怪,但我发现键盘驱动的电子邮件客户端比在 Web 浏览器中点击操作效率高得多。Mutt 非常可定制,这起初呈现出陡峭的学习曲线,但现在我已经用了几十年了,我的 Mutt 配置非常理想,非常适合我,就像量身定制的西装一样。
当然,与任何强大且可配置的工具一样,我不时会了解到 Mutt 的新功能,这些功能极大地提高了我的生活质量。在这种情况下,我正在使用的电子邮件系统不提供服务器端过滤器。因为我是许多不同电子邮件组和别名的成员,这意味着我的收件箱充斥着各种各样的电子邮件,并且很难从所有我想存档的不重要邮件中过滤出需要我立即关注的邮件。
有很多方法可以解决这个问题,其中一些方法涉及诸如 offlineimap 与过滤工具结合使用的工具。对于像 Thunderbird 这样的电子邮件客户端,您也可以设置过滤器,以便在每次同步时自动将电子邮件移动到其他文件夹。我想要一个与 Mutt 类似的系统,只是我不希望它自动发生。我希望能够先按下一个键,以便我可以确认正在移动的内容。在弄清楚这一点的过程中,我发现了一些注意事项,我认为其他 Mutt 用户在设置类似系统时会想知道。
标记电子邮件设置键盘宏以根据模式移动电子邮件的传统第一步是使用 Mutt 的按模式标记功能(默认情况下,按 T 键)来标记文件夹中所有与特定模式匹配的消息。例如,如果您的所有 cron 电子邮件的主题行中都有“Cron Daemon”,您将键入以下键序列来标记所有这些消息
TCron Daemon<enter>
那是大写 T,后跟我要在主题行中匹配的模式(Cron Daemon),然后是 Enter 键。如果我在我的 Mutt 索引窗口中键入它,该窗口向我显示我的收件箱中的所有电子邮件,它将标记所有与该模式匹配的消息,但它还不会对它们执行任何操作。要对所有这些消息执行操作,我按下 ; 键(默认情况下),后跟我要执行的操作。因此,要将所有标记的电子邮件保存到我的“cron”文件夹,我将键入
;s=cron<enter>
那是 ; 后跟 s 键以保存,后跟要保存到的文件夹的名称,其中 =cron
表示“位于收件箱下的名为 cron 的文件夹”。要将所有这些组合成一个宏,以便我可以通过按 .c 来触发此操作,我将以下内容添加到我的 Mutt 配置文件中
macro index .c "TCron Daemon<enter>;s=cron<enter>"
或者,如果您想使其更具可移植性(以防您将保存命令重新映射到另一个键),您可以这样做
macro index .c "TCron Daemon<enter><tag-prefix>
↪<save-message>=cron<enter>"
当然,如果您要清理收件箱中的大量邮件,您可能需要匹配很多不同的模式。例如,我想移动发送到 dmarc-reports 电子邮件地址的所有 DMARC 报告消息,因此我将在该宏中添加另一个模式,该模式会将所有这些消息保存到我的 dmarc 文件夹中。就其本身而言,宏看起来像这样
macro index .c "T~Cdmarc-reports<enter><tag-prefix>
↪<save-message>=dmarc<enter>"
这里最重要的区别在于,对于我的标记模式,我不仅仅是匹配 dmarc-reports
,这只会匹配主题行,我在它前面键入了 ~C
,它会标记所有在 To: 或 CC: 标头中包含“dmarc-reports”的消息。组合后的宏只是将两个按键列表一个接一个地组合起来,看起来像这样
macro index .c "TCron Daemon<enter><tag-prefix><save-message>
↪=cron<enter>T~Cdmarc-reports<enter><tag-prefix><save-message>
↪=dmarc<enter>"
问题
上面的宏有一个微妙的问题,除非您过去设置过像这样的 Mutt 宏,否则您可能不会注意到它。实际上,在前几次运行宏时,它可能看起来工作正常——只要您的收件箱中有匹配的消息。如果您没有任何匹配的消息,则会发生问题。Mutt 解释此宏的方式是,如果您没有任何匹配的消息,它仍然会愉快地将 <tag-prefix> 命令之后的任何命令应用于光标当前所在的消息!幸运的是,我只是在移动消息,但如果您告诉 Mutt 删除标记的消息,它们将永远消失!
这里的解决方案是使用一个名为 <tag-prefix-cond>
的特殊 Mutt 命令,而不是 <tag-prefix>
。这告诉 Mutt 仅当 Mutt 实际标记了任何消息时才执行 <tag-prefix-cond>
之后的命令。然后,您用 <end-cond>
包裹该命令,以告诉 Mutt 该条件命令已完成。因此,对于一个简单的宏,我将替换
macro index .c "TCron Daemon<enter><tag-prefix><save-message>
↪=cron<enter>"
为
macro index .c "TCron Daemon<enter><tag-prefix-cond>
↪<save-message>=cron<enter><end-cond>"
如您所见,我将整个 <save-message>
命令包裹在这个条件块中。如果我对完整的宏进行相同的处理,我将转换
macro index .c "TCron Daemon<enter><tag-prefix><save-message>
↪=cron<enter>T~Cdmarc-reports<enter><tag-prefix>
↪<save-message>=dmarc<enter>"
为
macro index .c "TCron Daemon<enter><tag-prefix-cond>
↪<save-message>=cron<enter><end-cond>T~Cdmarc-reports<enter>
↪<tag-prefix-cond><save-message>=dmarc<enter><end-cond>"
现在,当我想为我的收件箱添加新过滤器时,我可以手动在 Mutt 中测试 tag
命令一次,以确认它是否按我的预期工作,然后将其附加到我的宏中。现在,当我加载我的收件箱时,我可以按下一个简单的键并执行这些过滤器。如果您希望这是自动的,您只需为您的收件箱文件夹设置一个 folder-hook 语句,该语句使用 Mutt push
命令来按下上述宏中的所有键。