From 9b6a537e097eb79de4f8c0e6eaaacf1c7c20b6f0 Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 11 Sep 2002 01:19:16 +0000 Subject: [PATCH] reorganised mailgw code git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1128 57a73879-2fb5-44c3-a270-3262357dd7e2 --- roundup/mailgw.py | 91 +++++++++++++++++++++++++++++-- roundup/scripts/roundup_mailgw.py | 86 +++-------------------------- 2 files changed, 92 insertions(+), 85 deletions(-) diff --git a/roundup/mailgw.py b/roundup/mailgw.py index 07a041d..7057597 100644 --- a/roundup/mailgw.py +++ b/roundup/mailgw.py @@ -73,7 +73,7 @@ are calling the create() method to create a new node). If an auditor raises an exception, the original message is bounced back to the sender with the explanatory message given in the exception. -$Id: mailgw.py,v 1.86 2002-09-10 12:44:42 richard Exp $ +$Id: mailgw.py,v 1.87 2002-09-11 01:19:16 richard Exp $ ''' import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri @@ -143,6 +143,79 @@ class MailGW: # (for testing) self.trapExceptions = 1 + def do_pipe(self): + ''' Read a message from standard input and pass it to the mail handler. + ''' + self.main(sys.stdin) + return 0 + + def do_mailbox(self, filename): + ''' Read a series of messages from the specified unix mailbox file and + pass each to the mail handler. + ''' + # open the spool file and lock it + import fcntl, FCNTL + f = open(filename, 'r+') + fcntl.flock(f.fileno(), FCNTL.LOCK_EX) + + # handle and clear the mailbox + try: + from mailbox import UnixMailbox + mailbox = UnixMailbox(f, factory=Message) + # grab one message + message = mailbox.next() + while message: + # handle this message + self.handle_Message(message) + message = mailbox.next() + # nuke the file contents + os.ftruncate(f.fileno(), 0) + except: + import traceback + traceback.print_exc() + return 1 + fcntl.flock(f.fileno(), FCNTL.LOCK_UN) + return 0 + + def do_pop(self, server, user='', password=''): + '''Read a series of messages from the specified POP server. + ''' + import getpass, poplib, socket + try: + if not user: + user = raw_input(_('User: ')) + if not password: + password = getpass.getpass() + except (KeyboardInterrupt, EOFError): + # Ctrl C or D maybe also Ctrl Z under Windows. + print "\nAborted by user." + return 1 + + # open a connection to the server and retrieve all messages + try: + server = poplib.POP3(server) + except socket.error, message: + print "POP server error:", message + return 1 + server.user(user) + server.pass_(password) + numMessages = len(server.list()[1]) + for i in range(1, numMessages+1): + # retr: returns + # [ pop response e.g. '+OK 459 octets', + # [ array of message lines ], + # number of octets ] + lines = server.retr(i)[1] + s = cStringIO.StringIO('\n'.join(lines)) + s.seek(0) + self.handle_Message(Message(s)) + # delete the message + server.dele(i) + + # quit the server to commit changes. + server.quit() + return 0 + def main(self, fp): ''' fp - the file from which to read the Message. ''' @@ -795,9 +868,13 @@ def parseContent(content, keep_citations, keep_body, signature=re.compile(r'^[>|\s]*[-_]+\s*$'), original_message=re.compile(r'^[>|\s]*-----Original Message-----$')): ''' The message body is divided into sections by blank lines. - Sections where the second and all subsequent lines begin with a ">" or "|" - character are considered "quoting sections". The first line of the first - non-quoting section becomes the summary of the message. + Sections where the second and all subsequent lines begin with a ">" + or "|" character are considered "quoting sections". The first line of + the first non-quoting section becomes the summary of the message. + + If keep_citations is true, then we keep the "quoting sections" in the + content. + If keep_body is true, we even keep the signature sections. ''' # strip off leading carriage-returns / newlines i = 0 @@ -850,10 +927,12 @@ def parseContent(content, keep_citations, keep_body, # and add the section to the output l.append(section) - # we only set content for those who want to delete cruft from the - # message body, otherwise the body is left untouched. + + # Now reconstitute the message content minus the bits we don't care + # about. if not keep_body: content = '\n\n'.join(l) + return summary, content # vim: set filetype=python ts=4 sw=4 et si diff --git a/roundup/scripts/roundup_mailgw.py b/roundup/scripts/roundup_mailgw.py index 0d28019..d644636 100644 --- a/roundup/scripts/roundup_mailgw.py +++ b/roundup/scripts/roundup_mailgw.py @@ -14,7 +14,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundup_mailgw.py,v 1.4 2002-09-10 01:07:06 richard Exp $ +# $Id: roundup_mailgw.py,v 1.5 2002-09-11 01:19:16 richard Exp $ # python version check from roundup import version_check @@ -24,85 +24,13 @@ import sys, os, re, cStringIO from roundup.mailgw import Message from roundup.i18n import _ -def do_pipe(handler): - '''Read a message from standard input and pass it to the mail handler. - ''' - handler.main(sys.stdin) - return 0 - -def do_mailbox(handler, filename): - '''Read a series of messages from the specified unix mailbox file and - pass each to the mail handler. - ''' - # open the spool file and lock it - import fcntl, FCNTL - f = open(filename, 'r+') - fcntl.flock(f.fileno(), FCNTL.LOCK_EX) - - # handle and clear the mailbox - try: - from mailbox import UnixMailbox - mailbox = UnixMailbox(f, factory=Message) - # grab one message - message = mailbox.next() - while message: - # call the instance mail handler - handler.handle_Message(message) - message = mailbox.next() - # nuke the file contents - os.ftruncate(f.fileno(), 0) - except: - import traceback - traceback.print_exc() - return 1 - fcntl.flock(f.fileno(), FCNTL.LOCK_UN) - return 0 - -def do_pop(handler, server, user='', password=''): - '''Read a series of messages from the specified POP server. - ''' - import getpass, poplib, socket - try: - if not user: - user = raw_input(_('User: ')) - if not password: - password = getpass.getpass() - except (KeyboardInterrupt, EOFError): - # Ctrl C or D maybe also Ctrl Z under Windows. - print "\nAborted by user." - return 1 - - # open a connection to the server and retrieve all messages - try: - server = poplib.POP3(server) - except socket.error, message: - print "POP server error:", message - return 1 - server.user(user) - server.pass_(password) - numMessages = len(server.list()[1]) - for i in range(1, numMessages+1): - # retr: returns - # [ pop response e.g. '+OK 459 octets', - # [ array of message lines ], - # number of octets ] - lines = server.retr(i)[1] - s = cStringIO.StringIO('\n'.join(lines)) - s.seek(0) - handler.handle_Message(Message(s)) - # delete the message - server.dele(i) - - # quit the server to commit changes. - server.quit() - return 0 - def usage(args, message=None): if message is not None: print message - print _('Usage: %(program)s [source spec]')%{'program': args[0]} + print _('Usage: %(program)s [method]')%{'program': args[0]} print _(''' -The roundup mail gateway may be called in one of two ways: + +The roundup mail gateway may be called in one of three ways: . with an instance home as the only argument, . with both an instance home and a mail spool file, or . with both an instance home and a pop server account. @@ -152,19 +80,19 @@ def main(args): # if there's no more arguments, read a single message from stdin if len(args) == 2: - return do_pipe(handler) + return handler.do_pipe() # otherwise, figure what sort of mail source to handle if len(args) < 4: return usage(args, _('Error: not enough source specification information')) source, specification = args[2:] if source == 'mailbox': - return do_mailbox(handler, specification) + return handler.do_mailbox(specification) elif source == 'pop': m = re.match(r'((?P[^:]+)(:(?P.+))?@)?(?P.+)', specification) if m: - return do_pop(handler, m.group('server'), m.group('user'), + return handler.do_pop(m.group('server'), m.group('user'), m.group('pass')) return usage(args, _('Error: pop specification not valid')) -- 2.30.2