Changeset 41

Show
Ignore:
Timestamp:
10/22/07 01:55:26 (1 year ago)
Author:
amcgregor
Message:

Rewrite of the AddressList? class and its integration into the Message class.

Location:
branches/3.0/turbomail
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • branches/3.0/turbomail/message.py

    r40 r41  
    3737         
    3838        def __str__(self): 
    39                 assert self.sender 
    40                 assert self.recipients 
    41                 assert self.message 
    42                  
    4339                return self.message 
    4440 
    4541 
    4642class Message(object): 
    47         """Simple e-mail message class. 
    48          
    49         Message provides a means to easily create e-mail messages to be 
    50         sent through the Dispatch mechanism or MailPool.  Message provides 
    51         various helper functions to correctly format plain text, dual plain 
    52         text and rich text MIME encoded messages, as well as handle 
    53         embedded and external attachments. 
    54          
    55         All properties can be set from the constructor. 
    56         """ 
     43        """Simple e-mail message class.""" 
    5744         
    5845        def __init__(self, **kw): 
     
    7057                self._dirty = False 
    7158                 
    72                 self.date = formatdate(localtime=True) 
    73                  
    74                 self._sender = AddressList(turbomail.config.get("mail.message.sender", None)) 
    75                 self._envelope = AddressList(turbomail.config.get("mail.message.envelope", None)) 
    76                 self._reply = AddressList(turbomail.config.get("mail.message.reply", None)) 
    77                 self._to = AddressList() 
    78                 self._cc = AddressList(turbomail.config.get("mail.message.cc", None)) 
    79                 self._bcc = AddressList(turbomail.config.get("mail.message.bcc", None)) 
    80                 self._disposition = AddressList(turbomail.config.get("mail.message.disposition", None)) 
    81                  
    82                 self.organization = turbomail.config.get("mail.message.organization", None) 
    83                 self.encoding = turbomail.config.get("mail.encoding", 'us-ascii') 
    84                 self.priority = turbomail.config.get("mail.message.priority", None) 
    85                 self.subject = None 
    86                 self.plain = None 
    87                 self.rich = None 
    88                 self.attachments = [] 
    89                 self.embedded = [] 
    90                 self.headers = turbomail.config.get("mail.message.headers", []) 
    91                 self.tries = turbomail.config.get("mail.tries", 3) 
    92                  
    93                 self._id = None 
    94                  
    95                 for i, j in kw.iteritems(): 
    96                         assert hasattr(self, i), "Unknown attribute: '%s'" % i 
    97                         setattr(self, i, j) 
     59                def configget(name, key, default=None): 
     60                        pass 
     61                 
     62                self.date = kw.get("date", formatdate(localtime=True)) 
     63                 
     64                self._senders = AddressList(kw.get("sender", turbomail.config.get("mail.message.sender", None))) 
     65                self._senders = AddressList(kw.get("senders", turbomail.config.get("mail.message.senders", self._senders))) 
     66                self._envelope = AddressList(kw.get("envelope", turbomail.config.get("mail.message.envelope", None))) 
     67                self._reply = AddressList(kw.get("reply", turbomail.config.get("mail.message.reply", None))) 
     68                self._to = AddressList(kw.get("to", None)) 
     69                self._cc = AddressList(kw.get("cc", turbomail.config.get("mail.message.cc", None))) 
     70                self._bcc = AddressList(kw.get("bcc", turbomail.config.get("mail.message.bcc", None))) 
     71                self._disposition = AddressList(kw.get("disposition", turbomail.config.get("mail.message.disposition", None))) 
     72                 
     73                self.organization = kw.get("organization", turbomail.config.get("mail.message.organization", None)) 
     74                self.encoding = kw.get("encoding", turbomail.config.get("mail.encoding", 'us-ascii')) 
     75                self.priority = kw.get("priority", turbomail.config.get("mail.message.priority", None)) 
     76                self.subject = kw.get("subject", None) 
     77                self.plain = kw.get("plain", None) 
     78                self.rich = kw.get("rich", None) 
     79                self.attachments = kw.get("attachments", []) 
     80                self.embedded = kw.get("embedded", []) 
     81                self.headers = kw.get("headers", turbomail.config.get("mail.message.headers", [])) 
     82                self.tries = kw.get("tries", turbomail.config.get("mail.tries", 3)) 
     83                 
     84                self._id = kw.get("id", None) 
    9885         
    9986        def __setattr__(self, name, value): 
     
    10289                super(Message, self).__setattr__(name, value) 
    10390                 
    104                 if name not in ('bcc', '_dirty'): self.__dict__['_dirty'] = True 
     91                if name not in ('bcc', '_dirty', '_processed'): self.__dict__['_dirty'] = True 
    10592         
    10693        def __str__(self): 
    10794                return self.mime.as_string() 
    10895         
    109         sender = property(lambda self: self._sender, lambda self, value: self._sender.replace(value), lambda self: self._sender.replace()) 
    110         envelope = property(lambda self: self._envelope, lambda self, value: self._envelope.replace(value), lambda self: self._envelope.replace()) 
    111         reply = property(lambda self: self._reply, lambda self, value: self._reply.replace(value), lambda self: self._reply.replace()) 
    112         to = property(lambda self: self._to, lambda self, value: self._to.replace(value), lambda self: self._to.replace()) 
    113         cc = property(lambda self: self._cc, lambda self, value: self._cc.replace(value), lambda self: self._cc.replace()) 
    114         bcc = property(lambda self: self._bcc, lambda self, value: self._bcc.replace(value), lambda self: self._bcc.replace()) 
    115         disposition = property(lambda self: self._disposition, lambda self, value: self._disposition.replace(value), lambda self: self._disposition.replace()) 
    116          
    117         @property 
     96        def _get_sender(self): 
     97                if self._envelope: 
     98                        return self._envelope.addresses[0] 
     99                return self._senders.addresses[0] 
     100         
     101        sender = AddressList.protected('_senders') 
     102        senders = AddressList.protected('_senders') 
     103        envelope = AddressList.protected('_envelope') 
     104        reply = AddressList.protected('_reply') 
     105        to = AddressList.protected('_to') 
     106        cc = AddressList.protected('_cc') 
     107        bcc = AddressList.protected('_bcc') 
     108        disposition = AddressList.protected('_disposition') 
     109         
    118110        def id(self): 
    119111                if not self._id or (self._processed and self._dirty): 
     
    122114                 
    123115                return self._id 
    124          
    125         @property 
     116        id = property(id) 
     117         
    126118        def recipients(self): 
    127119                return [isinstance(i, tuple) and i[1] or i for i in self.to + self.cc + self.bcc] 
    128          
    129         @property 
     120        recipients = property(recipients) 
     121         
    130122        def mime(self): 
    131123                """Produce the final MIME message.""" 
    132124 
    133                 assert self.sender, "You must specify a sender." 
     125                assert self.senders, "You must specify a sender." 
    134126                assert self.subject, "You must specify a subject." 
    135127                assert self.to or self.cc or self.bcc, "You must specify at least one recipient." 
     
    170162 
    171163                headers = [ 
    172                                 ('Sender', self.envelope and self.envelope[0] or AddressList(self.sender[0])), # AddressList 
    173                                 ('From', self.sender), # AddressList 
     164                                ('Sender', self.sender), # AddressList 
     165                                ('From', self.senders), # AddressList 
    174166                                ('Reply-To', self.reply), # AddressList 
    175167                                ('Subject', self.subject), 
     
    202194                 
    203195                return message 
     196        mime = property(mime) 
    204197         
    205198        def attach(self, file, name=None): 
  • branches/3.0/turbomail/util.py

    r36 r41  
    33"""MIME-encoded electronic mail message classes.""" 
    44 
     5import re, turbomail 
     6from turbomail.exceptions import MailNotEnabledError 
    57from email.Header import Header 
    6 from email.utils import formataddr 
     8from email.utils import parseaddr, formataddr 
    79 
    8 __all__ = ['AddressList'] 
     10__all__ = ['Address', 'AddressList', 'protected', 'send'] 
     11 
     12 
     13class Address(object): 
     14        validator = re.compile(r'^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(\+([0-9a-zA-Z])+)?@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$') 
     15         
     16        def __init__(self, *args): 
     17                assert len(args) < 3 and len(args) > 0, "You must specify an address or a name and address." 
     18                 
     19                if len(args) == 1 and isinstance(args[0], basestring): 
     20                        self.name, self.address = parseaddr(args[0]) 
     21                         
     22                elif not isinstance(args[0], basestring): 
     23                        self.name, self.address = args[0] 
     24                         
     25                else: 
     26                        self.name, self.address = args 
     27                 
     28                if not self.validator.match(self.address): 
     29                        raise ValueError, 'Invalid e-mail address.' 
     30                 
     31                super(Address, self).__init__() 
     32         
     33        def __cmp__(self, other): 
     34                if isinstance(other, (Address, basestring)): 
     35                        return cmp(str(self), str(other)) 
     36                elif isinstance(other, tuple): 
     37                        return cmp((self.name, self.address), other) 
     38                return cmp(self, other) 
     39         
     40        def __repr__(self): 
     41                return "Address(\"%s\")" % str(self) 
     42         
     43        def __str__(self): 
     44                assert self.address, "You must specify an address." 
     45                 
     46                return formataddr((self.name, self.address)).replace("\n", "") 
     47         
    948 
    1049 
    1150class AddressList(list): 
    12         """docstring for AddressList""" 
    13          
    1451        def __init__(self, addresses=[]): 
    1552                super(AddressList, self).__init__() 
    16                 self.replace(addresses) 
     53                 
     54                if isinstance(addresses, (basestring, tuple)): 
     55                        addresses = [addresses] 
     56                 
     57                if addresses is not None: 
     58                        self.extend(addresses) 
    1759         
    18         def replace(self, addresses=[]): 
    19                 del self[:] 
    20                 if not addresses: return 
    21                 self.extend(isinstance(addresses, list) and addresses or [addresses]) 
     60        def __repr__(self): 
     61                if not self: return "AddressList()" 
     62                return "AddressList(\"" + "\", \"".join([str(i) for i in self]) + "\")" 
    2263         
    2364        def __str__(self): 
    24                 addresses = [] 
     65                return ",\n ".join([str(i) for i in self]) 
     66         
     67        def __setitem__(self, k, value): 
     68                if not isinstance(value, Address): 
     69                        value = Address(value) 
    2570                 
    26                 for address in self: 
    27                         if type(address) == type(()): 
    28                                 addresses.append(formataddr(address)) # Header(address[0]) was to encode names.  Still nessicary? 
    29                         else: addresses.append(address) 
     71                super(AddressList, self).__setitem__(k, value) 
     72         
     73        def extend(self, value): 
     74                values = [] 
    3075                 
    31                 return ",\n ".join(addresses) 
     76                for i in value: 
     77                        if not isinstance(i, Address): 
     78                                i = Address(i) 
     79                        values.append(i) 
     80                 
     81                super(AddressList, self).extend(values) 
     82         
     83        def append(self, value): 
     84                self.extend([value]) 
     85         
     86        def addresses(self): 
     87                return AddressList([i.address for i in self]) 
     88         
     89        addresses = property(addresses) 
     90         
     91        def protected(cls, field): 
     92                def fget(self): 
     93                        return getattr(self, field) 
     94 
     95                def fset(self, value): 
     96                        if not isinstance(value, AddressList): 
     97                                value = AddressList(value) 
     98 
     99                        setattr(self, field, AddressList(value)) 
     100 
     101                def fdel(self): 
     102                        setattr(self, field, AddressList()) 
     103 
     104                return property(fget, fset, fdel) 
     105         
     106        protected = classmethod(protected) 
     107 
     108 
     109def send(message): 
     110        if not turbomail.manager: 
     111                raise MailNotEnabledError 
     112         
     113        return turbomail.manager.deliver(message)