[Zope-Checkins] SVN: Zope/trunk/ added support for asynchronous
mail delivery using zope.sendmail
Andreas Jung
andreas at andreas-jung.com
Sun Aug 19 05:05:12 EDT 2007
Log message for revision 78983:
added support for asynchronous mail delivery using zope.sendmail
queue mechanism
Changed:
U Zope/trunk/doc/CHANGES.txt
U Zope/trunk/lib/python/Products/MailHost/MailHost.py
U Zope/trunk/lib/python/Products/MailHost/dtml/manageMailHost.dtml
-=-
Modified: Zope/trunk/doc/CHANGES.txt
===================================================================
--- Zope/trunk/doc/CHANGES.txt 2007-08-19 07:24:24 UTC (rev 78982)
+++ Zope/trunk/doc/CHANGES.txt 2007-08-19 09:05:12 UTC (rev 78983)
@@ -66,7 +66,11 @@
- MailHost: now uses zope.sendmail for delivering the mail providing
integration with the Zope transaction system (avoids sending dupe
- emails in case of conflict errors)
+ emails in case of conflict errors). In addition MailHost now provides
+ support for asynchronous mail delivery. The 'Use queue' configuration
+ option will create a mail queue on the filesystem (under
+ 'Queue directory') and start a queue thread that checks the queue every
+ three seconds. This decouples the sending of mail from its delivery.
- integrated ZODB 3.8
Modified: Zope/trunk/lib/python/Products/MailHost/MailHost.py
===================================================================
--- Zope/trunk/lib/python/Products/MailHost/MailHost.py 2007-08-19 07:24:24 UTC (rev 78982)
+++ Zope/trunk/lib/python/Products/MailHost/MailHost.py 2007-08-19 09:05:12 UTC (rev 78983)
@@ -17,6 +17,7 @@
import mimetools
import rfc822
+import time
from cStringIO import StringIO
import Acquisition
@@ -31,10 +32,13 @@
from zope.interface import implements
from zope.sendmail.mailer import SMTPMailer
-from zope.sendmail.delivery import DirectMailDelivery
+from zope.sendmail.delivery import DirectMailDelivery, QueuedMailDelivery, \
+ QueueProcessorThread
from interfaces import IMailHost
+queue_threads = {}
+
class MailHostError(Exception):
pass
@@ -64,6 +68,8 @@
security = ClassSecurityInfo()
smtp_uid='' # Class attributes for smooth upgrades
smtp_pwd=''
+ smtp_queue = False
+ smtp_queue_directory = '/tmp'
timeout=1.0
@@ -79,7 +85,7 @@
def __init__( self, id='', title='', smtp_host='localhost', smtp_port=25,
- smtp_uid='', smtp_pwd=''):
+ smtp_uid='', smtp_pwd='', smtp_queue=False, smtp_queue_directory='/tmp'):
"""Initialize a new MailHost instance """
self.id = id
self.title = title
@@ -87,6 +93,8 @@
self.smtp_port = int(smtp_port)
self.smtp_uid = smtp_uid
self.smtp_pwd = smtp_pwd
+ self.smtp_queue = smtp_queue
+ self.smtp_queue_directory = smtp_queue_directory
# staying for now... (backwards compatibility)
@@ -95,7 +103,9 @@
self.smtp_port=smtp_port
security.declareProtected(change_configuration, 'manage_makeChanges')
- def manage_makeChanges(self,title,smtp_host,smtp_port,smtp_uid='',smtp_pwd='', REQUEST=None):
+ def manage_makeChanges(self,title,smtp_host,smtp_port,smtp_uid='',smtp_pwd='',
+ smtp_queue=False, smtp_queue_directory='/tmp',
+ REQUEST=None):
'make the changes'
title=str(title)
@@ -107,6 +117,17 @@
self.smtp_port=smtp_port
self.smtp_uid = smtp_uid
self.smtp_pwd = smtp_pwd
+ self.smtp_queue = smtp_queue
+ self.smtp_queue_directory = smtp_queue_directory
+
+ # restart queue processor thread
+ if self.smtp_queue:
+ self._stopQueueProcessorThread()
+ self._startQueueProcessorThread()
+ else:
+ self._stopQueueProcessorThread()
+
+
if REQUEST is not None:
msg = 'MailHost %s updated' % self.id
return self.manage_main( self
@@ -153,18 +174,56 @@
self._send( mfrom, mto, body )
+
+ def _makeMailer(self):
+ """ Create a SMTPMailer """
+ return SMTPMailer(self.smtp_host,
+ int(self.smtp_port),
+ self.smtp_uid or None,
+ self.smtp_pwd or None
+ )
+
+ def _stopQueueProcessorThread(self):
+ """ Stop thread for processing the mail queue """
+
+ path = self.absolute_url(1)
+ if queue_threads.has_key(path):
+ thread = queue_threads[path]
+ thread.stop()
+ while thread.isAlive():
+ # wait until thread is really dead
+ time.sleep(0.1)
+
+
+ def _startQueueProcessorThread(self):
+ """ Start thread for processing the mail queue """
+
+ path = self.absolute_url(1)
+
+ if not queue_threads.has_key(path):
+
+ thread = QueueProcessorThread()
+ thread.setMailer(self._makeMailer())
+ thread.setQueuePath(self.smtp_queue_directory)
+ thread.start()
+ queue_threads[path] = thread
+
+
security.declarePrivate('_send')
def _send(self, mfrom, mto, messageText):
""" Send the message """
- mailer = SMTPMailer(self.smtp_host,
- int(self.smtp_port),
- self.smtp_uid or None,
- self.smtp_pwd or None
- )
- delivery = DirectMailDelivery(mailer)
- delivery.send(mfrom, mto, messageText)
+ if self.smtp_queue:
+
+ # Start queue processor thread, if necessary
+ self._startQueueProcessorThread()
+ delivery = QueuedMailDelivery(self.smtp_queue_directory)
+ else:
+ delivery = DirectMailDelivery(self._makeMailer())
+
+ delivery.send(mfrom, mto, messageText)
+
InitializeClass(MailBase)
Modified: Zope/trunk/lib/python/Products/MailHost/dtml/manageMailHost.dtml
===================================================================
--- Zope/trunk/lib/python/Products/MailHost/dtml/manageMailHost.dtml 2007-08-19 07:24:24 UTC (rev 78982)
+++ Zope/trunk/lib/python/Products/MailHost/dtml/manageMailHost.dtml 2007-08-19 09:05:12 UTC (rev 78983)
@@ -51,7 +51,7 @@
<tr>
<td align="left" valign="top">
<div class="form-label">
- Authentication ID:
+ Username:
</div>
</td>
<td align="left" valign="top">
@@ -72,8 +72,31 @@
</tr>
<tr>
<td align="left" valign="top">
+ <div class="form-label">
+ Use queue
+ </div>
</td>
<td align="left" valign="top">
+ <input type="checkbox" name="smtp_queue:boolean" value="1"
+ <dtml-if "smtp_queue">checked</dtml-if>
+
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ Queue directory:
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="smtp_queue_directory" size="30"
+ value="&dtml-smtp_queue_directory;"/>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value="Save Changes" />
More information about the Zope-Checkins
mailing list