]>
code.delx.au - offlineimap/blob - head/offlineimap/folder/Maildir.py
1 # Maildir folder 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 from Base
import BaseFolder
20 from offlineimap
import imaputil
21 import os
.path
, os
, re
, time
, socket
23 class MaildirFolder(BaseFolder
):
24 def __init__(self
, root
, name
):
28 self
.uidfilename
= os
.path
.join(self
.getfullname(), "offlineimap.uidvalidity")
29 self
.messagelist
= None
31 def getfullname(self
):
32 return os
.path
.join(self
.getroot(), self
.getname())
34 def getuidvalidity(self
):
35 if not os
.path
.exists(self
.uidfilename
):
37 file = open(self
.uidfilename
, "rt")
38 retval
= long(file.readline().strip())
42 def saveuidvalidity(self
, newval
):
43 file = open(self
.uidfilename
, "wt")
44 file.write("%d\n" % newval
)
47 def isuidvalidityok(self
, remotefolder
):
48 myval
= self
.getuidvalidity()
50 return myval
== remotefolder
.getuidvalidity()
52 self
.saveuidvalidity(remotefolder
.getuidvalidity())
55 def cachemessagelist(self
):
56 """Cache the message list. Maildir flags are:
62 and must occur in ASCII order."""
65 nouidcounter
= -1 # Messages without UIDs get
66 # negative UID numbers.
67 for dirannex
in ['new', 'cur']:
68 fulldirname
= os
.path
.join(self
.getfullname(), dirannex
)
69 files
.extend([os
.path
.join(fulldirname
, filename
) for
70 filename
in os
.listdir(fulldirname
)])
72 messagename
= os
.path
.basename(file)
73 uidmatch
= re
.search(',U=(\d+)', messagename
)
79 uid
= long(uidmatch
.group(1))
80 flagmatch
= re
.search(':.*2,([A-Z]+)', messagename
)
83 flags
= [x
for x
in flagmatch
.group(1)]
85 self
.messagelist
[uid
] = {'uid': uid
,
89 def getmessagelist(self
):
90 return self
.messagelist
92 def getmessage(self
, uid
):
93 filename
= self
.getmessagelist()[uid
]['filename']
94 file = open(filename
, 'rt')
99 def savemessage(self
, uid
, content
, flags
):
101 # We cannot assign a new uid.
103 if uid
in self
.getmessagelist():
104 # We already have it.
105 self
.savemessageflags(uid
, flags
)
107 newdir
= os
.path
.join(self
.getfullname(), 'new')
108 tmpdir
= os
.path
.join(self
.getfullname(), 'tmp')
113 raise IOError, "Couldn't write to file %s" % messagename
114 messagename
= '%d.%d.%s,U=%d' % \
117 socket
.gethostname(),
119 if os
.path
.exists(os
.path
.join(tmpdir
, messagename
)):
124 file = open(os
.path
.join(tmpdir
, messagename
), "wt")
127 os
.link(os
.path
.join(tmpdir
, messagename
),
128 os
.path
.join(newdir
, messagename
))
129 os
.unlink(os
.path
.join(tmpdir
, messagename
))
130 self
.messagelist
[uid
] = {'uid': uid
, 'flags': [],
131 'filename': os
.path
.join(newdir
, messagename
)}
132 self
.savemessageflags(uid
, flags
)
135 def getmessageflags(self
, uid
):
136 return self
.getmessagelist()[uid
]['flags']
138 def savemessageflags(self
, uid
, flags
):
139 oldfilename
= self
.getmessagelist()[uid
]['filename']
140 newpath
, newname
= os
.path
.split(oldfilename
)
142 infomatch
= re
.search('(:.*)$', newname
)
143 if infomatch
: # If the info string is present..
144 infostr
= infomatch
.group(1)
145 newname
= newname
.split(':')[0] # Strip off the info string.
146 infostr
= re
.sub('2,[A-Z]*', '', infostr
)
148 infostr
+= '2,' + ''.join(flags
)
151 newfilename
= os
.path
.join(newpath
, newname
)
152 if (newfilename
!= oldfilename
):
153 os
.rename(oldfilename
, newfilename
)
154 self
.getmessagelist()[uid
]['flags'] = flags
155 self
.getmessagelist()[uid
]['filename'] = newfilename
157 def getmessageflags(self
, uid
):
158 return self
.getmessagelist()[uid
]['flags']
160 def deletemessage(self
, uid
):
161 if not uid
in self
.messagelist
:
163 filename
= self
.getmessagelist()[uid
]['filename']
165 del(self
.messagelist
[uid
])