]> code.delx.au - offlineimap/blob - offlineimap/repository/IMAP.py
Update FSF address
[offlineimap] / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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, os
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 = fd.readline().strip()
119 fd.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 try:
161 imapobj.select(foldername, readonly = 1)
162 except ValueError:
163 continue
164 retval.append(self.getfoldertype()(self.imapserver,
165 foldername,
166 self.nametrans(foldername),
167 self.accountname, self))
168 finally:
169 self.imapserver.releaseconnection(imapobj)
170
171 retval.sort(lambda x, y: self.foldersort(x.getvisiblename(), y.getvisiblename()))
172 self.folders = retval
173 return retval
174
175 def makefolder(self, foldername):
176 #if self.getreference() != '""':
177 # newname = self.getreference() + self.getsep() + foldername
178 #else:
179 # newname = foldername
180 newname = foldername
181 imapobj = self.imapserver.acquireconnection()
182 try:
183 result = imapobj.create(newname)
184 if result[0] != 'OK':
185 raise RuntimeError, "Repository %s could not create folder %s: %s" % (self.getname(), foldername, str(result))
186 finally:
187 self.imapserver.releaseconnection(imapobj)
188
189 class MappedIMAPRepository(IMAPRepository):
190 def getfoldertype(self):
191 return MappedIMAPFolder