【问题标题】:Parse Email Reply from Thread in Zapier从 Zapier 中的 Thread 解析电子邮件回复
【发布时间】:2020-09-14 21:51:10
【问题描述】:

我正在考虑从电子邮件线程中解析出最近的回复/消息,作为 zap 的一部分。

我找到了这个链接,但是如何在 Zap 中使用它? https://github.com/zapier/email-reply-parser

即当我从 gmail 中提取一个线程时,我如何提取最近的消息?

这在 Zapier 的代码中是否可行?如果可以,如何实现?

例如

输入:

好的,我会在早上给你发电子邮件。

2012 年 11 月 16 日星期五下午 1:48,Zapier 写道:

我们的支持团队刚刚评论了您的公开票证: “嗨,Royce,我们早上可以聊聊你的问题吗?”


输出: 即解析后的电子邮件:

好的,我会在早上给你发电子邮件。

【问题讨论】:

    标签: python zapier


    【解决方案1】:

    首先:不能直接在代码步骤中使用它。 Python 代码步骤无权访问外部包。

    也就是说,那个包只是 Python 代码,没有什么能阻止你将所有重要的代码复制到代码步骤中并以这种方式使用它。

    值得注意的是,链接的代码相当陈旧,而且看起来无人维护,因此如果不进行修改,它是不可能工作的。

    【讨论】:

    • 谢谢 - 我设法复制了重要的代码并将其破解。你知道有什么更好的代码来去除电子邮件回复吗?
    • 我没有,这不是我曾经研究过的东西!此外,如果此答案解决了您的问题,请确保对其进行投票并将其标记为正确(info)(或发布您自己的)
    【解决方案2】:

    我尝试修改了这个https://github.com/zapier/email-reply-parser,它似乎也很有效。

    """
        email_reply_parser is a python library port of GitHub's Email Reply Parser.
    
        For more information, visit https://github.com/zapier/email-reply-parser
    """
    
    import re
    
    
    class EmailReplyParser(object):
        """ Represents a email message that is parsed.
        """
    
        @staticmethod
        def read(text):
            """ Factory method that splits email into list of fragments
    
                text - A string email body
    
                Returns an EmailMessage instance
            """
            return EmailMessage(text).read()
    
        @staticmethod
        def parse_reply(text):
            """ Provides the reply portion of email.
    
                text - A string email body
    
                Returns reply body message
            """
            return EmailReplyParser.read(text).reply
    
    
    class EmailMessage(object):
        """ An email message represents a parsed email body.
        """
    
        SIG_REGEX = re.compile(r'(--|__|-\w)|(^Sent from my (\w+\s*){1,3})')
        QUOTE_HDR_REGEX = re.compile('On.*wrote:$')
        QUOTED_REGEX = re.compile(r'(>+)')
        HEADER_REGEX = re.compile(r'^\*?(From|Sent|To|Subject):\*? .+')
        _MULTI_QUOTE_HDR_REGEX = r'(?!On.*On\s.+?wrote:)(On\s(.+?)wrote:)'
        MULTI_QUOTE_HDR_REGEX = re.compile(_MULTI_QUOTE_HDR_REGEX, re.DOTALL | re.MULTILINE)
        MULTI_QUOTE_HDR_REGEX_MULTILINE = re.compile(_MULTI_QUOTE_HDR_REGEX, re.DOTALL)
    
        def __init__(self, text):
            self.fragments = []
            self.fragment = None
            self.text = text.replace('\r\n', '\n')
            self.found_visible = False
    
        def read(self):
            """ Creates new fragment for each line
                and labels as a signature, quote, or hidden.
    
                Returns EmailMessage instance
            """
    
            self.found_visible = False
    
            is_multi_quote_header = self.MULTI_QUOTE_HDR_REGEX_MULTILINE.search(self.text)
            if is_multi_quote_header:
                self.text = self.MULTI_QUOTE_HDR_REGEX.sub(is_multi_quote_header.groups()[0].replace('\n', ''), self.text)
    
            # Fix any outlook style replies, with the reply immediately above the signature boundary line
            #   See email_2_2.txt for an example
            self.text = re.sub('([^\n])(?=\n ?[_-]{7,})', '\\1\n', self.text, re.MULTILINE)
    
            self.lines = self.text.split('\n')
            self.lines.reverse()
    
            for line in self.lines:
                self._scan_line(line)
    
            self._finish_fragment()
    
            self.fragments.reverse()
    
            return self
    
        @property
        def reply(self):
            """ Captures reply message within email
            """
            reply = []
            for f in self.fragments:
                if not (f.hidden or f.quoted):
                    reply.append(f.content)
            return '\n'.join(reply)
    
        def _scan_line(self, line):
            """ Reviews each line in email message and determines fragment type
    
                line - a row of text from an email message
            """
            is_quote_header = self.QUOTE_HDR_REGEX.match(line) is not None
            is_quoted = self.QUOTED_REGEX.match(line) is not None
            is_header = is_quote_header or self.HEADER_REGEX.match(line) is not None
    
            if self.fragment and len(line.strip()) == 0:
                if self.SIG_REGEX.match(self.fragment.lines[-1].strip()):
                    self.fragment.signature = True
                    self._finish_fragment()
    
            if self.fragment \
                    and ((self.fragment.headers == is_header and self.fragment.quoted == is_quoted) or
                             (self.fragment.quoted and (is_quote_header or len(line.strip()) == 0))):
    
                self.fragment.lines.append(line)
            else:
                self._finish_fragment()
                self.fragment = Fragment(is_quoted, line, headers=is_header)
    
        def quote_header(self, line):
            """ Determines whether line is part of a quoted area
    
                line - a row of the email message
    
                Returns True or False
            """
            return self.QUOTE_HDR_REGEX.match(line[::-1]) is not None
    
        def _finish_fragment(self):
            """ Creates fragment
            """
    
            if self.fragment:
                self.fragment.finish()
                if self.fragment.headers:
                    # Regardless of what's been seen to this point, if we encounter a headers fragment,
                    # all the previous fragments should be marked hidden and found_visible set to False.
                    self.found_visible = False
                    for f in self.fragments:
                        f.hidden = True
                if not self.found_visible:
                    if self.fragment.quoted \
                            or self.fragment.headers \
                            or self.fragment.signature \
                            or (len(self.fragment.content.strip()) == 0):
    
                        self.fragment.hidden = True
                    else:
                        self.found_visible = True
                self.fragments.append(self.fragment)
            self.fragment = None
    
    
    class Fragment(object):
        """ A Fragment is a part of
            an Email Message, labeling each part.
        """
    
        def __init__(self, quoted, first_line, headers=False):
            self.signature = False
            self.headers = headers
            self.hidden = False
            self.quoted = quoted
            self._content = None
            self.lines = [first_line]
    
        def finish(self):
            """ Creates block of content with lines
                belonging to fragment.
            """
            self.lines.reverse()
            self._content = '\n'.join(self.lines)
            self.lines = None
    
        @property
        def content(self):
            return self._content.strip()
    return {'emailstring': EmailReplyParser.parse_reply(input_data['body'])}
    

    【讨论】:

      猜你喜欢
      • 2010-09-21
      • 2015-05-03
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 2016-12-18
      相关资源
      最近更新 更多