When a mail is not immediately sent, it is sent at the end of the transaction. When some code calls transaction.savepoint, this fails with a traceback, because our MailDataManager has no savepoint.
What I did:
I have a PR ready with a fix, and a testcase that fails without the fix. Simplified from the test, here is some code that would fail:
My real use case is much harder to reproduce, and requires Plone knowledge:
Plone 5.2.2 site, Python 3.
Add a content rule that triggers when a document changes.
Give this a mailer action.
The default Plone mailer action seems to call send with immediate=True, which does not trigger any error. So either hack this to use immediate=False or write your own mailer action.
Activate this rule on a document.
Go to the history tab, which is backed by CMFEditions.
Choose to revert to a previous version of this document.
What I expect to happen:
A mail is sent, because the content rule and mail action are triggered.
What actually happened:
I get a traceback, because CMFEditions needs to call transaction.savepoint in order to work:
Traceback (innermost last):
Module ZPublisher.WSGIPublisher, line 162, in transaction_pubevents
Module ZPublisher.WSGIPublisher, line 359, in publish_module
Module ZPublisher.WSGIPublisher, line 254, in publish
Module ZPublisher.mapply, line 85, in mapply
Module ZPublisher.WSGIPublisher, line 63, in call_object
Module Products.CMFCore.FSPythonScript, line 133, in __call__
Module Shared.DC.Scripts.Bindings, line 335, in __call__
Module Shared.DC.Scripts.Bindings, line 372, in _bindAndExec
Module Products.PythonScripts.PythonScript, line 351, in _exec
Module script, line 26, in revertversion
<FSPythonScript at /plone_portal/.../revertversion>
Line 26
Module Products.CMFEditions.CopyModifyMergeRepositoryTool, line 332, in save
Module ugent.patches.products_cmfeditions, line 9, in _recursiveSave
Module Products.CMFEditions.ArchivistTool, line 267, in prepare
Module Products.CMFEditions.ModifierRegistryTool, line 135, in getReferencedAttributes
Module plone.app.versioningbehavior.modifiers, line 117, in getReferencedAttributes
Module Products.CMFEditions.CopyModifyMergeRepositoryTool, line 410, in retrieve
Module Products.CMFEditions.CopyModifyMergeRepositoryTool, line 557, in _retrieve
Module transaction._manager, line 272, in savepoint
Module transaction._manager, line 151, in savepoint
Module transaction._transaction, line 227, in savepoint
Module transaction._transaction, line 316, in _saveAndRaiseCommitishError
Module transaction._compat, line 45, in reraise
Module transaction._transaction, line 224, in savepoint
Module transaction._transaction, line 634, in __init__
TypeError: ('Savepoints unsupported', <zope.sendmail.delivery.MailDataManager object at 0x7fb19e8b3c10>)
Or in the testcase:
Error in test testSavepoint (zope.sendmail.tests.test_delivery.TestDirectMailDelivery)
Traceback (most recent call last):
File "/Users/maurits/.pyenv/versions/2.7.17/lib/python2.7/unittest/case.py", line 329, in run
testMethod()
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/zope/sendmail/tests/test_delivery.py", line 286, in testSavepoint
transaction.savepoint()
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/transaction/_manager.py", line 272, in savepoint
return self.manager.savepoint(optimistic)
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/transaction/_manager.py", line 150, in savepoint
return self.get().savepoint(optimistic)
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/transaction/_transaction.py", line 228, in savepoint
self._saveAndRaiseCommitishError() # reraises!
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/transaction/_transaction.py", line 316, in _saveAndRaiseCommitishError
reraise(t, v, tb)
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/transaction/_transaction.py", line 225, in savepoint
savepoint = Savepoint(self, optimistic, *self._resources)
File "/Users/maurits/community/plone-coredev/py3/src/zope.sendmail/.tox/py27/lib/python2.7/site-packages/transaction/_transaction.py", line 623, in __init__
raise TypeError("Savepoints unsupported", datamanager)
TypeError: ('Savepoints unsupported', <zope.sendmail.delivery.MailDataManager object at 0x109044810>)
What version of Python and Zope/Addons I am using:
Plone 5.2.2, Zope 4.5.1, both Python 2 and 3, zope.sendmail 5.1.
As said, I have a branch ready with a fix. This adds a savepoint implementation that basically does nothing. I took the code from a comment on aplone.namedfile branch with a similar error.
Alternatively, I wonder if it might be possible to add proper support. At least I can imagine this scenario in one transaction:
Do stuff
Package X creates savepoint A
Send mail A
Unrelated stuff in package X goes wrong.
Package X does a rollback to savepoint A and tries something else.
Send mail B.
Unrelated stuff now goes right.
Transaction commit.
In this case, only mail B should be sent. I have not tried this scenario, but I guess currently both mail A and B would be sent.
But this seems much more difficult than the simple fix I have ready, so I will just push that branch.
BUG/PROBLEM REPORT (OR OTHER COMMON ISSUE)
When a mail is not immediately sent, it is sent at the end of the transaction. When some code calls
transaction.savepoint
, this fails with a traceback, because ourMailDataManager
has nosavepoint
.What I did:
I have a PR ready with a fix, and a testcase that fails without the fix. Simplified from the test, here is some code that would fail:
My real use case is much harder to reproduce, and requires Plone knowledge:
send
withimmediate=True
, which does not trigger any error. So either hack this to useimmediate=False
or write your own mailer action.What I expect to happen:
A mail is sent, because the content rule and mail action are triggered.
What actually happened:
I get a traceback, because CMFEditions needs to call
transaction.savepoint
in order to work:Or in the testcase:
What version of Python and Zope/Addons I am using:
Plone 5.2.2, Zope 4.5.1, both Python 2 and 3, zope.sendmail 5.1.
As said, I have a branch ready with a fix. This adds a savepoint implementation that basically does nothing. I took the code from a comment on a
plone.namedfile
branch with a similar error.Alternatively, I wonder if it might be possible to add proper support. At least I can imagine this scenario in one transaction:
In this case, only mail B should be sent. I have not tried this scenario, but I guess currently both mail A and B would be sent.
But this seems much more difficult than the simple fix I have ready, so I will just push that branch.