summaryrefslogtreecommitdiff
path: root/src/leap/mail/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/mail/utils.py')
-rw-r--r--src/leap/mail/utils.py54
1 files changed, 51 insertions, 3 deletions
diff --git a/src/leap/mail/utils.py b/src/leap/mail/utils.py
index fed24b3..64fca98 100644
--- a/src/leap/mail/utils.py
+++ b/src/leap/mail/utils.py
@@ -17,12 +17,15 @@
"""
Mail utilities.
"""
+from email.utils import parseaddr
import json
import re
import traceback
import Queue
from leap.soledad.common.document import SoledadDocument
+from leap.common.check import leap_assert_type
+from twisted.mail import smtp
CHARSET_PATTERN = r"""charset=([\w-]+)"""
@@ -42,9 +45,12 @@ def first(things):
def empty(thing):
"""
Return True if a thing is None or its length is zero.
+ If thing is a number (int, float, long), return False.
"""
if thing is None:
return True
+ if isinstance(thing, (int, float, long)):
+ return False
if isinstance(thing, SoledadDocument):
thing = thing.content
try:
@@ -224,10 +230,31 @@ def accumulator_queue(fun, lim):
return _accumulator
+def validate_address(address):
+ """
+ Validate C{address} as defined in RFC 2822.
+
+ :param address: The address to be validated.
+ :type address: str
+
+ @return: A valid address.
+ @rtype: str
+
+ @raise smtp.SMTPBadRcpt: Raised if C{address} is invalid.
+ """
+ leap_assert_type(address, str)
+ # in the following, the address is parsed as described in RFC 2822 and
+ # ('', '') is returned if the parse fails.
+ _, address = parseaddr(address)
+ if address == '':
+ raise smtp.SMTPBadRcpt(address)
+ return address
+
#
# String manipulation
#
+
class CustomJsonScanner(object):
"""
This class is a context manager definition used to monkey patch the default
@@ -273,13 +300,13 @@ class CustomJsonScanner(object):
end = s.find("\"", idx)
while not found:
try:
- if s[end-1] != "\\":
+ if s[end - 1] != "\\":
found = True
else:
- end = s.find("\"", end+1)
+ end = s.find("\"", end + 1)
except Exception:
found = True
- return s[idx:end].decode("string-escape"), end+1
+ return s[idx:end].decode("string-escape"), end + 1
def __enter__(self):
"""
@@ -325,3 +352,24 @@ def json_loads(data):
obj = json.loads(data, cls=json.JSONDecoder)
return obj
+
+
+class CaseInsensitiveDict(dict):
+ """
+ A dictionary subclass that will allow case-insenstive key lookups.
+ """
+ def __init__(self, d=None):
+ if d is None:
+ d = []
+ if isinstance(d, dict):
+ for key, value in d.items():
+ self[key] = value
+ else:
+ for key, value in d:
+ self[key] = value
+
+ def __setitem__(self, key, value):
+ super(CaseInsensitiveDict, self).__setitem__(key.lower(), value)
+
+ def __getitem__(self, key):
+ return super(CaseInsensitiveDict, self).__getitem__(key.lower())