]> code.delx.au - offlineimap/blob - offlineimap/head/offlineimap/repository/IMAP.py
/offlineimap/head: changeset 445
[offlineimap] / offlineimap / head / offlineimap / repository / IMAP.py
1 # IMAP repository support
2 # Copyright (C) 2002 John Goerzen
3 # <jgoerzen@complete.org>
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 2 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 Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 from Base import BaseRepository
20 from offlineimap import folder, imaputil, imapserver
21 from offlineimap.folder.UIDMaps import MappedIMAPFolder
22 from offlineimap.threadutil import ExitNotifyThread
23 import re, types
24 from threading import *
25
26 class IMAPRepository(BaseRepository):
27 def __init__(self, reposname, account):
28 """Initialize an IMAPRepository object."""
29 BaseRepository.__init__(self, reposname, account)
30 self.imapserver = imapserver.ConfigedIMAPServer(self)
31 self.folders = None
32 self.nametrans = lambda foldername: foldername
33 self.folderfilter = lambda foldername: 1
34 self.folderincludes = []
35 self.foldersort = cmp
36 localeval = self.localeval
37 if self.config.has_option(self.getsection(), 'nametrans'):
38 self.nametrans = localeval.eval(self.getconf('nametrans'),
39 {'re': re})
40 if self.config.has_option(self.getsection(), 'folderfilter'):
41 self.folderfilter = localeval.eval(self.getconf('folderfilter'),
42 {'re': re})
43 if self.config.has_option(self.getsection(), 'folderincludes'):
44 self.folderincludes = localeval.eval(self.getconf('folderincludes'),
45 {'re': re})
46 if self.config.has_option(self.getsection(), 'foldersort'):
47 self.foldersort = localeval.eval(self.getconf('foldersort'),
48 {'re': re})
49
50 def startkeepalive(self):
51 keepalivetime = self.getkeepalive()
52 if not keepalivetime: return
53 self.kaevent = Event()
54 self.kathread = ExitNotifyThread(target = self.imapserver.keepalive,
55 name = "Keep alive " + self.getname(),
56 args = (keepalivetime, self.kaevent))
57 self.kathread.setDaemon(1)
58 self.kathread.start()
59
60 def stopkeepalive(self, abrupt = 0):
61 if not hasattr(self, 'kaevent'):
62 # Keepalive is not active.
63 return
64
65 self.kaevent.set()
66 if not abrupt:
67 self.kathread.join()
68 del self.kathread
69 del self.kaevent
70
71 def holdordropconnections(self):
72 if not self.getholdconnectionopen():
73 self.dropconnections()
74
75 def dropconnections(self):
76 self.imapserver.close()
77
78 def getholdconnectionopen(self):
79 return self.getconfboolean("holdconnectionopen", 0)
80
81 def getkeepalive(self):
82 return self.getconfint("keepalive", 0)
83
84 def getsep(self):
85 return self.imapserver.delim
86
87 def gethost(self):
88 return self.getconf('remotehost')
89
90 def getuser(self):
91 return self.getconf('remoteuser')
92
93 def getport(self):
94 return self.getconfint('remoteport', None)
95
96 def getssl(self):
97 return self.getconfboolean('ssl', 0)
98
99 def getpreauthtunnel(self):
100 return self.getconf('preauthtunnel', None)
101
102 def getreference(self):
103 return self.getconf('reference', '""')
104
105 def getmaxconnections(self):
106 return self.getconfint('maxconnections', 1)
107
108 def getexpunge(self):
109 return self.getconfboolean('expunge', 1)
110
111 def getpassword(self):
112 password = self.getconf('remotepass', None)
113 if password != None:
114 return password
115 passfile = self.getconf('remotepassfile', None)
116 if passfile != None:
117 fd = open(os.path.expanduser(passfile))
118 password = passfile.readline().strip()
119 passfile.close()
120 return password
121 return None
122
123 def getfolder(self, foldername):
124 return self.getfoldertype()(self.imapserver, foldername,
125 self.nametrans(foldername),
126 self.accountname, self)
127
128 def getfoldertype(self):
129 return folder.IMAP.IMAPFolder
130
131 def getfolders(self):
132 if self.folders != None:
133 return self.folders
134 retval = []
135 imapobj = self.imapserver.acquireconnection()
136 try:
137 listresult = imapobj.list(directory = self.imapserver.reference)[1]
138 finally:
139 self.imapserver.releaseconnection(imapobj)
140 for string in listresult:
141 if string == None or \
142 (type(string) == types.StringType and string == ''):
143 # Bug in imaplib: empty strings in results from
144 # literals.
145 continue
146 flags, delim, name = imaputil.imapsplit(string)
147 flaglist = [x.lower() for x in imaputil.flagsplit(flags)]
148 if '\\noselect' in flaglist:
149 continue
150 foldername = imaputil.dequote(name)
151 if not self.folderfilter(foldername):
152 continue
153 retval.append(self.getfoldertype()(self.imapserver, foldername,
154 self.nametrans(foldername),
155 self.accountname, self))
156 if len(self.folderincludes):
157 imapobj = self.imapserver.acquireconnection()
158 try:
159 for foldername in self.folderincludes:
160 if imapobj.select(foldername, readonly = 1)[0] == 'OK':
161 retval.append(self.getfoldertype()(self.imapserver,
162 foldername,
163 self.nametrans(foldername),
164 self.accountname, self))
165 finally:
166 self.imapserver.releaseconnection(imapobj)
167
168 retval.sort(lambda x, y: self.foldersort(x.getvisiblename(), y.getvisiblename()))
169 self.folders = retval
170 return retval
171
172 def makefolder(self, foldername):
173 #if self.getreference() != '""':
174 # newname = self.getreference() + self.getsep() + foldername
175 #else:
176 # newname = foldername
177 newname = foldername
178 imapobj = self.imapserver.acquireconnection()
179 try:
180 result = imapobj.create(newname)
181 if result[0] != 'OK':
182 raise RuntimeError, "Repository %s could not create folder %s: %s" % (self.getname(), foldername, str(result))
183 finally:
184 self.imapserver.releaseconnection(imapobj)
185
186 class MappedIMAPRepository(IMAPRepository):
187 def getfoldertype(self):
188 return MappedIMAPFolder