# HG changeset patch # User Paul Boddie # Date 1342915104 -7200 # Node ID 710ca8cada97fc3c4ad2c8c42adf00aaa0522e52 # Parent 29c65bed990b2ea59d08176d4d4a009c47610334 Added a library for preparing and sending messages, along with a test of the library. Removed a superfluous variable from the encryption test. diff -r 29c65bed990b -r 710ca8cada97 MoinMessage.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MoinMessage.py Sun Jul 22 01:58:24 2012 +0200 @@ -0,0 +1,131 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - MoinMessage library + + @copyright: 2012 by Paul Boddie + @license: GNU GPL (v2 or later), see COPYING.txt for details. +""" + +from MoinMoin.log import getLogger +from email import message_from_string +from email.encoders import encode_noop +from email.mime.multipart import MIMEMultipart +from email.mime.application import MIMEApplication +from email.mime.base import MIMEBase +from email.mime.text import MIMEText +from subprocess import Popen, PIPE +import httplib + +class Message: + + "An update message." + + def __init__(self): + self.updates = [] + + def add_update(self, alternatives): + if len(alternatives) > 1: + part = MIMEMultipart() + for alternative in alternatives: + part.attach(alternative) + self.updates.append(part) + else: + self.updates.append(alternatives[0]) + + def get_payload(self): + if len(self.updates) == 1: + message = self.updates[0] + else: + message = MIMEMultipart() + message.add_header("Update-Type", "collection") + for update in self.updates: + message.attach(update) + + return message + +class MoinMessageError(Exception): + pass + +def gpg(args, text): + + "Invoke gpg with the given 'args', supplying the given 'text'." + + cmd = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) + + cmd.stdin.write(text) + cmd.stdin.close() + + errors = cmd.stderr.read() + if errors: + getLogger(__name__).warning(errors) + + try: + text = cmd.stdout.read() + + # Test for a zero result. + + if not cmd.wait(): + return text + else: + raise MoinMessageError, errors + + finally: + cmd.stdout.close() + cmd.stderr.close() + +def signMessage(message, keyid): + + """ + Return a signed 'message' using the given 'keyid'. + """ + + text = message.as_string() + signature = gpg(["gpg", "--armor", "-u", keyid, "--detach-sig"], text) + + # Make the container for the message. + + signed_message = MIMEMultipart("signed", protocol="application/pgp-signature") + signed_message.attach(message) + + signature_part = MIMEBase("application", "pgp-signature") + signature_part.set_payload(signature) + signed_message.attach(signature_part) + + return signed_message + +def encryptMessage(message, keyid): + + """ + Return an encrypted 'message' using the given 'keyid'. + """ + + text = message.as_string() + encrypted = gpg(["gpg", "--armor", "-r", keyid, "--encrypt", "--trust-model", "always"], text) + + # Make the container for the message. + + encrypted_message = MIMEMultipart("encrypted", protocol="application/pgp-encrypted") + + # For encrypted content, add the declaration and content. + + declaration = MIMEBase("application", "pgp-encrypted") + declaration.set_payload("Version: 1") + encrypted_message.attach(declaration) + + content = MIMEApplication(encrypted, "octet-stream", encode_noop) + encrypted_message.attach(content) + + return encrypted_message + +def sendMessage(message, host, path): + + "Send 'message' to the given 'host' using the specified URL 'path'." + + text = message.as_string() + + req = httplib.HTTPConnection(host) + req.request("PUT", path, text) # {"Content-Length" : len(text)} + resp = req.getresponse() + return resp.read() + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 29c65bed990b -r 710ca8cada97 tests/test_encrypt.py --- a/tests/test_encrypt.py Sat Jul 21 23:52:59 2012 +0200 +++ b/tests/test_encrypt.py Sun Jul 22 01:58:24 2012 +0200 @@ -8,7 +8,6 @@ if __name__ == "__main__": text = sys.stdin.read() - signature = None protocol = "application/pgp-encrypted" subtype = "encrypted" diff -r 29c65bed990b -r 710ca8cada97 tests/test_send.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_send.py Sun Jul 22 01:58:24 2012 +0200 @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +from MoinMessage import * +from email.mime.text import MIMEText +import sys + +if __name__ == "__main__": + signer = sys.argv[1] + recipient = sys.argv[2] + host = sys.argv[3] + path = sys.argv[4] + "?action=PostMessage" + + message = Message() + message.add_update([MIMEText("An update to the Wiki.", "moin")]) + message.add_update([MIMEText("Another update to the Wiki.", "moin")]) + email_message = message.get_payload() + + try: + signed_message = signMessage(email_message, signer) + encrypted_message = encryptMessage(signed_message, recipient) + sendMessage(encrypted_message, host, path) + except MoinMessageError, exc: + print exc + +# vim: tabstop=4 expandtab shiftwidth=4