classification
Title: email.Utils.parseaddr fails to parse valid addresses
Type: behavior Stage: test needed
Components: email, Library (Lib) Versions: Python 3.3, Python 3.2, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: barry, christian.heimes, eric.araujo, martin.panter, melicertes, r.david.murray, sdgathman
Priority: normal Keywords:

Created on 2004-09-09 20:43 by melicertes, last changed 2014-07-25 13:01 by martin.panter.

Messages (8)
msg22413 - (view) Author: Charles (melicertes) Date: 2004-09-09 20:43
email.Utils.parseaddr() does not successfully parse a
field value into a (comment, address) pair if the
address contains a source route with more than one hop.

i.e., it is successfully parses this:

  "God" <@hop1.org:jeff@spec.org>

to get the address <jeff@spec.org>, but it fails to do
the same if supplied with a 2-hop source route:

  "God" <@hop1.org,@hop2.net:jeff@spec.org>

In this case, it gets the comment ("God") right, but
fails to extract the address.

Multi-hop source routes, while deprecated, are still
valid in rfc2822.

msg59669 - (view) Author: Stuart D Gathman (sdgathman) Date: 2008-01-10 16:34
# A quick and very dirty fix for common broken cases, with test cases.

import rfc822

def parseaddr(t):
  """Split email into Fullname and address.

  >>> parseaddr('user@example.com')
  ('', 'user@example.com')
  >>> parseaddr('"Full Name" <foo@example.com>')
  ('Full Name', 'foo@example.com')
  >>> parseaddr('spam@viagra.com <foo@example.com>')
  ('spam@viagra.com', 'foo@example.com')
  >>> parseaddr('"God" <@hop1.org,@hop2.net:jeff@spec.org>')
  ('God', 'jeff@spec.org')
  """
  #return email.Utils.parseaddr(t)
  res = rfc822.parseaddr(t)
  # dirty fix for some broken cases
  if not res[0]:
    pos = t.find('<')
    if pos > 0 and t[-1] == '>':
      addrspec = t[pos+1:-1]
      pos1 = addrspec.rfind(':')
      if pos1 > 0:
        addrspec = addrspec[pos1+1:]
      return rfc822.parseaddr('"%s" <%s>' % (t[:pos].strip(),addrspec))
  if not res[1]:
    pos = t.find('<')
    if pos > 0 and t[-1] == '>':
      addrspec = t[pos+1:-1]
      pos1 = addrspec.rfind(':')
      if pos1 > 0:
        addrspec = addrspec[pos1+1:]
      return rfc822.parseaddr('%s<%s>' % (t[:pos].strip(),addrspec))
  return res
msg59670 - (view) Author: Stuart D Gathman (sdgathman) Date: 2008-01-10 16:37
Ok, I see the '@' is technically not allowed in an atom.  But it either
needs to throw an invalid syntax exception, or heuristically return
something reasonable.
msg59671 - (view) Author: Stuart D Gathman (sdgathman) Date: 2008-01-10 16:39
Repeating because previous real life test case was rejected as 'spam':

It also fails to parse:
>>> from email.Utils import parseaddr
>>> parseaddr('foo@spammer.com <bar@baz.com>')
('', 'foo@spammer.com')

Getting the wrong part as the actual email to boot!  Checked 2.4 and 2.5.
msg59735 - (view) Author: Stuart D Gathman (sdgathman) Date: 2008-01-11 19:08
Same or related issues: Issue1221, Issue1409460
msg59737 - (view) Author: Stuart D Gathman (sdgathman) Date: 2008-01-11 19:14
Test cases so far:
  >>> parseaddr('user@example.com')
  ('', 'user@example.com')
  >>> parseaddr('"Full Name" <foo@example.com>')
  ('Full Name', 'foo@example.com')
  >>> parseaddr('spam@spammer.com <foo@example.com>')
  ('spam@spammer.com', 'foo@example.com')
  >>> parseaddr('God@heaven <@hop1.org,@hop2.net:jeff@spec.org>')
  ('God@heaven', 'jeff@spec.org')
  >>> parseaddr('Real Name ((comment)) <addr...@example.com>')
  ('Real Name', 'addr...@example.com')
  >>> parseaddr('a(WRONG)@b')
  ('', 'a@b')
msg59751 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2008-01-11 21:18
An example from #1221:

>>> email.Utils.parseaddr("a(WRONG)@b")
('WRONG WRONG', 'a@b')
msg59753 - (view) Author: Stuart D Gathman (sdgathman) Date: 2008-01-11 21:21
tiran: yes, but that is the wrong answer, and that example is already in
the testcase list (with what I believe is the right answer).
History
Date User Action Args
2014-07-25 13:01:28martin.pantersetnosy: + martin.panter
2012-05-16 01:57:28r.david.murraysetassignee: r.david.murray ->
components: + email
versions: - Python 3.1
2011-03-14 03:26:43r.david.murraysetnosy: barry, melicertes, christian.heimes, sdgathman, eric.araujo, r.david.murray
versions: + Python 3.3
2010-12-27 18:26:58r.david.murraysetnosy: barry, melicertes, christian.heimes, sdgathman, eric.araujo, r.david.murray
versions: + Python 3.1, Python 3.2
2010-07-17 11:44:39eric.araujosetnosy: + eric.araujo
2010-05-05 13:40:29barrysetassignee: barry -> r.david.murray

nosy: + r.david.murray
2009-07-04 02:42:37ezio.melottisetstage: test needed
versions: + Python 2.7, - Python 2.5, Python 2.4, Python 2.3
2008-01-28 08:33:42loewissetmessages: - msg59668
2008-01-11 21:21:47sdgathmansetmessages: + msg59753
2008-01-11 21:18:31christian.heimeslinkissue1221 superseder
2008-01-11 21:18:11christian.heimessetnosy: + christian.heimes
messages: + msg59751
2008-01-11 19:14:26sdgathmansetmessages: + msg59737
2008-01-11 19:08:47sdgathmansetmessages: + msg59735
2008-01-10 16:39:04sdgathmansetmessages: + msg59671
2008-01-10 16:37:37sdgathmansetmessages: + msg59670
2008-01-10 16:34:08sdgathmansetmessages: + msg59669
2008-01-10 16:22:47sdgathmansettype: behavior
2008-01-10 16:22:18sdgathmansetnosy: + sdgathman
messages: + msg59668
versions: + Python 2.5, Python 2.4
2004-09-09 20:43:42melicertescreate