Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdd84563dd | ||
|
|
8138ea9a60 | ||
|
|
c171f9a875 | ||
|
|
3f97a8b8ff | ||
|
|
1147767ff3 | ||
|
|
afff08b017 | ||
|
|
238a5de5cc |
2
setup.py
2
setup.py
@@ -29,7 +29,7 @@ class InstallCommand(install):
|
||||
|
||||
|
||||
setup(name='talon',
|
||||
version='1.4.5',
|
||||
version='1.4.7',
|
||||
description=("Mailgun library "
|
||||
"to extract message quotations and signatures."),
|
||||
long_description=open("README.rst").read(),
|
||||
|
||||
@@ -87,23 +87,24 @@ def cut_gmail_quote(html_message):
|
||||
|
||||
def cut_microsoft_quote(html_message):
|
||||
''' Cuts splitter block and all following blocks. '''
|
||||
#use EXSLT extensions to have a regex match() function with lxml
|
||||
ns = {"re": "http://exslt.org/regular-expressions"}
|
||||
|
||||
#general pattern: @style='border:none;border-top:solid <color> 1.0pt;padding:3.0pt 0<unit> 0<unit> 0<unit>'
|
||||
#outlook 2007, 2010 (international) <color=#B5C4DF> <unit=cm>
|
||||
#outlook 2007, 2010 (american) <color=#B5C4DF> <unit=pt>
|
||||
#outlook 2013 (international) <color=#E1E1E1> <unit=cm>
|
||||
#outlook 2013 (american) <color=#E1E1E1> <unit=pt>
|
||||
#also handles a variant with a space after the semicolon
|
||||
splitter = html_message.xpath(
|
||||
#outlook 2007, 2010 (international)
|
||||
"//div[@style='border:none;border-top:solid #B5C4DF 1.0pt;"
|
||||
"padding:3.0pt 0cm 0cm 0cm']|"
|
||||
#outlook 2007, 2010 (american)
|
||||
"//div[@style='border:none;border-top:solid #B5C4DF 1.0pt;"
|
||||
"padding:3.0pt 0in 0in 0in']|"
|
||||
#outlook 2013 (international)
|
||||
"//div[@style='border:none;border-top:solid #E1E1E1 1.0pt;"
|
||||
"padding:3.0pt 0cm 0cm 0cm']|"
|
||||
#outlook 2013 (american)
|
||||
"//div[@style='border:none;border-top:solid #E1E1E1 1.0pt;"
|
||||
"padding:3.0pt 0in 0in 0in']|"
|
||||
#outlook 2007, 2010, 2013 (international, american)
|
||||
"//div[@style[re:match(., 'border:none; ?border-top:solid #(E1E1E1|B5C4DF) 1.0pt; ?"
|
||||
"padding:3.0pt 0(in|cm) 0(in|cm) 0(in|cm)')]]|"
|
||||
#windows mail
|
||||
"//div[@style='padding-top: 5px; "
|
||||
"border-top-color: rgb(229, 229, 229); "
|
||||
"border-top-width: 1px; border-top-style: solid;']"
|
||||
, namespaces=ns
|
||||
)
|
||||
|
||||
if splitter:
|
||||
|
||||
@@ -22,7 +22,7 @@ import six
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
RE_FWD = re.compile("^[-]+[ ]*Forwarded message[ ]*[-]+$", re.I | re.M)
|
||||
RE_FWD = re.compile("^[-]+[ ]*Forwarded message[ ]*[-]+\s*$", re.I | re.M)
|
||||
|
||||
RE_ON_DATE_SMB_WROTE = re.compile(
|
||||
u'(-*[>]?[ ]?({0})[ ].*({1})(.*\n){{0,2}}.*({2}):?-*)'.format(
|
||||
@@ -139,13 +139,17 @@ RE_ORIGINAL_MESSAGE = re.compile(u'[\s]*[-]+[ ]*({})[ ]*[-]+'.format(
|
||||
'Oprindelig meddelelse',
|
||||
))), re.I)
|
||||
|
||||
RE_FROM_COLON_OR_DATE_COLON = re.compile(u'(_+\r?\n)?[\s]*(:?[*]?{})[\s]?:[*]?.*'.format(
|
||||
RE_FROM_COLON_OR_DATE_COLON = re.compile(u'((_+\r?\n)?[\s]*:?[*]?({})[\s]?:([^\n$]+\n){{1,2}}){{2,}}'.format(
|
||||
u'|'.join((
|
||||
# "From" in different languages.
|
||||
'From', 'Van', 'De', 'Von', 'Fra', u'Från',
|
||||
# "Date" in different languages.
|
||||
'Date', 'Datum', u'Envoyé', 'Skickat', 'Sendt',
|
||||
))), re.I)
|
||||
'Date', '[S]ent', 'Datum', u'Envoyé', 'Skickat', 'Sendt', 'Gesendet',
|
||||
# "Subject" in different languages.
|
||||
'Subject', 'Betreff', 'Objet', 'Emne', u'Ämne',
|
||||
# "To" in different languages.
|
||||
'To', 'An', 'Til', u'À', 'Till'
|
||||
))), re.I | re.M)
|
||||
|
||||
# ---- John Smith wrote ----
|
||||
RE_ANDROID_WROTE = re.compile(u'[\s]*[-]+.*({})[ ]*[-]+'.format(
|
||||
@@ -567,7 +571,6 @@ def _correct_splitlines_in_headers(markers, lines):
|
||||
updated_markers = ""
|
||||
i = 0
|
||||
in_header_block = False
|
||||
|
||||
for m in markers:
|
||||
# Only set in_header_block flag when we hit an 's' and line is a header
|
||||
if m == 's':
|
||||
|
||||
@@ -131,7 +131,7 @@ def html_tree_to_text(tree):
|
||||
for el in tree.iter():
|
||||
el_text = (el.text or '') + (el.tail or '')
|
||||
if len(el_text) > 1:
|
||||
if el.tag in _BLOCKTAGS:
|
||||
if el.tag in _BLOCKTAGS + _HARDBREAKS:
|
||||
text += "\n"
|
||||
if el.tag == 'li':
|
||||
text += " * "
|
||||
@@ -142,7 +142,8 @@ def html_tree_to_text(tree):
|
||||
if href:
|
||||
text += "(%s) " % href
|
||||
|
||||
if el.tag in _HARDBREAKS and text and not text.endswith("\n"):
|
||||
if (el.tag in _HARDBREAKS and text and
|
||||
not text.endswith("\n") and not el_text):
|
||||
text += "\n"
|
||||
|
||||
retval = _rm_excessive_newlines(text)
|
||||
|
||||
@@ -453,7 +453,8 @@ def test_link_closed_with_quotation_marker_on_new_line():
|
||||
msg_body = '''8.45am-1pm
|
||||
|
||||
From: somebody@example.com
|
||||
|
||||
Date: Wed, 16 May 2012 00:15:02 -0600
|
||||
|
||||
<http://email.example.com/c/dHJhY2tpbmdfY29kZT1mMDdjYzBmNzM1ZjYzMGIxNT
|
||||
> <bob@example.com <mailto:bob@example.com> >
|
||||
|
||||
@@ -494,7 +495,9 @@ def test_from_block_starts_with_date():
|
||||
msg_body = """Blah
|
||||
|
||||
Date: Wed, 16 May 2012 00:15:02 -0600
|
||||
To: klizhentas@example.com"""
|
||||
To: klizhentas@example.com
|
||||
|
||||
"""
|
||||
eq_('Blah', quotations.extract_from_plain(msg_body))
|
||||
|
||||
|
||||
@@ -564,11 +567,12 @@ def test_mark_message_lines():
|
||||
# next line should be marked as splitter
|
||||
'_____________',
|
||||
'From: foo@bar.com',
|
||||
'Date: Wed, 16 May 2012 00:15:02 -0600',
|
||||
'',
|
||||
'> Hi',
|
||||
'',
|
||||
'Signature']
|
||||
eq_('tessemet', quotations.mark_message_lines(lines))
|
||||
eq_('tesssemet', quotations.mark_message_lines(lines))
|
||||
|
||||
lines = ['Just testing the email reply',
|
||||
'',
|
||||
@@ -807,7 +811,7 @@ def test_split_email():
|
||||
>
|
||||
>
|
||||
"""
|
||||
expected_markers = "stttttsttttetesetesmmmmmmssmmmmmmsmmmmmmmm"
|
||||
expected_markers = "stttttsttttetesetesmmmmmmsmmmmmmmmmmmmmmmm"
|
||||
markers = quotations.split_emails(msg)
|
||||
eq_(markers, expected_markers)
|
||||
|
||||
@@ -823,3 +827,15 @@ that this line is intact."""
|
||||
|
||||
parsed = quotations.extract_from_plain(msg_body)
|
||||
eq_(msg_body, parsed.decode('utf8'))
|
||||
|
||||
|
||||
def test_appointment():
|
||||
msg_body = """Invitation for an interview:
|
||||
|
||||
Date: Wednesday 3, October 2011
|
||||
Time: 7 : 00am
|
||||
Address: 130 Fox St
|
||||
|
||||
Please bring in your ID."""
|
||||
parsed = quotations.extract_from_plain(msg_body)
|
||||
eq_(msg_body, parsed.decode('utf8'))
|
||||
|
||||
Reference in New Issue
Block a user