Support more than one address in Message.mail_to

This commit is contained in:
Sergey Lavrinenko 2015-03-28 23:23:08 +03:00
parent 37d0b67dd0
commit 12db9e9633
4 changed files with 67 additions and 9 deletions

View File

@ -7,7 +7,7 @@ from .compat import (string_types, is_callable, to_bytes, formataddr as compat_f
from .utils import (SafeMIMEText, SafeMIMEMultipart, sanitize_address,
parse_name_and_email, load_email_charsets,
encode_header as encode_header_,
renderable, format_date_header)
renderable, format_date_header, parse_name_and_email_list)
from .exc import BadHeaderError
from .backend import ObjectFactory, SMTPBackend
from .store import MemoryFileStore, BaseFile
@ -66,10 +66,7 @@ class BaseMessage(object):
mail_from = property(get_mail_from, set_mail_from)
def set_mail_to(self, mail_to):
# Now we parse only one to-addr
# TODO: parse list of to-addrs
mail_to = mail_to and parse_name_and_email(mail_to)
self._mail_to = mail_to and [mail_to, ] or []
self._mail_to = parse_name_and_email_list(mail_to)
def get_mail_to(self):
return self._mail_to

View File

@ -107,15 +107,36 @@ def test_sanitize_header():
emails.Message(html='...', **{header: value}).as_message()
def test_address_header_not_double_encoded():
msg = {}
m = Message()
def test_headers_not_double_encoded():
TEXT = ''
m = Message()
m.mail_from = (TEXT, 'a@b.c')
m.mail_to = (TEXT, 'a@b.c')
m.subject = TEXT
m.html = '...'
msg = m.as_message()
assert decode_header(parseaddr(msg['From'])[0]) == TEXT
assert decode_header(parseaddr(msg['To'])[0]) == TEXT
assert decode_header(msg['Subject']) == TEXT
def test_message_addresses():
m = Message()
m.mail_from = "웃 <b@c.d>"
assert m.mail_from == ("", "b@c.d")
m.mail_from = ["", "b@c.d"]
assert m.mail_from == ("", "b@c.d")
m.mail_to = ("", "b@c.d")
assert m.mail_to == [("", "b@c.d"), ]
m.mail_to = [("", "b@c.d"), "e@f.g"]
assert m.mail_to == [("", "b@c.d"), (None, "e@f.g")]
def test_message_policy():

View File

@ -4,9 +4,10 @@ import pytest
import datetime
import time
from emails.utils import (parse_name_and_email, encode_header, decode_header, sanitize_address, fetch_url,
MessageID, format_date_header)
MessageID, format_date_header, parse_name_and_email_list)
from emails.exc import HTTPLoaderError
def test_parse_name_and_email():
assert parse_name_and_email('john@smith.me') == (None, 'john@smith.me')
assert parse_name_and_email('"John Smith" <john@smith.me>') == \
@ -19,6 +20,13 @@ def test_parse_name_and_email():
parse_name_and_email([42,])
def test_parse_name_and_list():
assert parse_name_and_email_list(['a@b.c', 'd@e.f']) == [(None, 'a@b.c'), (None, 'd@e.f')]
assert parse_name_and_email_list(('a@b.c', 'd@e.f')) == [('a@b.c', 'd@e.f'), ]
assert parse_name_and_email_list(['a@b.c']) == [(None, 'a@b.c')]
assert parse_name_and_email_list("♤ <a@b.c>") == [("", 'a@b.c'), ]
def test_header_encode():
v = 'Мама мыла раму. ' * 30
assert decode_header(encode_header(v)).strip() == v.strip()

View File

@ -87,6 +87,38 @@ class MessageID:
return "".join(['<', r, '@', self.domain, '>'])
def parse_name_and_email_list(elements, encoding='utf-8'):
"""
Parse a list of address-like elements, i.e.:
* "name <email>"
* "email"
* (name, email)
:param elements: one element or list of elements
:param encoding: element encoding, if bytes
:return: list of pairs (name, email)
"""
if not elements:
return []
if isinstance(elements, string_types):
return [parse_name_and_email(elements, encoding), ]
if not isinstance(elements, (list, tuple)):
raise TypeError("Can not parse_name_and_email_list from %s" % elements.__repr__())
if len(elements) == 2:
# Oops, it may be pair (name, email) or pair of emails [email1, email2]
# Let's do some guesses
if isinstance(elements, tuple):
n, e = elements
if isinstance(e, string_types) and (not n or isinstance(e, string_types)):
# It is probably a pair (name, email)
return [parse_name_and_email(elements, encoding), ]
return [parse_name_and_email(x, encoding) for x in elements]
def parse_name_and_email(obj, encoding='utf-8'):
# In: 'john@smith.me' or '"John Smith" <john@smith.me>' or ('John Smith', 'john@smith.me')
# Out: (u'John Smith', u'john@smith.me')