Hi all, I was surprised by the behavior of asynchronous mailing in zope 2.11.3 MailHost product. It creates a thread by instance of MailHost by the mean of using self.absolute_url(1) as key for the queue_threads dictionnary.
It seems obviously wrong, IMO, if several instances share the same queue directory, mesages actually get sent more than once. Following is the monkey patch which works fine for me, but the idea is straightforward, it's to use the realpath of the smtp_queue_directory as the identifier of the thread, ensuring that MailHosts that share the same queue directory will also share the same thread for processing mails. regards, # un monkey patch du mailhost de zope2.11, ce dernier utilise une thread # par instance de mailhost pour la getsion de la queue de messages, ce n'est # pas correct, il faut qu'il garantisse qu'il n'y a qu'une thread par # répertoire réel de queue. from Products.MailHost import MailHost as mh if not hasattr(mh.MailBase, '_cfenet_patched_queueThreadAlive'): mh.MailBase._cfenet_patched_queueThreadAlive = mh.MailBase.queueThreadAlive def queueThreadAlive(self): """return True/False is queue thread is working""" from Products.MailHost import MailHost as mh from os.path import realpath # Il est important d'avoir un mailer unique par répertoire th = mh.queue_threads.get(realpath(self.smtp_queue_directory)) return th and th.isAlive() mh.MailBase.queueThreadAlive = queueThreadAlive if not hasattr(mh.MailBase, '_cfenet_patched__stopQueueProcessorThread'): mh.MailBase._cfenet_patched__stopQueueProcessorThread = \ mh.MailBase._stopQueueProcessorThread @mh.synchronized(mh.MailBase.lock) def _stopQueueProcessorThread(self): """ Stop thread for processing the mail queue """ from Products.MailHost import MailHost as mh from os.path import realpath path = realpath(self.smtp_queue_directory) if mh.queue_threads.has_key(path): th = mh.queue_threads[path] th.stop() while th.isAlive(): # wait until thread is really dead mh.time.sleep(0.3) del mh.queue_threads[path] mh.LOG.info('Thread for %s stopped' % path) mh.MailBase._stopQueueProcessorThread = _stopQueueProcessorThread if not hasattr(mh.MailBase, '_cfenet_patched__startQueueProcessorThread'): mh.MailBase._cfenet_patched__startQueueProcessorThread = \ mh.MailBase._startQueueProcessorThread @mh.synchronized(mh.MailBase.lock) def _startQueueProcessorThread(self): """ Start thread for processing the mail queue """ from Products.MailHost import MailHost as mh from os.path import realpath path = realpath(self.smtp_queue_directory) if not mh.queue_threads.has_key(path): th = mh.QueueProcessorThread() th.setMailer(self._makeMailer()) th.setQueuePath(self.smtp_queue_directory) th.start() mh.queue_threads[path] = th mh.LOG.info('Thread for %s started' % path) mh.MailBase._startQueueProcessorThread = _startQueueProcessorThread -- _____________ Maric Michaud _______________________________________________ Zope maillist - Zope@zope.org https://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope-dev )