From 7ec6d8468b45123d078e0249039f9755bfa7b1c7 Mon Sep 17 00:00:00 2001 From: Jeff Widman Date: Tue, 18 Nov 2014 16:26:53 -0800 Subject: [PATCH 1/7] Fix two typos --- docs/User Manual.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/User Manual.md b/docs/User Manual.md index 5a99f61e..408a3b26 100644 --- a/docs/User Manual.md +++ b/docs/User Manual.md @@ -172,7 +172,7 @@ Exchanger responds, the domain is considered invalid. above two steps can be cached to improve performance. `flanker` by default uses Redis for this cache, but use of Redis is not required. Similar to the DNS lookup library, any cache can be used here, as long as the interface as the same as that of a `dict`. - See [flanker/addresslib/drivers/redis_cache.py](../flanker/addresslib/drivers/redis_cache.py) + See [flanker/addresslib/drivers/redis_driver.py](../flanker/addresslib/drivers/redis_driver.py) for an example. 3. **Custom Grammar.** Large ESPs rarely if ever support the full grammar that the RFC allows @@ -190,7 +190,7 @@ grammar, then the validator will run that additional check on the localpart of t domain portion of an email address. This can be used to correct common typos like `gmal.com` instead of `gmail.com`. The spelling corrector uses `difflib` which in turn uses the [Ratcliff-Obershelp](http://xlinux.nist.gov/dads/HTML/ratcliffObershelp.html) algorithm -to compute the similarity of two strings. This is a very fast an accurate algorithm for +to compute the similarity of two strings. This is a very fast and accurate algorithm for domain spelling correction. ###### Example: Validate a single email address From b3b242008b4eab47b662108836df911ef0095755 Mon Sep 17 00:00:00 2001 From: Michael Grinich Date: Sun, 2 Nov 2014 16:31:50 -0800 Subject: [PATCH 2/7] Fix for decoding errors if the list includes a non-ASCII string. --- flanker/addresslib/address.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flanker/addresslib/address.py b/flanker/addresslib/address.py index e158b644..88f173b6 100644 --- a/flanker/addresslib/address.py +++ b/flanker/addresslib/address.py @@ -130,7 +130,7 @@ def parse_list(address_list, strict=False, as_tuple=False, metrics=False): # if we have a list, transform it into a string first if isinstance(address_list, list): - address_list = ', '.join([str(addr) for addr in address_list]) + address_list = ', '.join(address_list) # parse try: From a63fe09ca60af9ef5f3a3bd2b3bbf85f95e7fc0a Mon Sep 17 00:00:00 2001 From: Christine Spang Date: Sat, 10 Jan 2015 11:28:08 -0800 Subject: [PATCH 3/7] Add regression test for non-ascii email address parsing. --- tests/addresslib/address_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/addresslib/address_test.py b/tests/addresslib/address_test.py index e35aa16c..d301fcae 100644 --- a/tests/addresslib/address_test.py +++ b/tests/addresslib/address_test.py @@ -106,6 +106,14 @@ def test_addresslist_with_apostrophe(): eq_(u'Eugueny ώ Kontsevoy', lst[0].display_name) +def test_addresslist_non_ascii_list_input(): + al = [u'Aurélien Berger ', 'Os Wi '] + lst = parse_list(al) + eq_(2, len(lst)) + eq_('=?utf-8?q?Aur=C3=A9lien_Berger?= ', lst[0].full_spec()) + eq_('Os Wi ', lst[1].full_spec()) + + def test_edge_cases(): email = EmailAddress('"foo.bar@"@example.com') eq_('"foo.bar@"@example.com', email.address) From be90377ccde2e745396a73e6475c07730dce1039 Mon Sep 17 00:00:00 2001 From: "Jason E. Aten" Date: Wed, 26 Nov 2014 18:03:29 -0800 Subject: [PATCH 4/7] If unable to connect to a MX server, don't cache that result. --- flanker/addresslib/validate.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/flanker/addresslib/validate.py b/flanker/addresslib/validate.py index a85e3cc5..116ad1f6 100644 --- a/flanker/addresslib/validate.py +++ b/flanker/addresslib/validate.py @@ -138,7 +138,6 @@ def mail_exchanger_lookup(domain, metrics=False): mx_hosts = lookup_domain(domain) mtimes['dns_lookup'] += time.time() - bstart if mx_hosts is None: - mx_cache[domain] = False return None, mtimes # test connecting to the mx exchanger @@ -146,7 +145,6 @@ def mail_exchanger_lookup(domain, metrics=False): mail_exchanger = connect_to_mail_exchanger(mx_hosts) mtimes['mx_conn'] = time.time() - bstart if mail_exchanger is None: - mx_cache[domain] = False return None, mtimes # valid mx records, connected to mail exchanger, return True From ede112b6e42dbc3be3e0725db635bec1d9700a06 Mon Sep 17 00:00:00 2001 From: Christine Spang Date: Tue, 13 Jan 2015 13:45:59 -0800 Subject: [PATCH 5/7] Failing test case for case where parse_list() received Address object. --- tests/addresslib/address_test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/addresslib/address_test.py b/tests/addresslib/address_test.py index d301fcae..13088a42 100644 --- a/tests/addresslib/address_test.py +++ b/tests/addresslib/address_test.py @@ -114,6 +114,16 @@ def test_addresslist_non_ascii_list_input(): eq_('Os Wi ', lst[1].full_spec()) +def test_addresslist_address_obj_list_input(): + al = [EmailAddress(u'Aurélien Berger '), + UrlAddress('https://www.example.com')] + lst = parse_list(al) + eq_(2, len(lst)) + eq_('=?utf-8?q?Aur=C3=A9lien_Berger?= ', + lst[0].full_spec()) + eq_('https://www.example.com', lst[1].full_spec()) + + def test_edge_cases(): email = EmailAddress('"foo.bar@"@example.com') eq_('"foo.bar@"@example.com', email.address) From 1dea030ba20e3416c730a97c909134152ec73f79 Mon Sep 17 00:00:00 2001 From: Christine Spang Date: Tue, 13 Jan 2015 13:47:01 -0800 Subject: [PATCH 6/7] Fix parse_list() to handle Address objects with unicode properly also. --- flanker/addresslib/address.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/flanker/addresslib/address.py b/flanker/addresslib/address.py index 88f173b6..c27abef5 100644 --- a/flanker/addresslib/address.py +++ b/flanker/addresslib/address.py @@ -46,6 +46,19 @@ from flanker.mime.message.headers.encodedword import mime_to_unicode from urlparse import urlparse + +def _normalize_address_list(address_list): + parts = [] + + for addr in address_list: + if isinstance(addr, Address): + parts.append(unicode(addr)) + if isinstance(addr, basestring): + parts.append(addr) + + return parts + + @metrics_wrapper() def parse(address, addr_spec_only=False, metrics=False): """ @@ -130,7 +143,7 @@ def parse_list(address_list, strict=False, as_tuple=False, metrics=False): # if we have a list, transform it into a string first if isinstance(address_list, list): - address_list = ', '.join(address_list) + address_list = ', '.join(_normalize_address_list(address_list)) # parse try: From 2f1317653a0248b8eb758a2513c20ec31ef17199 Mon Sep 17 00:00:00 2001 From: Russell Jones Date: Wed, 14 Jan 2015 01:12:28 +0000 Subject: [PATCH 7/7] Version bump and minor refactor. --- flanker/addresslib/address.py | 24 ++++++++++++------------ setup.py | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/flanker/addresslib/address.py b/flanker/addresslib/address.py index c27abef5..6fb098d7 100644 --- a/flanker/addresslib/address.py +++ b/flanker/addresslib/address.py @@ -47,18 +47,6 @@ from urlparse import urlparse -def _normalize_address_list(address_list): - parts = [] - - for addr in address_list: - if isinstance(addr, Address): - parts.append(unicode(addr)) - if isinstance(addr, basestring): - parts.append(addr) - - return parts - - @metrics_wrapper() def parse(address, addr_spec_only=False, metrics=False): """ @@ -620,3 +608,15 @@ def addr_types(self): Returns a set of address types used in addresses in this list. """ return set([addr.addr_type for addr in self.container]) + + +def _normalize_address_list(address_list): + parts = [] + + for addr in address_list: + if isinstance(addr, Address): + parts.append(addr.to_unicode()) + if isinstance(addr, basestring): + parts.append(addr) + + return parts diff --git a/setup.py b/setup.py index e1488d10..b57cf595 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup(name='flanker', - version='0.4.24', + version='0.4.25', description='Mailgun Parsing Tools', long_description=open('README.rst').read(), classifiers=[],