Skip to main content

Introduction

collective.MockMailHost enables integration testing of email functionality from Plone. Simply add this egg to your [test] runner section, and install this product through your Layer or TestCase.

Note

THIS IS FOR TESTING PURPOSE ONLY, do not use this product on your running Plone site. It replaces the standard MailHost with a Mock MailHost that you can poke at to check email content and recipients.

Has been tested with Plone 4 but should also work with earlier versions.

Integration

Example how to integrate collective.MockMailHost to your testing setup based on plone.app.testing. Add the package to your extras_requires section in your package’s setup.py file, so buildout will automatically download the package for you.:

setup(name='my.package',
      ...
      extras_require={
        'test': [
            'plone.app.testing',
            'collective.MockMailHost',
        ]
      },
      ...
      )

Your test layer setup could look like this example below:

from plone.app.testing import helpers, layers
from plone.testing import z2


class MyLayer(helpers.PloneSandboxLayer):
    defaultBases = (layers.PLONE_FIXTURE, )

    def setUpZope(self, app, configurationContext):
        # Load zcml
        import collective.MockMailHost
        self.loadZCML(package=collective.MockMailHost)

        # Install product and call its initialize() function
        z2.installProduct(app, 'collective.MockMailHost')

        # Note: you can skip this if my.product is not a Zope 2-style
        # product, i.e. it is not in the Products.* namespace and it
        # does not have a <five:registerPackage /> directive in its
        # configure.zcml.

    def tearDownZope(self, app):
        # Uninstall product
        z2.uninstallProduct(app, 'collective.MockMailHost')

        # Note: Again, you can skip this if my.product is not a Zope 2-
        # style product

    def setUpPloneSite(self, portal):
        helpers.quickInstallProduct(portal, 'collective.MockMailHost')

        helpers.applyProfile(portal, 'collective.MockMailHost:default')

MY_FIXTURE = MyLayer()

Using a member-posting forum

>>> from Products.CMFCore.utils import getToolByName
>>> from Products.MailHost.interfaces import IMailHost
>>> from zope.component import getUtility
>>> app = layer['app']
>>> portal = layer['portal']

Test starting conversations, replying and modifying comments in a default member-posting forum.

Let us log all exceptions, which is useful for debugging. Also, clear portlet slots, to make the test browser less confused by things like the recent portlet and the navtree.

>>> portal.error_log._ignored_exceptions = ()
>>> portal.left_slots = portal.right_slots = []
>>> workflow = portal.portal_workflow

Validate mailhost replacement

>>> portal.MailHost
<collective.MockMailHost.MockMailHost.MockMailHost object at ...>
>>> getToolByName(portal, 'MailHost')
<collective.MockMailHost.MockMailHost.MockMailHost object at ...>
>>> getUtility(IMailHost)
<collective.MockMailHost.MockMailHost.MockMailHost object at ...>

Send email

>>> to_ = "member@example.com"
>>> from_ = "admin@example.com"
>>> msg = """
...
... Dear Sir:
...
... Thank you"""
>>> portal.MailHost.send(msg, to_, from_)
>>> len(portal.MailHost.messages)
1
>>> b'To: member@example.com' in portal.MailHost.messages[0]
True
>>> b'From: admin@example.com' in portal.MailHost.messages[0]
True
>>> b'Dear Sir:' in portal.MailHost.messages[0]
True
>>> portal.MailHost.messages_from
['admin@example.com']
>>> portal.MailHost.messages_to
[['member@example.com']]
>>> portal.MailHost.reset()
>>> len(portal.MailHost.messages)
0

Send an email.message.EmailMessage object with cc/bcc recipients

>>> from email.message import EmailMessage
>>> msg = EmailMessage()
>>> msg["Subject"] = "Hello"
>>> msg["From"] = "me@example.com"
>>> msg["To"] = "you@example.com"
>>> msg["Cc"] = "foo@example.com"
>>> msg["Bcc"] = "bar@example.com"
>>> msg.set_content("""
... This message is for you, foo, and bar.
... """)
>>> portal.MailHost.send(msg)
>>> len(portal.MailHost.messages)
1
>>> b'To: you@example.com' in portal.MailHost.messages[0]
True
>>> b'From: me@example.com' in portal.MailHost.messages[0]
True
>>> b'Cc: foo@example.com' in portal.MailHost.messages[0]
True
>>> b'bar@example.com' in portal.MailHost.messages[0]
False
>>> b'This message is for you, foo, and bar.' in portal.MailHost.messages[0]
True
>>> len(portal.MailHost.messages)
1
>>> portal.MailHost.messages_from
['me@example.com']
>>> portal.MailHost.messages_to
[['you@example.com', 'foo@example.com', 'bar@example.com']]
>>> portal.MailHost.reset()
>>> len(portal.MailHost.messages)
0

