【问题标题】:How to parse an email signature to get the details separately?如何解析电子邮件签名以分别获取详细信息?
【发布时间】:2015-08-03 07:52:30
【问题描述】:

我的项目需要解析我收到的 gmail 帐户的邮件签名。我必须从签名中获取名字、姓氏、邮件 ID 等 [只有发件人的]。你能告诉我从哪里开始吗? (从某种意义上说,“从哪里开始”,是否已经为此做好了准备?)

我已经通过了这个question,这个问题是关于删除签名的东西,但这与我的要求完全相反。这个问题的答案并不能解决我的问题。

我知道我可以使用正则表达式来完成这项工作。但我不想错过那些不遵循邮件签名网络礼节的邮件,比如在签名前去掉“--”,尾随连字符。

如果可能的话,请让我知道任何完全提供此功能的开源 javascript 项目。

提前致谢。

更新:我正在寻找的签名通常与业务相关,因此它们包含 HTML 内容或有时直接包含 VCard。

更新:我只需要剥离签名的每一行并从这些行中获取详细信息。

【问题讨论】:

  • 你能举几个输入(你正在使用的文本)和期望输出的例子吗?
  • 输入也可以是 HTML,因为我使用的邮件通常是商业邮件,我为自己的个人资料提供粗略的输入 Vamshi Krishna Alladi |产品软件工程师 P +91 9123456789 E abcdefghi@xyz.com W www.xyz.com
  • 如果没有准确的输入(可能是 HTML 代码),将无法为您提供帮助。
  • 没有具体的输入。这正是我想说的。
  • 谈到我之前在 cmets 中提供的输入只是为了说明签名的要点。输入没有特定的格式

标签: javascript regex email parsing signature


【解决方案1】:

回答这个问题有几个可能的部分。

gmail 界面中的签名

在 gmail 界面中,签名相当容易抓取。它们包含在<font color="#888888"> 中,因此如果您从 gmail 界面中获取签名,那么使用 xmlreader 获取那些应该非常容易。这不会得到 gmail 未检测到的任何签名。

使用签名设置从 gmail 发送的邮件中的签名

只需在电子邮件的 html 版本中查找 <div class=3D"gmail_signature">

签名解析的一般方法

我任意将目标限定为发件人的联系方式。因此,在签名中仅获取联系信息是最有意义的。由于许多电子邮件包含发件人以外的其他人的联系信息,因此第一步是隔离签名。

一旦签名被隔离,每一行都可以与正则表达式模式匹配。我绝不是正则表达式专家,所以我不会尝试在这里描述实际模式。

下面是一个方法,而不是代码。实际的实现应该非常简单。

从电子邮件中获取签名

  1. 删除目标消息中除呈现文本之外的所有内容。在适当的地方留下 \n 换行符。
  2. 从消息底部开始工作,将每一行存储在一个变量中。当您遇到长行时停止(60 多个字符,确切数字需要实验1)。不要包括长线。
  3. 如果中间某处有多个 \n,请删除它们以及它们上方的所有内容。这是为了删除所有短线和大多数结束称呼。2

现在签名被隔离了。

以下是关于剩余部分的一些假设。除非指定了顺序,否则假定它们可以是任何顺序。

A) End of message and closing greeting will be the topmost line(s)
B) Name
C) Phone Number
D) Email Address
E) Mailing Address
F) Tag line or witty saying, etc.

