【问题标题】:How to split single mail with procmail?如何使用 procmail 拆分单个邮件?
【发布时间】:2019-07-04 12:03:38
【问题描述】:

我有一个隔离文件夹,我必须定期下载并按收件人收件箱拆分,或者更好地将每封邮件拆分到一个文本文件中。我有每天 10.000 封邮件,我正在用 fetchmail 和 procmail 编写一些东西。问题是我不知道如何在 procmail 中逐条拆分消息;它们最终都在同一个收件箱中。

我尝试通过如下配方传递脚本中的每条消息:

    :0
    | script_processing_messages.sh

其中包含

    read varname
    echo "$varname" > test_file

要尝试查看是否可以在 $varname 变量中获取一条消息但不行,我每次只获取一行消息。

我现在用

    fetchmail --keep

.fetchmailrc 在哪里

    poll mail.mymta.my protocol pop3 username "my@inbox.com" password "****" mda "procmail /root/.procmailrc"

而 .procmailrc 是

    VERBOSE=0
    DEFAULT=/root/inbox.quarantine

我想为每条消息获取一个文件,所以:

1.txt
2.txt
3.txt
[...]
10000.txt

我有很多收件人和很多域,所以我不能说编写 5000 条规则来匹配每个收件人。要是有什么办法就好了

^To: $USER 

重定向到

/$USER.inbox

这样 procmail 自己负责阅读和动态创建这些收件箱

我不是 fetchmail 和 procmail 食谱方面的专家,我正在努力但我不会走得太远。

【问题讨论】:

  • 我已经这样做了,但我没有找到任何可以帮助我的东西。我的意思是,管道规则中可能有一些东西,但我无法像我在问题中显示的那样得到它
  • 查看“将消息直接发送到默认位置。” 页面将* ^From: spammer@domain.com 指向/dev/null 的部分。如果我理解,您需要使用 ^To: 字段将消息定向到用户文件夹。这应该使您进入参考的正确部分。我使用 procmail 将用户过滤到文件夹中,但对于您的问题没有解决方案。
  • 是的,我应该更准确地描述我的问题。我有很多收件人和很多域,所以我不能说编写 5000 条规则来匹配每个收件人。如果有某种^To: $USER 重定向到/$USER.inbox 那就太好了,这样procmail 本身就会负责阅读和动态创建这些收件箱……而这就是我找不到答案的地方
  • 不太清楚你在问什么。是否要将单个 Berkeley mbox 文件拆分为消息并通过 Procmail 传递每个消息?这是formail -s procmail <mboxfile,在 Procmail 文档中有非常清楚的解释。

标签: bash email split procmail fetchmail


【解决方案1】:

你似乎有两三个不同的问题; Stack Overflow 上的正确礼仪是分别询问每个人 - 这也有助于未来的访问者遇到您的问题之一。

首先,要拆分包含多条消息的 Berkeley mbox 文件并分别在每条消息上运行 Procmail,尝试

formail -s procmail -m <file.mbox

您可能需要阅读mailbox formats supported by Procmail。 Berkeley 邮箱是包含多条消息的单个文件,仅由以From 开头的行分隔(四个字母字符后有一个空格)。这个分隔符必须是唯一的,因此在正文的行首包含这五个字符的消息需要以某种方式转义(通常通过在From 之前写一个&gt;)。

要将每封邮件保存在单独的文件中,请选择与单文件伯克利格式不同的邮箱格式。具体来说,如果目标是一个目录,Procmail 将在该目录中创建一个新文件。新文件的具体命名方式取决于目录的内容(如果它包含 Maildir 子目录 newtmpcur,则根据 Maildir 命名约定在 new 中创建新文件)以及如何准确指定目录(斜杠和点选择 MH 格式;否则,邮件目录格式)。

保存到每个收件人一个邮箱有许多讨厌的角落案例。如果邮件发送给多个本地收件人怎么办?如果收件人地址在标头中不可见怎么办?等等(Procmail Mini-FAQ 有a section about this,在域虚拟主机的上下文中,这基本上是一个变体)。但如果我们简单地忽略这些,你也许可以用类似的东西来完成它

:0  # whitespace before ] is a literal tab
* ^TO_\/[^ @    ]+@(yourdomain\.example|example\.info)\>
{
    # Trim domain part from captured MATCH
    :0
    * MATCH ?? ^\/[^@]+
    ./$MATCH/
}

这将捕获到$MATCH 匹配正则表达式的第一个地址,然后对捕获的字符串执行另一个正则表达式匹配以仅捕获@ 符号之前的部分。这显然要求您要匹配的地址都在一组特定的域中(在这里,我使用了yourdomain.exampleexample.info;显然将它们替换为您的实际域名)并且捕获第一个匹配的地址就足够了(因此,如果一条消息是 To: alice@yourdomain.exampleCc: bob@example.info,则该配方将挑选出更接近消息顶部的消息,而另一个将被忽略)。

更详细地说,\/ 特殊标记使 Procmail 将在此点之后与正则表达式匹配的文本复制到内部变量 MATCH 中。正如这个秘籍所展示的,你可以对该变量本身执行正则表达式匹配以提取它的子字符串(或者,换句话说,丢弃部分捕获的匹配)。

动作./$MATCH/ 使用MATCH 中捕获的字符串作为要保存到的文件夹的名称。前导 ./ 指定当前目录(等于 Procmail 变量 MAILDIR 的值),尾随 / 选择邮件目录格式。

如果您的预期收件人不能被限制在一组特定的域中或以其他方式与单个正则表达式匹配,我的建议是提出一个范围更有限的新问题,并提供足够的详细信息来实际确定您想要什么完成。

【讨论】:

    【解决方案2】:

    我找到了部分问题的解决方案。

    在procmail中似乎没有办法让procmail自己识别For收件人而不在recipe中指定它,所以我只是获取了一个列表并创建了一个巨大的recipe文件。

    但后来我发现,为了节省单个邮件并避免巨大的邮箱塞满大量邮件,可以编写如下配方:

    :0
    * ^To: recipient@mail.it
    /inbox/folder/recipient@mail.it/
    

    注意末尾的/:这将使 procmail 创建一个文件夹结构,而不是将所有内容都写在一个文件中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-30
      • 2019-09-05
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      相关资源
      最近更新 更多