Hi, next patch: configurable boilerplate for message delivery. Delivery modules now support "MessageHeader" (disclaimer at top of delivered messages) and "MessageFooter" (disclaimer at bottom of delivered messages). "ArmorPlaintext" switches the (optional) OpenPGP ASCII armor on/off for for printable ASCII, i.e. exit remailer operators can turn off the "BEGIN TYPE III ANONYMOUS MESSAGE" wrapping for most outgoing messages. Patch and configuration example follow: ===== Beginn ===== Index: server/Modules.py =================================================================== --- server/Modules.py (revision 5) +++ server/Modules.py (working copy) @@ -970,15 +970,18 @@ # maxMessageSize: Largest allowable size (after decompression, before # base64) for outgoing messages. # allowFromAddr: Boolean: do we support user-supplied from addresses? + # armorPlaintext: Boolean: do we want to ASCII armor plaintext messages? COMMON_OPTIONS = { 'MaximumSize' : ('ALLOW', "size", "100K"), 'AllowFromAddress' : ('ALLOW', "boolean", "yes"), + 'ArmorPlaintext' : ('ALLOW', "boolean", "yes"), 'SubjectLine' : ('ALLOW', None, 'Type III Anonymous Message'), 'X-Abuse' : ('ALLOW', None, None), 'Comments' : ('ALLOW', None, None), - 'Message' : ('ALLOW', None, None), + 'MessageHeader' : ('ALLOW', None, None), + 'MessageFooter' : ('ALLOW', None, None), 'FromTag' : ('ALLOW', None, "[Anon]"), 'ReturnAddress' : ('ALLOW', None, None), } @@ -1022,9 +1025,9 @@ #FFFF be too much of a headache. # Decode and escape the message, and get ready to send it. - msg = _escapeMessageForEmail(packet) - msg = "To: %s\nFrom: %s\nSubject: %s\n%s%s%s"%( - address, fromAddr, subject, "".join(morelines), self.header, msg) + msg = _escapeMessageForEmail(packet, armorPlaintext=self.armorPlaintext) + msg = "To: %s\nFrom: %s\nSubject: %s\n%s%s%s%s%s"%( + address, fromAddr, subject, "".join(morelines), self.header, self.messageHeader, msg, self.messageFooter) return msg @@ -1045,15 +1048,21 @@ # Blank line between headers and body header.append("\n") - # see if we have a disclaimer - disclaimer = sec.get("Message") - if disclaimer: - header.append("\n".join(textwrap.wrap(disclaimer.strip()))) - # blank line between disclaimer and body. - header.append("\n\n") - self.header = "".join(header) + # see if we have a top disclaimer + disclaimerTop = sec.get("MessageHeader") + if disclaimerTop: + self.messageHeader = "\n".join(textwrap.wrap(disclaimerTop.strip())) + "\n\n" + else: + self.messageHeader = "" + # see if we have a bottom disclaimer + disclaimerBottom = sec.get("MessageFooter") + if disclaimerBottom: + self.messageFooter = "\n" + "\n".join(textwrap.wrap(disclaimerBottom.strip())) + else: + self.messageFooter = "" + #---------------------------------------------------------------------- class NewsModule(DeliveryModule, MailBase): """Implementation for newsgroup delivery: sends messages, via SMTP, @@ -1119,6 +1128,7 @@ self.contact = sec['RemoveContact'] self.retrySchedule = sec['Retry'] self.allowFromAddr = sec['AllowFromAddress'] + self.armorPlaintext = sec['ArmorPlaintext'] # validate should have caught these. assert (self.returnAddress and self.contact) @@ -1245,6 +1255,7 @@ self.contact = sec['RemoveContact'] self.retrySchedule = sec['Retry'] self.allowFromAddr = sec['AllowFromAddress'] + self.armorPlaintext = sec['ArmorPlaintext'] # validate should have caught these. assert (self.addressFile and self.returnAddress and self.contact) @@ -1410,6 +1421,7 @@ self.returnAddress = sec['ReturnAddress'] self.fromTag = sec.get('FromTag', "[Anon]") self.allowFromAddr = sec['AllowFromAddress'] + self.armorPlaintext = sec['ArmorPlaintext'] self.initializeHeaders(sec) @@ -1493,6 +1505,7 @@ self.retrySchedule = sec['Retry'] self.fromTag = sec.get('FromTag', "[Anon]") self.allowFromAddr = sec['AllowFromAddress'] + self.armorPlaintext = sec['ArmorPlaintext'] self.command = cmd[0] self.options = tuple(cmd[1]) + ("-l", self.server) self.returnAddress = "nobody" @@ -1622,7 +1635,7 @@ lines.append("") # to get final \n return "\n".join(lines) -def _escapeMessageForEmail(packet): +def _escapeMessageForEmail(packet, armorPlaintext=1): """Helper function: Given a DeliveryPacket, escape the message if it is not plaintext ascii, and wrap it in some standard boilerplate. Add a disclaimer if the message is not ascii. @@ -1634,6 +1647,8 @@ if packet.isError(): return None + encMsg = packet.getTextEncodedMessage() + if packet.isEncrypted(): junk_msg = """\ This message is not in plaintext. It's either 1) a reply; 2) a forward @@ -1650,7 +1665,10 @@ before sending it to you.\n\n""" else: assert packet.isPlaintext() + if not armorPlaintext: + # Return unencoded packet contents + return encMsg.getContents() + # Otherwise: encode below junk_msg = "" - encMsg = packet.getTextEncodedMessage() return "%s%s"%(junk_msg, encMsg.pack()) ===== Ende ===== Configuration example for MBOX delivery: ===== Beginn ===== [Delivery/MBOX] Enabled: yes AddressFile: <path to address file> ReturnAddress: <"From:" address to use> RemoveContact: <Address to use as a contact> #SendmailCommand: sendmail -i -t SMTPServer: localhost Retry: every 7 hours for 6 days MaximumSize: 100K AllowFromAddress: yes MessageHeader: <message header goes here> MessageFooter: <message footer goes here> ArmorPlaintext: no ===== Ende ===== Ciao Tobias -- mbox:admin@tainaron
Attachment:
pgpHbnxHH8xIx.pgp
Description: PGP signature