[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[minion-cvs] Add initial support for "SMTP-Via-Mixmaster" delivery m...



Update of /home/minion/cvsroot/src/minion/lib/mixminion
In directory moria.seul.org:/tmp/cvs-serv29795/lib/mixminion

Modified Files:
	Modules.py Queue.py 
Log Message:
Add initial support for "SMTP-Via-Mixmaster" delivery module.

This way, we should be able to get usable, arbitrary-address SMTP
delivery working even in release 0.0.1, when your average Minion
operator won't want to run a SMTP exit node.


Index: Modules.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Modules.py,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- Modules.py	21 Nov 2002 16:55:49 -0000	1.15
+++ Modules.py	21 Nov 2002 18:26:12 -0000	1.16
@@ -180,6 +180,7 @@
 
         self.registerModule(MBoxModule())
         self.registerModule(DropModule())
+        self.registerModule(MixmasterSMTPModule())
 
     def _setQueueRoot(self, queueRoot):
 	"""Sets a directory under which all modules' queue directories
@@ -194,6 +195,7 @@
     def registerModule(self, module):
 	"""Inform this ModuleManager about a delivery module.  This method
    	   updates the syntax options, but does not enable the module."""
+        getLog().info("Loading module %s", module.getName())
         self.modules.append(module)
         syn = module.getConfigSyntax()
         for sec, rules in syn.items():
@@ -248,8 +250,15 @@
     def enableModule(self, module):
 	"""Maps all the types for a module object."""
         for t in module.getExitTypes():
+            if (self.typeToModule.has_key(t) and
+                self.typeToModule[t].getName() != module.getName()):
+                getLog().warn("More than one module is enabled for type %x"%t)
             self.typeToModule[t] = module
 
+        getLog().info("Module %s: enabled for types %s",
+                      module.getName(),
+                      map(hex, module.getExitTypes()))
+
 	queueDir = os.path.join(self.queueRoot, module.getName())
 	queue = module.createDeliveryQueue(queueDir)
 	self.queues[module.getName()] = queue
@@ -260,8 +269,10 @@
 	
     def disableModule(self, module):
 	"""Unmaps all the types for a module object."""
+        getLog().info("Disabling module %s", module.getName())
         for t in module.getExitTypes():
-            if self.typeToModule.has_key(t):
+            if (self.typeToModule.has_key(t) and
+                self.typeToModule[t].getName() == module.getName()):
                 del self.typeToModule[t]
 	if self.queues.has_key(module.getName()):
 	    del self.queues[module.getName()]
@@ -341,7 +352,6 @@
 	    raise ConfigError("Missing ReturnAddress field in Delivery/MBOX")
 	if not self.contact:
 	    raise ConfigError("Missing RemoveContact field in Delivery/MBOX")
-			
 
         self.nickname = config['Server']['Nickname']
         if not self.nickname:
@@ -408,6 +418,95 @@
 
         return sendSMTPMessage(self.server, [address], self.returnAddress, msg)
 
+#----------------------------------------------------------------------
+class SMTPModule(DeliveryModule):
+    """Placeholder for real exit node implementation.
+        DOCDOC XXXXX document me."""
+    def __init__(self):
+        DeliveryModule.__init__(self)
+        self.enabled = 0
+    def getServerInfoBlock(self):
+        if self.enabled:
+            return "[Delivery/SMTP]\nVersion: 0.1\n"
+        else:
+            return ""
+    def getName(self):
+        return "SMTP"
+    def getExitTypes(self):
+        return (SMTP_TYPE,)
+
+class MixmasterSMTPModule(SMTPModule):
+    """Implements SMTP by relaying messages via Mixmaster nodes.  This
+       is kind of unreliable and kludgey, but it does allow us to
+       test mixminion by usingg Mixmaster nodes as exits."""
+    # FFFF Mixmaster has tons of options.  Maybe we should use 'em...
+    # FFFF ... or maybe we should deliberately ignore them, since
+    # FFFF this is only a temporary workaround until enough people 
+    # FFFF are running SMTP exit nodes
+    def __init__(self):
+        SMTPModule.__init__(self)
+        self.mixDir = None
+    def getConfigSyntax(self):
+        return { "Delivery/SMTP-Via-Mixmaster" :
+                 { 'Enabled' : ('REQUIRE', _parseBoolean, "no"),
+                   'MixCommand' : ('REQUIRE', _parseCommand, None),
+                   'Server' : ('REQUIRE', None, None),
+                   'SubjectLine' : ('ALLOW', None,
+                                    'Type-III Anonymous Message'),
+                   }
+                 }
+                   
+    def validateConfig(self, sections, entries, lines, contents):
+        #FFFF implement
+        pass
+    def configure(self, config, manager):
+        sec = config['Delivery/SMTP-Via-Mixmaster']
+        self.enabled = sec.get("Enabled", 0)
+        if not self.enabled:
+            manager.disableModule(self)
+            return
+        cmd = sec['MixmasterCommand']
+        self.server = sec['Server']
+        self.subject = sec['Subject']
+        self.command = cmd[0]
+        self.options = cmd[1] + ("-l", self.server,
+                                 "-s", self.subject)
+        
+    def getName(self): 
+        return "SMTP_MIX2" 
+    def createDeliveryQueue(self, queueDir):
+        self.tmpQueue = mixminion.Queue.queue(queueDir+"_tmp", 1, 1)
+        self.tmpQueue.removeAll()
+        return _MixmasterSMTPModuleDeliveryQueue(self, queueDir)
+    def processMessage(self, message, exitType, exitInfo):
+        assert exitType == SMTP_TYPE
+        info = mixminion.Packet.parseSMTPInfo(exitInfo)
+
+        msg = _escapeMessageForEmail(message, info.tag)
+        handle = self.tmpQueue.queueMessage(msg)
+        
+        cmd = self.command
+        opts = self.options + (info.email,
+                               self.tmpQueue.getMessagePath(handle))
+        code = os.spawnl(os.P_WAIT, cmd, cmd, *opts)
+        getLog().debug("Queued Mixmaster message: exit code %s", code)
+        self.tmpQueue.removeMessage(handle)
+        return DELIVER_OK
+                         
+    def flushMixmasterPool(self):
+        "XXXX"
+        cmd = self.command
+        getLog().debug("Flushing Mixmaster pool")
+        os.spawnl(os.P_NOWAIT, cmd, cmd, "-S")
+
+class _MixmasterSMTPModuleDeliveryQueue(SimpleModuleDeliveryQueue):
+    "XXXX"
+    def __init__(self, module, directory):
+        SimpleModuleDeliveryQueue.__init__(self, module, directory)
+    def deliverMessages(self, msgList):
+        SimpleModuleDeliveryQueue.deliverMessages(self, msgList)
+        self.module.flushMixmaterPool()
+        
 #----------------------------------------------------------------------
 def sendSMTPMessage(server, toList, fromAddr, message):
     con = smtplib(server)

Index: Queue.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Queue.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Queue.py	11 Nov 2002 16:32:41 -0000	1.19
+++ Queue.py	21 Nov 2002 18:26:12 -0000	1.20
@@ -152,6 +152,11 @@
         self.removeMessage(handle)
         return newHandle
 
+    def getMessagePath(self, handle):
+        """Given a handle for an existing message, return the name of the
+           file that contains that message."""
+        return os.path.join(self.dir, "msg_"+handle)
+
     def openMessage(self, handle):
         """Given a handle for an existing message, returns a file descriptor
            open to read that message."""