Modoboa 2.13.0 is available
Nov. 13, 2026 — Antoine Nguyen
Before you upgrade
Python 3.11 or later
Python 3.10 is no longer supported: it reached end of life, and dnspython 2.9.0 no longer supports it (#4355). Modoboa now requires Python 3.11 or later, so pip won't install 2.13.0 on Python 3.10. Upgrade Python and rebuild your virtualenv first.
Client address detection
Modoboa no longer trusts the X-Forwarded-For header by default, because clients can set it, and it does not depend on django-xforwardedfor-middleware anymore. If you upgrade with the installer, you have nothing to do.
Otherwise, this step is mandatory: without it, your instance won't start in a new virtualenv. In settings.py, replace x_forwarded_for.middleware.XForwardedForMiddleware in MIDDLEWARE with modoboa.lib.middleware.TrustedProxyMiddleware, and set NUM_PROXIES in REST_FRAMEWORK to the number of reverse proxies in front of Modoboa: 0 with uwsgi_pass, Apache mod_wsgi or a direct connection, 1 for nginx proxy_pass in front of gunicorn. python manage.py check reports the instances still to update (modoboa.core.W003). Then run pip uninstall django-xforwardedfor-middleware.
Other changes to know about
- Disabling an account now revokes its OAuth2 tokens. To also reject the tokens of an account disabled by other means, set OAUTH2_VALIDATOR_CLASS in OAUTH2_PROVIDER (modoboa.core.W004)
- Failed logins are rate limited, per client address and per username
- load_initial_data and modoboa-admin.py deploy now generate a random password for the initial administrator instead of admin:password. If your instance still uses this default password, change it
The upgrade guide has every detail.
Audit trail
The audit trail was rebuilt to answer a simple question: who did what, and when? Events are now structured and easier to read, filter and export.
- Structured events with an action catalog, and an audit signal plugins can use to record their own actions (#4384)
- Messages written in English, meaningful log levels and object names (#4385)
- More actions are recorded, and the details of each event are shown (#4386)
- Filters and ISO dates (#4387), and CSV export (#4389)
- Domain administrators get their own audit trail (#4388)
- Users can see the history of their logins (#4390)
Webmail
- Message tags (#4394)
- A new preference shows only subscribed folders (#4398)
- Fixes: the INBOX of a shared mailbox opens from its owner level (#4347), and a failed OAUTHBEARER authentication no longer waits for the IMAP timeout (#4357)
Administration
- A configurable banner can be shown at the bottom of every page (#4346)
- Plugins can lock fields of an account (#4348), on API v1 too (#4351)
- Lists get a responsive toolbar, and identities can be filtered by domain (#4376)
- The autoreply rule keeps its position in the Sieve script (#4409)
- Fixes: blank account detail view when no plugin tab is registered (#4352), frontend plugin translations are loaded (#4353), the news date shows on its own line in the dashboard widget (#4377), and malformed DMARC aggregate reports are skipped instead of crashing (#4411)
Security hardening
- OAuth2 tokens are revoked on password change (#4402)
- Password hashes are no longer kept in the revision history (#4383)
- The password reset of accounts with an unusable password is refused (#4350)
- The raw access token is read from the Authorization header (#4356), and the Sieve client rejects missing credentials (#4401)
- Frontend dependencies with security advisories are updated: undici (#4354), glob and minimatch (#4396)
Packaging and dependencies
Each release now ships a constraints.txt file that pins every dependency to the version tested with it (#4374). Use it when you install or rebuild a virtualenv: you get the exact set we tested, and no dependency upgrade sneaks in with its own migrations.
- django-oauth-toolkit is capped below 3.5 (#4366), and rq, django-rq and redis to their current major (#4373)
- Django 5.2.19 (#4404), dnspython 2.9.2 (#4355, #4403), django-phonenumber-field 9.0.0 (#4359), django-reversion 6.5.1 (#4363, #4399), plus frontend updates (#4361, #4362, #4368, #4369, #4370, #4371, #4372, #4378, #4379, #4380, #4381, #4382, #4400)
- Translations: French and Japanese are updated (#4358, #4407, #4408, #4410)
- Development: the documentation moves to a newer VitePress (#4405), tests are fixed and isolated (#4349, #4391, #4395), and the dependency update policy is tightened (#4367)
Thanks
Welcome to our new contributors Christophe-Aubert and dylanpulver, and thanks to kryskool for the documentation update!
Upgrade
After the version-specific steps above:
pip install -U modoboa==2.13.0 -c https://github.com/modoboa/modoboa/releases/download/2.13.0/constraints.txt
cd <modoboa_instance_dir>
python manage.py migrate
python manage.py collectstatic
python manage.py check --deploy
python manage.py load_initial_data
sudo systemctl restart uwsgi supervisor
Full changelog: 2.12.0...2.13.0