Skip to content

Commit 0846f05

Browse files
author
Richard Jones
committed
added IMAP support to mail gateway (rfe [SF#934000])
1 parent 93a6c74 commit 0846f05

File tree

3 files changed

+103
-3
lines changed

3 files changed

+103
-3
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Feature:
1111
- roundup-server now uses the ForkingMixin
1212
- added another sample detector "creator_resolution"
1313
- added search_checkboxes as an option for the search form
14+
- added IMAP support to mail gateway (sf rfe 934000)
1415

1516
Fixed:
1617
- mysql and postgresql schema mutation now handle added Multilinks
@@ -142,6 +143,7 @@ Fixed:
142143
- paging in classhelp popup was broken
143144
- socket timeout error logging can fail
144145
- hyperlink designators in message display (sf bug 931828)
146+
- don't match retired items in RDBMS stringFind
145147

146148

147149
2004-04-01 0.6.8

roundup/mailgw.py

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18+
# vim: ts=4 sw=4 expandtab
19+
#
1820

1921
"""An e-mail gateway for Roundup.
2022
@@ -72,7 +74,7 @@ class node. Any parts of other types are each stored in separate files
7274
an exception, the original message is bounced back to the sender with the
7375
explanatory message given in the exception.
7476
75-
$Id: mailgw.py,v 1.146 2004-03-26 00:44:11 richard Exp $
77+
$Id: mailgw.py,v 1.147 2004-04-13 04:11:06 richard Exp $
7678
"""
7779
__docformat__ = 'restructuredtext'
7880

@@ -366,6 +368,79 @@ def do_mailbox(self, filename):
366368
fcntl.flock(f.fileno(), FCNTL.LOCK_UN)
367369
return 0
368370

371+
def do_imap(self, server, user='', password='', mailbox='', ssl=False):
372+
''' Do an IMAP connection
373+
'''
374+
import getpass, imaplib, socket
375+
try:
376+
if not user:
377+
user = raw_input('User: ')
378+
if not password:
379+
password = getpass.getpass()
380+
except (KeyboardInterrupt, EOFError):
381+
# Ctrl C or D maybe also Ctrl Z under Windows.
382+
print "\nAborted by user."
383+
return 1
384+
# open a connection to the server and retrieve all messages
385+
try:
386+
if ssl:
387+
print 'Trying server "%s" with ssl' % server
388+
server = imaplib.IMAP4_SSL(server)
389+
else:
390+
print 'Trying server %s without ssl' % server
391+
server = imaplib.IMAP4(server)
392+
except imaplib.IMAP4.error, e:
393+
print 'IMAP server error:', e
394+
return 1
395+
except socket.error, e:
396+
print 'SOCKET error:', e
397+
return 1
398+
except socket.sslerror, e:
399+
print 'SOCKET ssl error:', e
400+
return 1
401+
402+
try:
403+
server.login(user, password)
404+
except imaplib.IMAP4.error, e:
405+
print 'Login failure:', e
406+
return 1
407+
408+
try:
409+
if not mailbox:
410+
#print 'Using INBOX'
411+
(typ, data) = server.select()
412+
else:
413+
#print 'Using mailbox' , mailbox
414+
(typ, data) = server.select(mailbox=mailbox)
415+
if typ != 'OK':
416+
print 'Failed to get mailbox "%s": %s' % (mailbox, data)
417+
return 1
418+
try:
419+
numMessages = int(data[0])
420+
#print 'Found %s messages' % numMessages
421+
except ValueError:
422+
print 'Invalid return value from mailbox'
423+
return 1
424+
for i in range(1, numMessages+1):
425+
#print 'Processing message ', i
426+
(typ, data) = server.fetch(str(i), '(RFC822)')
427+
#This marks the message as deleted.
428+
server.store(str(i), '+FLAGS', r'(\Deleted)')
429+
#This is the raw text of the message
430+
s = cStringIO.StringIO(data[0][1])
431+
s.seek(0)
432+
self.handle_Message(Message(s))
433+
server.close()
434+
finally:
435+
try:
436+
server.expunge()
437+
except:
438+
pass
439+
server.logout()
440+
441+
return 0
442+
443+
369444
def do_apop(self, server, user='', password=''):
370445
''' Do authentication POP
371446
'''

roundup/scripts/roundup_mailgw.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1515
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1616
#
17-
# $Id: roundup_mailgw.py,v 1.12 2004-04-05 23:43:03 richard Exp $
17+
# $Id: roundup_mailgw.py,v 1.13 2004-04-13 04:11:06 richard Exp $
1818

1919
"""Command-line script stub that calls the roundup.mailgw.
2020
"""
@@ -80,6 +80,17 @@ def usage(args, message=None):
8080
Same as POP, but using Authenticated POP:
8181
apop username:password@server
8282
83+
IMAP:
84+
Connect to an IMAP server. This supports the same notation as that of POP mail.
85+
imap username:password@server
86+
It also allows you to specify a specific mailbox other than INBOX using this format:
87+
imap username:password@server mailbox
88+
89+
IMAPS:
90+
Connect to an IMAP server over ssl.
91+
This supports the same notation as IMAP.
92+
imaps username:password@server [mailbox]
93+
8394
''')
8495
return 1
8596

@@ -126,7 +137,7 @@ def main(argv):
126137
# otherwise, figure what sort of mail source to handle
127138
if len(args) < 3:
128139
return usage(argv, _('Error: not enough source specification information'))
129-
source, specification = args[1:]
140+
source, specification = args[1:3]
130141
if source == 'mailbox':
131142
return handler.do_mailbox(specification)
132143
elif source == 'pop':
@@ -143,6 +154,18 @@ def main(argv):
143154
return handler.do_apop(m.group('server'), m.group('user'),
144155
m.group('pass'))
145156
return usage(argv, _('Error: apop specification not valid'))
157+
elif source == 'imap' or source == 'imaps':
158+
m = re.match(r'((?P<user>[^:]+)(:(?P<pass>.+))?@)?(?P<server>.+)',
159+
specification)
160+
if m:
161+
ssl = False
162+
if source == 'imaps':
163+
ssl = True
164+
mailbox = ''
165+
if len(args) > 3:
166+
mailbox = args[3]
167+
return handler.do_imap(m.group('server'), m.group('user'),
168+
m.group('pass'), mailbox, ssl)
146169

147170
return usage(argv, _('Error: The source must be either "mailbox", "pop" or "apop"'))
148171
finally:

0 commit comments

Comments
 (0)