root / trunk / turbomail / util.py

Revision 120, 4.1 kB (checked in by fs, 3 weeks ago)

re-added the SMTP from functionality which was not honored by the SMTPTransport
renamed the envelope method in Message because an envelope normally has a sender and a recipient but this method was only about the SMTP from so I renamed it to envelope_sender.

  • Property svn:keywords set to Revision
Line 
1# encoding: utf-8
2"""TurboMail utility functions and support classes."""
3
4__version__ = "$Revision$"
5
6import re
7
8from email.Header import Header
9from email.Utils import parseaddr, formataddr
10
11__all__ = ['Address', 'AddressList']
12
13
14class Address(object):
15    """Validated electronic mail address class.
16   
17    This class knows how to validate and format e-mail addresses.  It
18    uses Python's built-in `parseaddr` and `formataddr` helper
19    functions and helps guarantee a uniform base for all e-mail
20    address operations.
21   
22    The AddressList unit tests provide comprehensive testing of this
23    class as well."""
24   
25    validator = re.compile(r'^(\w([-.\w]*\w)*(\+\w+)?@(\w(\-*\w)+)+(\.\w{2,9})*)$', re.UNICODE)
26   
27    def __init__(self, name_or_email, email=None):
28        if email == None:
29            if isinstance(name_or_email, AddressList):
30                assert len(name_or_email) > 0
31                name_or_email = str(name_or_email[0])
32            if isinstance(name_or_email, basestring):
33                self.name, self.address = parseaddr(name_or_email)
34            elif not isinstance(name_or_email, basestring):
35                self.name, self.address = name_or_email
36        else:
37            self.name = name_or_email
38            self.address = email
39        if not self.validator.match(self.address):
40            raise ValueError, 'Invalid e-mail address.'
41   
42    def __cmp__(self, other):
43        if isinstance(other, (Address, basestring)):
44            return cmp(str(self), str(other))
45        elif isinstance(other, tuple):
46            return cmp((self.name, self.address), other)
47        return cmp(self, other)
48   
49    def __repr__(self):
50        return 'Address(\'%s\')' % str(self)
51   
52    def __str__(self):
53        return self.encode()
54   
55    def encode(self, encoding="ascii"):
56        assert self.address, "You must specify an address."
57        name_string = self.name
58        if isinstance(name_string, unicode):
59            name_string = str(Header(name_string, encoding))
60       
61        # Encode punycode for internationalized domains.
62        localpart, domain = self.address.split("@")
63        if isinstance(domain, unicode):
64            domain = domain.encode("idna")
65        address = "@".join((localpart, domain))
66       
67        return formataddr((name_string, address)).replace("\n", "")
68
69
70class AddressList(list):
71    def __init__(self, addresses=[], encoding=None):
72        super(AddressList, self).__init__()
73       
74        self.encoding = encoding
75        if isinstance(addresses, (basestring, tuple)):
76            addresses = [addresses]
77       
78        if addresses is not None:
79            self.extend(addresses)
80   
81    def __repr__(self):
82        if not self: return "AddressList()"
83        return "AddressList(\"" + "\", \"".join([str(i) for i in self]) + "\")"
84   
85    def __str__(self):
86        return self.encode(self.encoding)
87   
88    def encode(self, encoding="ascii"):
89        addresses = []
90        for address in self:
91            addresses.append(address.encode(encoding))
92        return ",\n ".join(addresses)
93   
94    def __setitem__(self, k, value):
95        if not isinstance(value, Address):
96            value = Address(value)
97       
98        super(AddressList, self).__setitem__(k, value)
99   
100    def extend(self, value):
101        values = []
102       
103        for i in value:
104            if not isinstance(i, Address):
105                i = Address(i)
106            values.append(i)
107       
108        super(AddressList, self).extend(values)
109   
110    def append(self, value):
111        self.extend([value])
112   
113    def addresses(self):
114        return AddressList([i.address for i in self])
115   
116    addresses = property(addresses)
117   
118    def protected(cls, field):
119        def fget(self):
120            return getattr(self, field)
121
122        def fset(self, value):
123            if not isinstance(value, AddressList):
124                value = AddressList(value)
125
126            setattr(self, field, AddressList(value))
127
128        def fdel(self):
129            setattr(self, field, AddressList())
130
131        return property(fget, fset, fdel)
132   
133    protected = classmethod(protected)
Note: See TracBrowser for help on using the browser.