Package ProcImap :: Package Utils :: Module MailboxFactory
[hide private]
[frames] | no frames]

Source Code for Module ProcImap.Utils.MailboxFactory

  1  ############################################################################ 
  2  #    Copyright (C) 2008 by Michael Goerz                                   # 
  3  #    http://www.physik.fu-berlin.de/~goerz                                 # 
  4  #                                                                          # 
  5  #    This program is free software; you can redistribute it and#or modify  # 
  6  #    it under the terms of the GNU General Public License as published by  # 
  7  #    the Free Software Foundation; either version 3 of the License, or     # 
  8  #    (at your option) any later version.                                   # 
  9  #                                                                          # 
 10  #    This program is distributed in the hope that it will be useful,       # 
 11  #    but WITHOUT ANY WARRANTY; without even the implied warranty of        # 
 12  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         # 
 13  #    GNU General Public License for more details.                          # 
 14  #                                                                          # 
 15  #    You should have received a copy of the GNU General Public License     # 
 16  #    along with this program; if not, write to the                         # 
 17  #    Free Software Foundation, Inc.,                                       # 
 18  #    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             # 
 19  ############################################################################ 
 20  """ 
 21      This module contains the MailboxFactory class, together with some 
 22      Exceptions that are thrown by MailboxFactory, and the pathgenerator 
 23      functions used for the default mailbox types (see documentation 
 24      of MailboxFactory class) 
 25   
 26   
 27  """ 
 28   
 29  import mailbox 
 30  from ConfigParser import ConfigParser 
 31   
 32  from ProcImap.ImapServer import ImapServer 
 33  from ProcImap.ImapMailbox import ImapMailbox 
 34   
