]>
code.delx.au - offlineimap/blob - offlineimap/repository/IMAP.py
1 # IMAP repository support
2 # Copyright (C) 2002 John Goerzen
3 # <jgoerzen@complete.org>
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.
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.
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
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
, netrc
, errno
24 from threading
import *
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
)
32 self
.nametrans
= lambda foldername
: foldername
33 self
.folderfilter
= lambda foldername
: 1
34 self
.folderincludes
= []
36 localeval
= self
.localeval
37 if self
.config
.has_option(self
.getsection(), 'nametrans'):
38 self
.nametrans
= localeval
.eval(self
.getconf('nametrans'),
40 if self
.config
.has_option(self
.getsection(), 'folderfilter'):
41 self
.folderfilter
= localeval
.eval(self
.getconf('folderfilter'),
43 if self
.config
.has_option(self
.getsection(), 'folderincludes'):
44 self
.folderincludes
= localeval
.eval(self
.getconf('folderincludes'),
46 if self
.config
.has_option(self
.getsection(), 'foldersort'):
47 self
.foldersort
= localeval
.eval(self
.getconf('foldersort'),
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)
60 def stopkeepalive(self
, abrupt
= 0):
61 if not hasattr(self
, 'kaevent'):
62 # Keepalive is not active.
71 def holdordropconnections(self
):
72 if not self
.getholdconnectionopen():
73 self
.dropconnections()
75 def dropconnections(self
):
76 self
.imapserver
.close()
78 def getholdconnectionopen(self
):
79 return self
.getconfboolean("holdconnectionopen", 0)
81 def getkeepalive(self
):
82 return self
.getconfint("keepalive", 0)
85 return self
.imapserver
.delim
89 localeval
= self
.localeval
91 if self
.config
.has_option(self
.getsection(), 'remotehosteval'):
92 host
= self
.getconf('remotehosteval')
94 return localeval
.eval(host
)
96 host
= self
.getconf('remotehost')
102 localeval
= self
.localeval
104 if self
.config
.has_option(self
.getsection(), 'remoteusereval'):
105 user
= self
.getconf('remoteusereval')
107 return localeval
.eval(user
)
109 user
= self
.getconf('remoteuser')
114 netrcentry
= netrc
.netrc().authentificator(self
.gethost())
115 except IOError, inst
:
116 if inst
.errno
!= errno
.ENOENT
:
123 return self
.getconfint('remoteport', None)
126 return self
.getconfboolean('ssl', 0)
128 def getpreauthtunnel(self
):
129 return self
.getconf('preauthtunnel', None)
131 def getreference(self
):
132 return self
.getconf('reference', '""')
134 def getmaxconnections(self
):
135 return self
.getconfint('maxconnections', 1)
137 def getexpunge(self
):
138 return self
.getconfboolean('expunge', 1)
140 def getpassword(self
):
142 localeval
= self
.localeval
144 if self
.config
.has_option(self
.getsection(), 'remotepasseval'):
145 passwd
= self
.getconf('remotepasseval')
147 return localeval
.eval(passwd
)
149 password
= self
.getconf('remotepass', None)
152 passfile
= self
.getconf('remotepassfile', None)
154 fd
= open(os
.path
.expanduser(passfile
))
155 password
= fd
.readline().strip()
160 netrcentry
= netrc
.netrc().authenticators(self
.gethost())
161 except IOError, inst
:
162 if inst
.errno
!= errno
.ENOENT
:
166 user
= self
.getconf('remoteuser')
167 if user
== None or user
== netrcentry
[0]:
171 def getfolder(self
, foldername
):
172 return self
.getfoldertype()(self
.imapserver
, foldername
,
173 self
.nametrans(foldername
),
174 self
.accountname
, self
)
176 def getfoldertype(self
):
177 return folder
.IMAP
.IMAPFolder
180 imapobj
= self
.imapserver
.acquireconnection()
181 self
.imapserver
.releaseconnection(imapobj
)
183 def forgetfolders(self
):
186 def getfolders(self
):
187 if self
.folders
!= None:
190 imapobj
= self
.imapserver
.acquireconnection()
192 listresult
= imapobj
.list(directory
= self
.imapserver
.reference
)[1]
194 self
.imapserver
.releaseconnection(imapobj
)
195 for string
in listresult
:
196 if string
== None or \
197 (type(string
) == types
.StringType
and string
== ''):
198 # Bug in imaplib: empty strings in results from
201 flags
, delim
, name
= imaputil
.imapsplit(string
)
202 flaglist
= [x
.lower() for x
in imaputil
.flagsplit(flags
)]
203 if '\\noselect' in flaglist
:
205 foldername
= imaputil
.dequote(name
)
206 if not self
.folderfilter(foldername
):
208 retval
.append(self
.getfoldertype()(self
.imapserver
, foldername
,
209 self
.nametrans(foldername
),
210 self
.accountname
, self
))
211 if len(self
.folderincludes
):
212 imapobj
= self
.imapserver
.acquireconnection()
214 for foldername
in self
.folderincludes
:
216 imapobj
.select(foldername
, readonly
= 1)
219 retval
.append(self
.getfoldertype()(self
.imapserver
,
221 self
.nametrans(foldername
),
222 self
.accountname
, self
))
224 self
.imapserver
.releaseconnection(imapobj
)
226 retval
.sort(lambda x
, y
: self
.foldersort(x
.getvisiblename(), y
.getvisiblename()))
227 self
.folders
= retval
230 def makefolder(self
, foldername
):
231 #if self.getreference() != '""':
232 # newname = self.getreference() + self.getsep() + foldername
234 # newname = foldername
236 imapobj
= self
.imapserver
.acquireconnection()
238 result
= imapobj
.create(newname
)
239 if result
[0] != 'OK':
240 raise RuntimeError, "Repository %s could not create folder %s: %s" % (self
.getname(), foldername
, str(result
))
242 self
.imapserver
.releaseconnection(imapobj
)
244 class MappedIMAPRepository(IMAPRepository
):
245 def getfoldertype(self
):
246 return MappedIMAPFolder