bash脚本-从电子邮件列表到变量仅获取唯一域

时间:2019-01-08 05:13:34

标签: regex bash

我是bash的新手,对理解如何完成此操作有疑问。

选中所有“收件人:”字段电子邮件地址域,并将所有唯一域列出到变量中,以便与域进行比较。

我通过

获得“发件人地址”域
grep -m 1 "From: " filename | cut -f 2 -d '@' | cut -d ">" -f 1

读取存储在文件名中的邮件时。

对于“寻址”域,可以有多个“收件人:”地址,并且具有多个域。我不确定如何从“到地址字段”获取唯一域。

地址行示例如下:

To: user@domain.com, user2@domain.com, 
    User Name <sample@domaintest.com>, test@domainname.com
grep -m 1 "^To: " filename | cut -f 2 -d '@' | cut -d ">" -f 1

,但是电子邮件格式不同。因此,我不确定grep是否正确,还是应该搜索awk或其他内容。

我需要从“收件人:”字段的电子邮件地址中获取唯一域列表,然后将其发送到bash脚本中的变量。

上述示例的所需输出:

domain.com,domaintest.com,domainname.com

2 个答案:

答案 0 :(得分:0)

电子邮件地址标准化很棘手,因为有很多变体可供选择。

From: Elvis Parsley <king@graceland.example.com>
From: king@graceland.example.com
From: "Parsley, Elvis" <king@graceland.example.com> (kill me, I have to use Outlook)
From: "quoted@string" <king@graceland.example.com> (wait, he is already dead)
To: This could fold <recipient@example.net>,
   over multiple lines <another@example.org>

我将转向一种功能更强大的语言,并为解析所有这些格式提供适当的支持。我的选择是Python,尽管您也可以在几行Ruby或Perl中实现这一点。

email库在Python 3.6中进行了改进,因此假定您至少拥有该版本。在{3.6}中新增的email.Headerregistry类在这里特别方便。

#!/usr/bin/env python3

from email.policy import default
from email import message_from_binary_file
import sys

if len(sys.argv) == 1:
    sys.argv.append('-')

for arg in sys.argv[1:]:
    if arg == '-':
        handle = sys.stdin
    else:
        handle = open(arg, 'rb')

    message = message_from_binary_file(handle, policy=default)
    from_dom = message.get('From').address.domain
    to_doms = set()
    for addr in message.get('To').addresses:
        dom = addr.domain
        if dom == from_dom:
            continue
        to_doms.add(dom)
    print(','.join([from_dom] + list(to_doms)))

    if arg != '-':
        handle.close()

这只会产生一个逗号分隔的域名列表;您可能还想在Python中进行其余的处理,或者更改此方法以使其以稍微不同的格式打印内容。

您将其保存在方便的位置(例如/usr/local/bin/fromto)并将其标记为可执行文件(chmod 755 /usr/local/bin/fromto)。现在,您可以像其他grep之类的其他实用程序一样从外壳程序调用它。

答案 1 :(得分:0)

如果您想通过面向行的实用程序来做到这一点,那么Procmail发行版中有一个实用程序formail,可以为您一些规范化的事情。

bash$ formail -czxTo: <<\==test==
> From: me <sender@example.com>
> To: you <first@example.org>,
>    them <other@example.net>
> Subject: quick demo
>
> Very quick, innit.
> ==test==
first@example.org,    other@example.net

因此,您有了输入,您实际上可以将其传递给grep或Awk ...或sed

fromdom=$(formail -czxTo: <message | tr ',' '\n' | sed 's/.*@//')

From:不会对formail -czxFrom:地址进行规范化,但是您可以使用巧妙的技巧:使formail生成对From:地址的回复,然后提取To:标头。

todoms=$(formail -rtzcxTo: <message | sed 's/.*@//')

更详细地讲,-r表示要对发送给您message的任何人进行新的回复,然后我们对{em>那做-zcxTo:

-t选项可能会或可能不会执行您想要的操作。在这种情况下,我可能会忽略它。http://www.iki.fi/era/procmail/formail.html的操作说明不明确;另请参见本节。 http://www.iki.fi/era/procmail/mini-faq.html#group-writable之前,并且对于笨拙的链接感到抱歉-似乎没有很好的链接到页面内部的锚点。)