4.0.0 (2026-05-18)

Internal:

  • Make final release, no further changes.

4.0.0a1 (2025-12-09)

Breaking changes:

  • Replace pkg_resources namespace with PEP 420 native namespace. Support only Plone 6.2 and Python 3.10+. Configure with plone.meta. Switch to src-layout. (#3928)

Changelog

3.0.1 (unreleased)

  • Nothing changed yet.

3.0.0 (2024-04-23)

Breaking changes:

  • Remove support for Python versions prior to 3.7 and Plone versions prior to 5.2. [mamico]

New features:

  • Add messages_from, and messages_to to record senders and recipients. This is useful for testing bcc that is not present in the message. [mamico]

2.0.0 (2018-11-06)

Breaking changes:

  • Do not depend on old SecureMailHost any longer. [pbauer]

New features:

  • Python 3 support. [pbauer]

1.1.0 (2018-06-27)

  • Fix import location, Globals has been removed. [gforcada]

  • Rework tests setup. [gforcada]

1.0 (2016-01-25)

  • Fix MIMEText compatibility (broken since 0.9). [jone]

0.9 (2015-07-10)

  • Clean up msg before sending. Otherwise Plone self registration email does not work [sureshvv]

0.8 (2015-06-13)

  • Add browser view for functional testing [Casecarsid]

0.7 (2013-07-05)

  • MANIFEST [sureshvv]

0.6 (2013-07-03)

  • Track msg_type also. [sureshvv]

  • Behave more like collective.testcaselayer’s MockMailHost. [saily]

  • Documentation updates [saily]

0.5 - 2012-09-25

  • Remove ZopeSkel and Paster dependency from setup.py [saily]

  • Moved to github and changed to README.rst, links in setup.py [saily]

  • Allow multiple parameters for send and secureSend method in MockMailHost class. [saily]

0.4 (2011-05-17)

  • Register MockMailHost in SiteManager to get MockMailHost when using getToolByName(context, 'MailHost') or getUtility(IMailHost). [saily]

  • Inherit from MailHost instead of SimpleItem [saily]

  • Implement the secureSend method [saily]

0.3 (2011-04-04)

  • Add **kwargs to MockMailHost’s send method to support mto, mfrom, … keyword arguments as default MailHost does. [saily]

  • Added file for generic setup various handlers [sureshvv]

0.2 (2010-05-21)

  • Added tests [sureshvv]

0.1 (2010-05-16)

  • Initial release [sureshvv]

Release files for collective.MockMailHost 4.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for collective.MockMailHost 4.0.0
File Size Uploaded
collective_mockmailhost-4.0.0.tar.gz 23.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for collective.MockMailHost 4.0.0
File Interpreter ABI Platform
collective_mockmailhost-4.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 35.1 kB

Release files / collective_mockmailhost-4.0.0.tar.gz

Download URL collective_mockmailhost-4.0.0.tar.gz
Size 23.1 kB
Tags Source
SHA-256 checksum
How to use checksums
aebe8652ed57bfbf57aac589c9c4b20941625fb27b70217f156b45395147c3f9
BLAKE2b-256 checksum
How to use checksums
2a2d4f0b51f9859cbba26e7487cd302d3fd04b07cd8fcbd7d0d77f4a076846a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / collective_mockmailhost-4.0.0-py3-none-any.whl

Download URL collective_mockmailhost-4.0.0-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ea857d1859ebb700b22fc5a4003529533c5121b66d153a96c703ab3580618fba
BLAKE2b-256 checksum
How to use checksums
8702696f8aec32c3402ca161fd58b67fe78ddd5e8abed5880b40b9a494e50d12
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release history Release notifications | RSS feed

This release

4.0.0 This release

2 release files

3.0.0

2 release files

2.0.0

2 release files

1.1.0

2 release files

1.0

1 release file

0.9

1 release file

0.8

1 release file

0.7

1 release file

0.6

1 release file

0.5

1 release file

0.4

1 release file

0.3

1 release file

0.2

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page