# HG changeset patch # User Paul Boddie # Date 1414451386 -3600 # Node ID 56ec48e6cedb824bc89b1331c1741f7d97dd5806 # Parent 5cc902ed15c799f7a21c7ed9f98ff7c655701c01 Moved message sending functionality into a separate class. diff -r 5cc902ed15c7 -r 56ec48e6cedb imip_manager.py --- a/imip_manager.py Tue Oct 28 00:09:07 2014 +0100 +++ b/imip_manager.py Tue Oct 28 00:09:46 2014 +0100 @@ -4,7 +4,7 @@ sys.path.append("/var/lib/imip-agent") -from imiptools import make_message, sendmail +from imiptools import Messenger from imiptools.content import Handler, \ format_datetime, get_address, get_datetime, \ get_item, get_uri, get_utc_datetime, get_values, \ @@ -67,10 +67,12 @@ "A content handler for use by the manager." - def __init__(self, details, objtype, user): + def __init__(self, details, objtype, user, messenger): Handler.__init__(self, details) self.objtype = objtype self.user = user + self.messenger = messenger + self.organisers = map(get_address, self.get_values("ORGANIZER")) # Communication methods. @@ -82,12 +84,10 @@ given 'sender'. """ - # NOTE: Should parameterise the subject and body text. - node = to_node({self.objtype : [(self.details, {})]}) part = to_part("REPLY", [node]) - message = make_message([part], self.organisers, sender, "Response to request", "Response to a calendar request") - sendmail(sender, self.organisers, message.as_string()) + message = self.messenger.make_message([part], self.organisers) + self.messenger.sendmail(self.organisers, message.as_string()) # Action methods. @@ -128,7 +128,9 @@ "A simple manager application." - def __init__(self): + def __init__(self, messenger=None): + self.messenger = messenger or Messenger() + self.env = CGIEnvironment() user = self.env.get_user() self.user = user and get_uri(user) or None @@ -221,7 +223,7 @@ if accept or decline: - handler = ManagerHandler(request, objtype, self.user) + handler = ManagerHandler(request, objtype, self.user, self.messenger) if handler.process_request(accept): @@ -302,7 +304,7 @@ else: self.no_page() - def show(self): + def __call__(self): "Interpret a request and show an appropriate response." @@ -318,6 +320,6 @@ self.out.write(unicode(self.page).encode(self.encoding)) if __name__ == "__main__": - Manager().show() + Manager()() # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5cc902ed15c7 -r 56ec48e6cedb imiptools/__init__.py --- a/imiptools/__init__.py Tue Oct 28 00:09:07 2014 +0100 +++ b/imiptools/__init__.py Tue Oct 28 00:09:46 2014 +0100 @@ -27,29 +27,6 @@ "text/x-vcalendar", "application/ics", # other possibilities ] -# Sending of outgoing messages. - -def sendmail(sender, recipients, data, lmtp_socket=None): - if lmtp_socket: - smtp = LMTP(lmtp_socket) - else: - smtp = SMTP("localhost") - smtp.sendmail(sender, recipients, data) - smtp.quit() - -def make_message(parts, recipients, sender, subject, body_text): - message = MIMEMultipart("mixed", _subparts=parts) - message.preamble = body_text - payload = message.get_payload() - payload.insert(0, MIMEText(body_text)) - - message["From"] = sender - for recipient in recipients: - message["To"] = recipient - message["Subject"] = subject - - return message - # Processing of incoming messages. def get_all_values(msg, key): @@ -58,15 +35,68 @@ l += [s.strip() for s in v.split(",")] return l +class Messenger: + + "Sending of outgoing messages." + + def __init__(self, sender=None, subject=None, body_text=None): + self.sender = sender or MESSAGE_SENDER + self.subject = subject or MESSAGE_SUBJECT + self.body_text = body_text or MESSAGE_TEXT + + def sendmail(self, recipients, data, lmtp_socket=None): + + """ + Send a mail to the given 'recipients' consisting of the given 'data', + delivering to a local mail system using LMTP if 'lmtp_socket' is + provided. + """ + + if lmtp_socket: + smtp = LMTP(lmtp_socket) + else: + smtp = SMTP("localhost") + + smtp.sendmail(self.sender, recipients, data) + smtp.quit() + + def make_message(self, parts, recipients): + + "Make a message from the given 'parts' for the given 'recipients'." + + message = MIMEMultipart("mixed", _subparts=parts) + message.preamble = self.body_text + payload = message.get_payload() + payload.insert(0, MIMEText(self.body_text)) + + message["From"] = self.sender + for recipient in recipients: + message["To"] = recipient + message["Subject"] = self.subject + + return message + + def wrap_message(self, msg, parts): + + "Wrap 'msg' and provide the given 'parts' as the primary content." + + message = MIMEMultipart("mixed", _subparts=parts) + message.preamble = self.body_text + message.get_payload().append(MIMEMessage(msg)) + + message["From"] = msg["From"] + message["To"] = msg["To"] + message["Subject"] = msg["Subject"] + + return message + class Processor: "The processing framework." - def __init__(self, handlers, sender=None, subject=None, body_text=None): + def __init__(self, handlers, messenger=None): self.handlers = handlers - self.sender = sender or MESSAGE_SENDER - self.subject = subject or MESSAGE_SUBJECT - self.body_text = body_text or MESSAGE_TEXT + self.messenger = messenger or Messenger() self.lmtp_socket = None def process(self, f, original_recipients, recipients): @@ -107,22 +137,22 @@ # Reply using any outgoing parts in a new message. if outgoing_parts: - message = self.make_message(outgoing_parts, senders) + message = self.messenger.make_message(outgoing_parts, senders) if "-d" in sys.argv: print message else: - sendmail(self.sender, senders, message.as_string()) + self.messenger.sendmail(senders, message.as_string()) # Forward messages to their recipients using the existing message. if forwarded_parts: - message = self.wrap_message(msg, forwarded_parts) + message = self.messenger.wrap_message(msg, forwarded_parts) if "-d" in sys.argv: print message elif self.lmtp_socket: - sendmail(self.sender, original_recipients, message.as_string(), self.lmtp_socket) + self.messenger.sendmail(original_recipients, message.as_string(), self.lmtp_socket) # Unhandled messages are delivered as they are. @@ -130,27 +160,7 @@ if "-d" in sys.argv: print msg elif self.lmtp_socket: - sendmail(self.sender, original_recipients, msg.as_string(), self.lmtp_socket) - - def make_message(self, parts, recipients): - - "Make a message from the given 'parts' for the given 'recipients'." - - return make_message(parts, recipients, self.sender, self.subject, self.body_text) - - def wrap_message(self, msg, parts): - - "Wrap 'msg' and provide the given 'parts' as the primary content." - - message = MIMEMultipart("mixed", _subparts=parts) - message.preamble = self.body_text - message.get_payload().append(MIMEMessage(msg)) - - message["From"] = msg["From"] - message["To"] = msg["To"] - message["Subject"] = msg["Subject"] - - return message + self.messenger.sendmail(original_recipients, msg.as_string(), self.lmtp_socket) def process_args(self, args, stream): @@ -194,7 +204,7 @@ else: l.append(arg) - self.sender = senders and senders[0] or self.sender + self.messenger.sender = senders and senders[0] or self.messenger.sender self.lmtp_socket = lmtp and lmtp[0] or None self.process(stream, original_recipients, recipients) @@ -219,6 +229,8 @@ raise type, value, tb = sys.exc_info() print >>sys.stderr, "Exception %s at %d" % (exc, tb.tb_lineno) + #import traceback + #traceback.print_exc(file=open("/tmp/mail.log", "a")) sys.exit(EX_TEMPFAIL) sys.exit(0)