| Home | Trees | Indices | Help |
|
|---|
|
|
1 # This program is free software: you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation, either version 3 of the License, or
4 # (at your option) any later version.
5 #
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU General Public License for more details.
10 #
11 # You should have received a copy of the GNU General Public License
12 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13
14 # mail module (c) Whise (Helder Fraga) 2008 <helder.fraga@hotmail.com>
15
16 import screenlets
17 import dbus
18 import os
19 import sys
20 import stat
21 import gettext
22 import re
23 import urllib
24 gettext.textdomain('screenlets')
25 gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX + '/share/locale')
26 import gobject
27 import socket
28 import threading
29 try:
30 import poplib
31 except ImportError, err:
32 print " !!!Please install python poplib :", err
33 try:
34 import imaplib
35 except ImportError, err:
36 print " !!!Please install python imaplib :", err
37
38 try:
39 import gnomevfs
40 except ImportError, err:
41 print " !!!Please install python gnomevfs :", err
42
43
45 """This gets the unread mail number of kmail"""
46 kmail = commands.getoutput("dcop kmail default checkMail; sleep 5; echo ' ' | tr -d '\n'; dcop kmail KMailIface getFolder /Krealia/Inbox > /dev/null; dcop 'DCOPRef(kmail,FolderIface)' unreadMessages | tr -d '\n'; echo ' '")
47 if kmail.find("ERROR: Couldn't attach to DCOP server!") != -1:
48 return None
49 else:
50 return kmail
51
53 """This output the number of messages of gmail box"""
54 f = os.popen("wget --no-check-certificate -qO - https://%s:%s@mail.google.com/mail/feed/atom" % (urllib.pathname2url(login), urllib.pathname2url(password)))
55 a = f.read()
56 f.close()
57 match = re.search("<fullcount>([0-9]+)</fullcount>", a)
58 if match == None:
59 return None
60 else:
61 return match.group(1)
62
63
64
66 """This output the number of messages of mail box"""
67 try:
68 m = poplib.POP3_SSL(server)
69 except:
70 try:
71 m = poplib.POP3(server)
72 except:
73 return None
74
75 m.user(login)
76 m.pass_(passwd)
77 out = m.stat()
78 m.quit()
79 num = out[0]
80 return num
81
82
84 """Send mail via SMTP"""
85 import smtplib
86 server = smtplib.SMTP(smtp_server)
87 server.sendmail(fromaddr, toaddrs, subject + msg)
88 server.quit()
89
90 #------CLASSES----------
91 #-----------------------
92
93 # error messages
94 MSG_CONNECTION_FAILED = "Error while connecting to server."
95 MSG_FETCH_MAILS_FAILED = "Unable to retrieve mails from server."
96 MSG_AUTH_FAILED = """Error on login - invalid login data given? Some hosts
97 may block connections for a certain interval before allowing reconnects."""
98
99 # the current operational status of the mailcheck
105
106 # the mailcheck status
112
114 """The backend class which performs checking for mail and offers access
115 to the current mail-backend. By subclassing this class you can add multiple
116 mail-backends to the MailCheckScreenlet (e.g. pop3, maildir, imap,
117 gmail, ...)."""
118
119
120 __gsignals__ = {
121 'check_finished' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_INT, gobject.TYPE_INT,))
122 }
123
125 gobject.GObject.__init__(self)
126 # properties
127 self.name = name # name of backend
128 self.screenlet = screenlet # assigned MailCheckScreenlet
129 self.refreshing = False # not refreshing yet
130 self.unseen_count = 0 # number of unread messages on the server
131 self.status = MailCheckStatus.IDLE # status of the mailcheck backend
132 self.mailbox_status = MailboxStatus.UNKNOWN # status of the mailbox
133 self.error = '' # human-readable error message
134 self.options = [] # ???additonal ptions for backend
135 self.thread = None
136 self.mailcount = 0 #
137
139 """This handler should be overridden by subclasses to add new types
140 of checking mails in a backend. This handler has to set self.mailcount
141 to the number of mails found in the backend. The return value is
142 ignored, set self.error and self.status to return results."""
143
145 """Stop receiving mails from the backend. This should be overridden
146 by subclasses."""
147 self.thread = None
148
150 """Start receiving mails from the backend. Runs self.__execute as
151 a separate thread."""
152 self.thread = threading.Thread(target=self.__execute).start()
153
155 """Execute the thread and call the check-mail function."""
156 # set status to REFRESH and call check_mail-handler to fetch mails
157 self.refreshing = True
158 self.check_mail()
159 self.emit('check_finished', self.status, self.mailbox_status)
160 # not refreshing anymore
161 self.refreshing = False
162
163
164 # IMAPBackend was contributed by Robert Gartler - thanks :)
166 """A backend for retrieving the mailcount from an IMAP server."""
167
172
174 # set default timeout for all socket connections to 30 secs
175 socket.setdefaulttimeout(30000)
176 print "IMAPBackend: Connecting to IMAP-server ... please wait."
177 self.status = MailCheckStatus.REFRESH
178 try:
179 self.server = imaplib.IMAP4_SSL(self.screenlet.imap_host)
180 except:
181 try:
182 self.server = imaplib.IMAP4(self.screenlet.imap_host)
183 except:
184 self.error = MSG_CONNECTION_FAILED
185 self.status = MailCheckStatus.ERROR
186 return False
187 user, passwd = self.screenlet.imap_account
188 try:
189 self.server.login(user, passwd)
190 except:
191 self.error = MSG_AUTH_FAILED
192 self.status = MailCheckStatus.ERROR
193 self.server.logout()
194 return False
195
196 self.server.select()
197 typ, data = self.server.search(None, 'UNSEEN')
198 if typ == 'OK':
199 self.unseen_count = len(data[0].split())
200 if self.unseen_count > 0:
201 typ, data = self.server.search(None, 'NEW')
202 if typ == 'OK':
203 if len(data[0].split()) > 0:
204 self.mailbox_status = MailboxStatus.NEW_MAIL
205 print "NEW_MAIL"
206 else:
207 self.mailbox_status = MailboxStatus.UNREAD_MAIL
208 print "UNREAD_MAIL"
209 else:
210 print "IMAP error (checking new count): " + typ
211 else:
212 self.mailbox_status = MailboxStatus.ALL_READ
213 self.status = MailCheckStatus.IDLE
214 else:
215 print "IMAP error (checking unseen count): " + typ
216 self.error = MSG_FETCH_MAILS_FAILED
217 self.status = MailCheckStatus.ERROR
218 self.mailbox_status = MailboxStatus.UNKNOWN
219 self.server.close()
220 self.server.logout()
221 return False
222
224 if self.server:
225 self.server.close()
226 self.server.logout()
227 self.thread.join()
228 self.thread = None
229
231 """
232 Class that retrieve the information from an Imap, Pop or mbox account
233
234 All the email-related operation lies in this few lines
235 """
236 import imaplib
237 import poplib
238 import mailbox
239 from sys import exc_info
240 from os import stat, utime, path, listdir
241
242
244 self.config=config
245 self.last_size=-1
246 self.size=-1
247 self.mbox_size = 0
248 self.mbox_mtime = 0
249
251 self.last_size=self.size
252
253 try:
254 # IMAP4
255 #
256 if self.config['method']=='imap4':
257 s = self.imaplib.__dict__['IMAP4'+['','_SSL']
258 [self.config['ssl']]]\
259 (self.config['host'])
260 s.login(self.config['user_name'],self.config['user_password'])
261 s.select()
262 size = len(s.search(None, 'UNSEEN')[1][0].split())
263 s.logout()
264
265 # POP3
266 #
267 elif self.config['method']=='pop3':
268 s = self.poplib.__dict__['POP3'+['','_SSL']
269 [self.config['ssl']]]\
270 (self.config['host'])
271 s.user(self.config['user_name'])
272 s.pass_(self.config['user_password'])
273 size = len(s.list()[1])
274
275 # Maildir
276 #
277 # This was reported to work with qmail, but it is untested with
278 # other mail servers -- for maximum portability, one could
279 # still rewrite next four lines using the mailbox Python module
280 # (in core libraries).
281 #
282 elif self.config['method'] == 'maildir':
283 mdir_path = getenv('MAILDIR', self.config['mailspool'])
284 mdir_new = self.path.join(self.path.expanduser(mdir_path), 'new')
285
286 size = len([f for f in self.listdir(mdir_new) if f[0] != '.'])
287
288 # Unix mbox
289 #
290 elif self.config['method'] == 'mbox':
291 mbox_path = getenv('MAIL',self.config['mailspool'])
292 # Get mbox inode properties
293 #
294 s = self.stat(mbox_path)
295 if (s.st_size == self.mbox_size and
296 s.st_mtime == self.mbox_mtime):
297 size = self.last_size # mbox has not changed on disk
298 else:
299 size = 0 # mbox has changed
300 for m in self.mailbox.PortableUnixMailbox(file(mbox_path)):
301 if m.get('status','N').find('N') != -1:
302 size += 1
303
304 # Trick the system into thinking the mbox inode was not
305 # accessed since last modification. From 'manual.txt'
306 # of mutt 1.5.8:
307 #
308 # [ ... new mail is detected by comparing the last
309 # modification time to the last access time.
310 # Utilities like biff or frm or any other program
311 # which accesses the mailbox might cause Mutt to
312 # never detect new mail for that mailbox if they
313 # do not properly reset the access time.
314 # Backup tools are another common reason for updated
315 # access times. ]
316 #
317 self.utime(mbox_path, (s.st_atime, s.st_mtime))
318
319 # Remember size and time
320 #
321 self.mbox_size = s.st_size
322 self.mbox_mtime = s.st_mtime
323
324 # Uknown access method
325 #
326 else:
327 raise RuntimeError('unknown access method `%s\'' %
328 self.config['method'])
329 except:
330 # Exception handling: output a significant printout
331 #
332 size = -1
333 print '='*80
334 print traceback.print_exception(*self.exc_info())
335 print '='*80
336 print self.config
337 print '='*80
338
339 self.size = size
340 return size
341
342
344 """A backend for retrieving the mailcount from a POP3 server."""
345
350 # init additional attributes for this backend-type
351 # TODO: add POP3-specific options to the backend instead of having them
352 # defined in the screenlet by default (ideally they should be only shown
353 # when the POP3-backend is active
354
356 # set default timeout for all socket connections to 30 secs
357 socket.setdefaulttimeout(30000)
358 print "POP3Backend: Connecting to POP3-server ... please wait."
359 #self.screenlet.redraw_canvas()
360 try:
361 self.server = poplib.POP3_SSL(self.screenlet.pop3_server)
362 except:
363 try:
364 self.server = poplib.POP3(self.screenlet.pop3_server)
365 except:
366 self.error = MSG_CONNECTION_FAILED
367 self.status = MailCheckStatus.ERROR
368 return False
369 # authenticate
370 user, pw = self.screenlet.pop3_account
371 #print "ACCOUNT IS %s/%s!!" % (o[0], o[1])
372 try:
373 self.server.user(user)
374 self.server.pass_(pw)
375 except:
376 self.error = MSG_AUTH_FAILED
377 self.status = MailCheckStatus.ERROR
378 self.server.quit()
379 return False
380 # get list with mails (response, list-of-mails)
381 resp = self.server.list()
382 if resp[0].startswith('+OK'):
383 messages = resp[1]
384 #print messages
385 msgnum = len(messages)
386 if msgnum > self.mailcount:
387 diff = msgnum - self.mailcount
388 self.mailcount = msgnum
389 self.mailbox_status = MailboxStatus.NEW_MAIL
390 self.status = MailCheckStatus.GOT_MAIL
391 print "GOT_MAIL"
392 elif msgnum <= self.mailcount:
393 print "set status to IDLE (POP3Backend.check_mail)"
394 self.mailbox_status = MailboxStatus.ALL_READ
395 self.mailcount = msgnum
396 self.status = MailCheckStatus.IDLE
397 print "IDLE"
398 else:
399 self.error = MSG_FETCH_MAILS_FAILED
400 self.status = MailCheckStatus.ERROR
401 #server.quit()
402 #return False
403 # close connection
404 self.server.quit()
405 return False
406
412
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Wed Jan 4 16:58:25 2012 | http://epydoc.sourceforge.net |