160 个字符的行长是基于RFC 2822 强烈建议行应该是78 个字符长的事实。 Gmail 尊重这一点。大多数签名行都会比这短,除非整个地址写成一行。使用此方法无法正确检测极短电子邮件(

2由于大多数签名是自动添加的,通常在它们之前有一系列换行符。但是,手写签名可能不遵循此模式,因此根据您正在处理的电子邮件类型,您可能会发现此步骤无益或有害。

识别签名的各个部分

现在您已经降低了正则表达式误报匹配的可能性,您可以查看剩余的行是否与您的任何模式匹配。

  1. 用换行符替换常用分隔符,|是一个常见的例子。

  2. 检查是否有任何行与您的正则表达式模式匹配。如果他们这样做,请从进一步考虑中删除它们。最困难的部分是将名称与其他事物区分开来。建议顺序:

    电子邮件

    电话

    邮政编码(如果找到邮政编码,则为地址)

左边应该是结束称呼、姓名、标语和上述项目的任何格式错误的部分。请注意,虽然大多数正则表达式用于查找错误(用于验证),但您希望匹配错误,从进一步处理中删除行,然后验证或规范化。

在我看来,找出哪个部分是区分名称和标语行的最困难的部分。以下是一些对常见情况有帮助的建议:

  1. 名称由少量单词组成。
  2. 名称在某些地方包含句点 - 在 1-3 个字母单词之后。 (法语有 M. 代表 Messieur)
  3. 名称不包含太多标点符号。除了上述句号之外,可能只有破折号和撇号。您可能会遇到标题前逗号的问题,例如 John Lawyer, Esq。
  4. 标记行可能以逗号结尾
  5. 大写可以暗示(但不是明确地说)某事物是否是名称。

此外,您可以将常用的结束称呼词(真诚、谢谢、欢呼等)列入黑名单。如果将其缩小到一两行,则上面的最有可能是名字,而下面的最有可能标语。

有关识别名称的更多信息,请参阅Find names with Regular Expression。请记住,虽然在一般情况下编写解决方案应该很容易,但自然语言处理是巨大的,超出了像我这样的凡人的范围。 Named Entity Recognition is a known challenge。希望我所描述的内容能在大多数情况下为您提供帮助。

【讨论】:

  • 感谢您回答问题,但您的回答没有满足我的要求,我只想要签名部分,而且 60 多个字符不会一直存在,对吗?
  • 感谢@Josiah 的支持
  • 我已授予您赏金,因为您的回答给了我一个想法,至少在某种程度上解决了我想要的问题。需要实施并查看。
  • 如果我的签名前有一句问候怎么办?我自己多次添加“感谢和问候”,几乎在每封邮件中,在这种情况下它不会超过 60 个字符。如果邮件的最后一行不超过 60 个字符怎么办?
  • @VamshiKrishnaAlladi - 这是另一个更新,包含更多材料、更好的结构和更多的组织。希望这能回答您的大部分问题!
【解决方案2】:

我不使用 GMail,所以我实际上是从我拥有的唯一包含签名的 GMail 消息中构建了这个答案。这是垃圾邮件。不过,让我们看看这能让你走多远……

var sig = document.querySelector('div[data-tooltip="Show trimmed content"]')
                  .parentNode.nextElementSibling

这应该为紧跟隐藏/显示点之后的内容设置一个名为sig 的新变量。请注意,它还会找到引用的对话。这是一个开始,而不是完整的解决方案。

Element.querySelector() 是一种通过 CSS 搜索元素的便捷方式。在这种情况下,我寻找工具提示。我们想要的元素实际上是上一级元素,然后是下一个元素(CSS 不能做,但 JS 可以)。

【讨论】:

  • 抱歉@Adam Katz 这不是我想要的,我已经有了签名。我只想知道如何解析它或 GMail 是如何做到的?
  • 而且修剪后的内容部分没有单独的签名。如果邮件有任何回复,它也有邮件链。
  • 哦,你想解析这个非结构化的内容吗?这是通往精神错乱的捷径(如果没有NLP 和/或其他类似的繁重工作,您将不会走得太远)。
  • 是的,我知道。但我实际上是在寻找第三方库或开源项目,至少可以在一定程度上帮助我。
  • 感谢@Adam Katz 的支持
【解决方案3】:

我想解决这个问题的方法不仅仅是几行代码。我认为它需要某种专门用于此的特殊处理,例如签名解析器或 NLP。这个问题从 8 月就开始了,我想现在是时候关闭它了。

【讨论】:

  • 有没有开源库可以做这个提取?
【解决方案4】:

有一个 API 可以从签名中解析联系人数据。它还将处理回复链。请参阅下面的示例。

https://www.sigparser.com

您可以在 https://api.sigparser.com 的 swagger 详细信息页面上测试 API。

(顺便说一句,我是 SigParser.com 的创建者)

这是一个示例响应:

{
    "error": null,
    "contacts": [
        {
            "firstName": "Bill",
            "lastName": "Gates",
            "emailAddress": "bgates@example.com",
            "phoneNumber": null,
            "fax": null,
            "address": null,
            "title": null,
            "phoneNumbers": [
                {
                    "rationalType": null,
                    "type": "Mobile",
                    "phoneNumber": "7774448888"
                }
            ],
            "twitterUrl": [
                {
                    "emailAddress": "bgates@example.com",
                    "url": "https://twitter.com/BillGates"
                }
            ],
            "linkedInUrl": [
                {
                    "emailAddress": "bgates@example.com",
                    "url": "https://www.linkedin.com/in/williamhgates/"
                }
            ]
        }
    ],
    "isSpammyLookingEmailMessage": false,
    "isSpammyLookingSender": false,
    "isSpam": false,
    "from_LastName": "Gates",
    "from_FirstName": "Bill",
    "from_Fax": null,
    "from_Phone": null,
    "from_Address": null,
    "from_Title": null,
    "from_MobilePhone": "7774448888",
    "from_OfficePhone": null,
    "from_LinkedInUrl": "https://www.linkedin.com/in/williamhgates/",
    "from_TwitterUrl": "https://twitter.com/BillGates",
    "from_EmailAddress": "bgates@example.com",
    "emails": [
        {
            "from_EmailAddress": "bgates@example.com",
            "from_Name": "Bill Gates",
            "textBody": "Hi, good seeing you the other day.\r\n--\r\nBill Gates\r\nCell 777-444-8888LinkedInTwitter",
            "htmlLines": [
                "<div>Hi, good seeing you the other day.</div>",
                "<div>--</div>",
                "<div>Bill Gates</div>",
                "<div>Cell 777-444-8888</div><a href=\"https://www.linkedin.com/in/williamhgates/\">LinkedIn</a><a href=\"https://twitter.com/BillGates\">Twitter</a>"
            ],
            "date": "2017-01-01T00:00:00",
            "didParseCorrectly": true,
            "to": [],
            "cc": []
        }
    ]
}

【讨论】:

    猜你喜欢
    • 2020-09-14
    • 2014-04-25
    • 1970-01-01
    • 2011-12-01
    • 2015-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多