[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[minion-cvs] Apply patch from Brian Fordham, tweaked. Needs unit tes...
Update of /home/minion/cvsroot/src/minion/lib/mixminion/server
In directory moria.mit.edu:/tmp/cvs-serv7417/lib/mixminion/server
Modified Files:
Modules.py
Log Message:
Apply patch from Brian Fordham, tweaked. Needs unit tests and documentation.
Index: Modules.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/Modules.py,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -d -r1.71 -r1.72
--- Modules.py 21 Feb 2004 00:02:09 -0000 1.71
+++ Modules.py 25 Feb 2004 06:03:11 -0000 1.72
@@ -927,7 +927,6 @@
return 0
#----------------------------------------------------------------------
-
def _cleanMaxSize(sz,modname):
"""Given a 'Maximum-Size' configuration value, ensure that it's at least
32KB, and round it up to the next highest 1KB increment. Use 'modname'
@@ -942,6 +941,14 @@
sz = 1024*kb
return sz
+DEFAULT_SUBJECT_LINE = "Type III Anonymous Message"
+DEFAULT_MBOX_DISCLAIMER = """\
+THIS IS AN ANONYMOUS MESSAGE. The Mixminion server '%(nickname)s' at
+<%(IP)s has been configured to deliver messages to your address.
+If you do not want to receive messages in the future, contact %(removeaddress)s
+and you will be removed."""
+DEFAULT_SMTP_DISCLAIMER = ""
+
class MailBase:
"""Implementation class: contains code shared by modules that send email
messages (such as mbox and smtp)."""
@@ -957,6 +964,19 @@
# maxMessageSize: Largest allowable size (after decompression, before
# base64) for outgoing messages.
# allowFromAddr: Boolean: do we support user-supplied from addresses?
+
+ COMMON_OPTIONS = {
+ 'MaximumSize' : ('ALLOW', "size", "100K"),
+ 'AllowFromAddress' : ('ALLOW', "boolean", "yes"),
+ 'SubjectLine' : ('ALLOW', None,
+ 'Type III Anonymous Message'),
+ 'X-Abuse' : ('ALLOW', None, None),
+ 'Comments' : ('ALLOW', None, None),
+ 'Message' : ('ALLOW', None, None),
+ 'FromTag' : ('ALLOW', None, "[Anon]"),
+ 'ReturnAddress' : ('ALLOW', None, None),
+ }
+
def _formatEmailMessage(self, address, packet):
"""Given a RFC822 mailbox (delivery address), and an instance of
DeliveryMessage, return a string containing a message to be sent
@@ -988,11 +1008,37 @@
# Decode and escape the message, and get ready to send it.
msg = _escapeMessageForEmail(packet)
- msg = "To: %s\nFrom: %s\nSubject: %s\n%s%s\n\n%s"%(
+ msg = "To: %s\nFrom: %s\nSubject: %s\n%s%s%s"%(
address, fromAddr, subject, "".join(morelines), self.header, msg)
return msg
+ def initializeHeaders(self, sec):
+ """Sets subject and returns a string that can be added to message
+ headers."""
+ # set subject
+ self.subject = _wrapHeader(sec.get("SubjectLine").strip()).strip()
+
+ header = [ "X-Anonymous: yes\n" ]
+
+ # I'm putting this in a list so adding headers will be simple
+ for h in ['X-Abuse', 'Comments']:
+ val = sec.get(h)
+ if val:
+ header.append(_wrapHeader("%s: %s" % (h, val)))
+
+ # 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)
+
#----------------------------------------------------------------------
class MBoxModule(DeliveryModule, MailBase):
"""Implementation for MBOX delivery: sends messages, via SMTP, to
@@ -1023,18 +1069,15 @@
def getConfigSyntax(self):
# FFFF There should be some way to say that fields are required
# FFFF if the module is enabled.
- return { "Delivery/MBOX" :
- { 'Enabled' : ('REQUIRE', "boolean", "no"),
- 'Retry': ('ALLOW', "intervalList",
- "7 hours for 6 days"),
- 'AddressFile' : ('ALLOW', "filename", None),
- 'ReturnAddress' : ('ALLOW', None, None),
- 'RemoveContact' : ('ALLOW', None, None),
- 'AllowFromAddress' : ('ALLOW', "boolean", 'yes'),
- 'SMTPServer' : ('ALLOW', None, 'localhost'),
- 'MaximumSize' : ('ALLOW', "size", "100K"),
- }
- }
+ cfg = { 'Enabled' : ('REQUIRE', "boolean", "no"),
+ 'Retry': ('ALLOW', "intervalList",
+ "7 hours for 6 days"),
+ 'AddressFile' : ('ALLOW', "filename", None),
+ 'RemoveContact' : ('ALLOW', None, None),
+ 'SMTPServer' : ('ALLOW', None, 'localhost'),
+ }
+ cfg.update(MailBase.COMMON_OPTIONS)
+ return { "Delivery/MBOX" : cfg }
def validateConfig(self, config, lines, contents):
sec = config['Delivery/MBOX']
@@ -1078,15 +1121,8 @@
"Delivery/MBOX")
# These fields are needed by MailBase
- self.subject = "Type III Anonymous Message"
+ self.initializeHeaders(sec)
self.fromTag = "[Anon]"
- self.header = """\
-X-Anonymous: yes
-
-THIS IS AN ANONYMOUS MESSAGE. The mixminion server '%s' at
-%s has been configured to deliver messages to your address.
-If you do not want to receive messages in the future, contact %s
-and you will be removed.""" %(self.nickname, self.addr, self.contact)
# Parse the address file.
self.addresses = {}
@@ -1184,25 +1220,19 @@
def __init__(self):
SMTPModule.__init__(self)
+
def getRetrySchedule(self):
return self.retrySchedule
def getConfigSyntax(self):
- return { "Delivery/SMTP" :
- { 'Enabled' : ('REQUIRE', "boolean", "no"),
- 'Retry': ('ALLOW', "intervalList",
- "7 hours for 6 days"),
- 'BlacklistFile' : ('ALLOW', "filename", None),
- 'SMTPServer' : ('ALLOW', None, 'localhost'),
- 'AllowFromAddress': ('ALLOW', "boolean", "yes"),
- 'Message' : ('ALLOW', None, ""),
- 'ReturnAddress': ('ALLOW', None, None), #Required on e
- 'FromTag' : ('ALLOW', None, "[Anon]"),
- 'SubjectLine' : ('ALLOW', None,
- 'Type III Anonymous Message'),
- 'MaximumSize' : ('ALLOW', "size", "100K"),
- }
- }
+ cfg = { 'Enabled' : ('REQUIRE', "boolean", "no"),
+ 'Retry': ('ALLOW', "intervalList",
+ "7 hours for 6 days"),
+ 'BlacklistFile' : ('ALLOW', "filename", None),
+ 'SMTPServer' : ('ALLOW', None, 'localhost'),
+ }
+ cfg.update(MailBase.COMMON_OPTIONS)
+ return { "Delivery/SMTP" : cfg }
def validateConfig(self, config, lines, contents):
sec = config['Delivery/SMTP']
@@ -1232,15 +1262,11 @@
self.blacklist = EmailAddressSet(fname=sec['BlacklistFile'])
else:
self.blacklist = None
- message = "\n".join(textwrap.wrap(sec.get('Message',""))).strip()
- self.subject = sec['SubjectLine']
self.returnAddress = sec['ReturnAddress']
self.fromTag = sec.get('FromTag', "[Anon]")
self.allowFromAddr = sec['AllowFromAddress']
- if message:
- self.header = "X-Anonymous: yes\n\n%s" %(message)
- else:
- self.header = "X-Anonymous: yes"
+
+ self.initializeHeaders(sec)
self.maxMessageSize = _cleanMaxSize(sec['MaximumSize'],
"Delivery/SMTP")
@@ -1295,19 +1321,14 @@
return self.retrySchedule
def getConfigSyntax(self):
- return { "Delivery/SMTP-Via-Mixmaster" :
- { 'Enabled' : ('REQUIRE', "boolean", "no"),
- 'Retry': ('ALLOW', "intervalList",
- "7 hours for 6 days"),
- 'MixCommand' : ('REQUIRE', "command", None),
- 'Server' : ('REQUIRE', None, None),
- 'FromTag' : ('ALLOW', None, "[Anon]"),
- 'SubjectLine' : ('ALLOW', None,
- 'Type III Anonymous Message'),
- 'MaximumSize' : ('ALLOW', "size", "100K"),
- 'AllowFromAddress' : ('ALLOW', "boolean", "yes"),
- }
- }
+ cfg = { 'Enabled' : ('REQUIRE', "boolean", "no"),
+ 'Retry': ('ALLOW', "intervalList",
+ "7 hours for 6 days"),
+ 'MixCommand' : ('REQUIRE', "command", None),
+ 'Server' : ('REQUIRE', None, None),
+ }
+ cfg.update(MailBase.COMMON_OPTIONS)
+ return { "Delivery/SMTP-Via-Mixmaster" : cfg }
def validateConfig(self, config, lines, contents):
#FFFF write more
@@ -1323,14 +1344,13 @@
return
cmd = sec['MixCommand']
self.server = sec['Server']
- self.subject = sec['SubjectLine']
self.retrySchedule = sec['Retry']
self.fromTag = sec.get('FromTag', "[Anon]")
self.allowFromAddr = sec['AllowFromAddress']
self.command = cmd[0]
self.options = tuple(cmd[1]) + ("-l", self.server)
self.returnAddress = "nobody"
- self.header = "X-Anonymous: yes"
+ self.initializeHeaders(sec)
self.maxMessageSize = _cleanMaxSize(sec['MaximumSize'],
"Delivery/SMTP-Via-Mixmaster")
manager.enableModule(self)
@@ -1438,6 +1458,13 @@
#----------------------------------------------------------------------
+def _wrapHeader(text):
+ """Wraps a header. If it's more than 70 characters long, adds
+ spaces to the next lines so it's properly indented."""
+ lines = textwrap.wrap(text.strip(), width=70, subsequent_indent=" ")
+ lines.append("") # to get final \n
+ return "\n".join(lines)
+
def _escapeMessageForEmail(packet):
"""Helper function: Given a DeliveryPacket, escape the message if
it is not plaintext ascii, and wrap it in some standard