35 -class UnknownMailboxTypeError(Exception):
36 """ Raised when there is a mailbox type in the config file that is 37 unknown to MailboxFactory. You may have to add it first with the 38 'set_type' method. 39 """ 40 pass
41
42 -class FactoryIsNotMailboxTypeError(Exception):
43 """ Raised when you supplied a factory that is not a subclass of 44 mailbox.Mailbox. 45 """ 46 pass
47
48 -class PathgeneratorNotCallableError(Exception):
49 """ Raised when you supplied a pathgenerator that is not callable """ 50 pass
51
52 -class MailboxOptionsNotCompleteError(Exception):
53 """ Raised if there are options missing in the config file that are 54 needed in order to produce a mailbox object 55 """ 56 pass
57
58 -class MailboxFactory:
59 """ MailboxFactory is a factory class for Mailbox objects. You can define 60 mailboxes of different types in an INI-style config file (the file 61 has to parsable by ConfigParser.ConfigParser; the exceptions defined 62 in ConfigParser may be thrown if the config file is not well-formed.) 63 Each section in the config file describes one mailbox. 64 65 An example of a valid config file 'mailboxes.cfg' is the following: 66 67 [Standard] 68 type = IMAP 69 mailbox = INBOX 70 server = mail.physik.fu-berlin.de 71 username = goerz 72 password = secret 73 ssl = True 74 port = 933 75 76 [Sent] 77 type = IMAP 78 mailbox = Sent 79 server = mail.physik.fu-berlin.de 80 username = goerz 81 password = secret 82 83 [Backup] 84 type = mbox 85 path = /home/goerz/Mail/backup.mbox 86 87 The type of the mailbox is described by the 'type' parameters. The 88 types known by default are 'imap', 'mbox', 'maildir', 'MH', 'Babyl', 89 and 'MMDF', all of which have corresponding subclasses of 90 mailbox.Mailbox (all except ImapMailbox are defined in the standard 91 library). The type specification is not case sensitive. 92 93 The remaining parameters in a specific section depend on the type. The 94 Mailbox classes from the standard library need only a path; IMAP needs 95 type, mailbox, server, username, and password. The ssl and port 96 parameters are optional. ssl is enabled by default; the port, if 97 unspecified, is the standard port (933 for ssl, 433 otherwise). 98 99 MailboxFactory has capabilities to extend the set of known types by 100 using the set_type method. 101 102 The MailboxFactory partly supports a read-only dictionary interface. 103 """
104 - def __init__(self, configfilename):
105 """ Initialize MailboxFactory files. 106 The mailbox objects that can be generated must be described in 107 configfilename. 108 """ 109 self._types = {} 110 self.set_type('mbox', mailbox.mbox, standard_pathgenerator) 111 self.set_type('maildir', mailbox.Maildir, standard_pathgenerator) 112 self.set_type('mh', mailbox.MH, standard_pathgenerator) 113 self.set_type('babyl', mailbox.Babyl, standard_pathgenerator) 114 self.set_type('mmdf', mailbox.MMDF, standard_pathgenerator) 115 self.set_type('imap', ImapMailbox, imap_pathgenerator) 116 self._configparser = ConfigParser() 117 self._configparser.read(configfilename)
118
119 - def get(self, name):
120 """ Create the Mailbox object that is described in section 'name' 121 in the config file. For example, 122 >>> mailboxes = MailboxFactory("mailboxes.cfg") 123 >>> mb = mailboxes.get('Standard') 124 mb would now be an object of type ImapMailbox if mailboxes.cfg 125 contained the data as the example in the class docstring. 126 """ 127 mailboxtype = self._configparser.get(name, 'type').lower() 128 if not mailboxtype in self._types.keys(): 129 raise UnknownMailboxTypeError, "Unknown type: %s" % mailboxtype 130 factory, pathgenerator = self._types[mailboxtype] 131 path = pathgenerator(dict(self._configparser.items(name))) 132 return(factory(path))
133
134 - def __getitem__(self, name):
135 """ Shorthand for the get method. 136 For example, 137 >>> mailboxes = MailboxFactory("mailboxes.cfg") 138 >>> mb = mailboxes['Standard'] 139 """ 140 return self.get(name)
141 142
143 - def get_server(self, name):
144 """ Return an ImapServer instance from the server data that is 145 described in section 'name'. The section must have the form of 146 an imap mailbox (as described above). A TypeError will be raised 147 if the section is not of type IMAP. The 'mailbox' key is ignored. 148 149 For example, you could create an ImapServer like this: 150 151 >>> mailboxes = MailboxFactory("mailboxes.cfg") 152 >>> server = mailboxes.get_server('StandardServer') 153 """ 154 mailboxtype = self._configparser.get(name, 'type').lower() 155 if mailboxtype != 'imap': 156 raise TypeError, "You can only create a server from an IMAP mailbox" 157 factory, pathgenerator = self._types[mailboxtype] 158 path = pathgenerator(dict(self._configparser.items(name))) 159 return(path[0])
160
161 - def __contains__(self, name):
162 """ Return True if there is a mailbox with the given name, 163 False otherwise """ 164 return (name in self._configparser.sections())
165 166
167 - def list(self):
168 """ List all mailboxes defined in the config file """ 169 return self._configparser.sections()
170
171 - def data(self, name):
172 """ List all the data associated with the mailbox name """ 173 return self._configparser.items(name)
174
175 - def set_type(self, typename, factory, pathgenerator):
176 """ Make a new typename of Mailbox known. This allows you to 177 handle new types of Mailbox objects beyond IMAP and the 178 mailboxes of the standard library. 179 180 factory is the class that generates the Mailbox object and must 181 be a subclass of mailbox.Mailbox 182 183 pathgenerator is a callable that receives a dict of options set 184 in a section of the config file, and returns the 'path' that 185 is passed as the first argument to the factory. For the standard 186 mailboxes of the standard library, the 'path' is just a string, 187 the path of the mailbox in the filesystem. For IMAP, the path 188 is a tuple (server, name). For new types, this may be anything. 189 190 For example the constructor of this class makes the 'mbox' 191 type known as: 192 self.set_type('mbox', mailbox.mbox, standard_pathgenerator) 193 194 In combination, 195 factory(pathgenerator(dict_of_options_in_configfile_section)) 196 should create a Mailbox object of the appropriate type. 197 """ 198 if not issubclass(factory, mailbox.Mailbox): 199 raise FactoryIsNotMailboxTypeError 200 if not callable(pathgenerator): 201 raise PathgeneratorNotCallableError 202 self._types[str(typename).lower()] = (factory, pathgenerator)
203 204
205 -def imap_pathgenerator(optionsdict):
206 """ Converts options into (server, name) tuple """ 207 try: 208 name = optionsdict['mailbox'] 209 serveraddress = optionsdict['server'] 210 username = optionsdict['username'] 211 password = optionsdict['password'] 212 ssl = True 213 if optionsdict.has_key('ssl'): 214 if optionsdict['ssl'].lower() in ['0', 'false', 'no']: 215 ssl = False 216 port = None 217 if optionsdict.has_key('port'): 218 port = int(optionsdict['port']) 219 except KeyError: 220 raise MailboxOptionsNotCompleteError, \ 221 "IMAP Mailbox object needs the following parameters\n " \ 222 + "'mailbox', 'server', 'username', 'password'.\n" \ 223 + "The 'ssl' and 'port' parameters are optional." 224 server = ImapServer(serveraddress, username, password, ssl, port) 225 return(tuple((server, name)))
226 227
228 -def standard_pathgenerator(optionsdict):
229 """ Extract 'path' from options """ 230 try: 231 return optionsdict['path'] 232 except KeyError: 233 raise MailboxOptionsNotCompleteError, \ 234 "Standard Mailbox object needs 'path' parameter"
235