texxarulez / mailman_integration
Roundcube plugin for Mailman 3 list browsing and member actions
Package info
github.com/texxasrulez/mailman_integration
Type:roundcube-plugin
pkg:composer/texxarulez/mailman_integration
Requires
- php: >=7.4
- roundcube/plugin-installer: ~0.3.5
README
mailman_integration is a Roundcube plugin that exposes a small, admin-friendly Mailman 3 feature set inside Roundcube. It focuses on list discovery for the logged-in user, optional directory browsing, safe list metadata, simple member actions, and conservative outbound list headers.
v1 scope
Included in v1:
- plugin bootstrap, task registration, and native Roundcube rendering
- Mailman 3 REST API access from PHP only
- degraded mode when Mailman is missing, unreachable, or misconfigured
- "My Lists" view based on the active Roundcube identity
- optional browseable directory of lists
- subscribe and unsubscribe actions when enabled by config
- basic list detail view
- compose-time recognition of known list recipients
- outbound
List-*headers only when the message targets one recognized Mailman list
Intentionally excluded from v1:
- moderation queue handling
- owner or site-admin controls
- full Postorius replacement
- deep member preference management
- bounce and delivery diagnostics
- local database storage
Requirements
- Roundcube 1.5 or later
- PHP 7.4 or later
- Mailman 3 with the REST API enabled and reachable from the web server
Installation
Via Composer (recommended)
composer require texxasrulez/mailman_integration
Then add mailman_integration to the plugins array in Roundcube's config/config.inc.php.
Manual
-
Download or clone this repository into Roundcube's
plugins/mailman_integration/directory. -
Copy
config.inc.php.disttoconfig.inc.php:cp plugins/mailman_integration/config.inc.php.dist plugins/mailman_integration/config.inc.php
-
Edit
config.inc.phpand set at minimum the API URL and credentials (see Configuration). -
Add
mailman_integrationto thepluginsarray in Roundcube'sconfig/config.inc.php:$config['plugins'] = ['mailman_integration', /* other plugins */];
-
Clear Roundcube caches if your deployment caches templates or plugin metadata.
Configuration
Copy config.inc.php.dist to config.inc.php in the plugin directory to get started. All settings have safe defaults except the API connection options, which must be set for the plugin to function.
API connection
| Setting | Default | Description |
|---|---|---|
mailman_integration_enabled |
true |
Master on/off switch |
mailman_integration_api_url |
— | Mailman REST base URL, e.g. https://lists.example.com/3.1 |
mailman_integration_api_user |
— | REST API username (set in mailman.cfg) |
mailman_integration_api_password |
— | REST API password |
mailman_integration_timeout |
8 |
API request timeout in seconds |
mailman_integration_tls_verify |
true |
Verify TLS certificates; disable only for internal deployments |
mailman_integration_postorius_url |
'' |
Optional Postorius URL used to link the word Mailman in the health status line |
mailman_integration_health_path |
/system |
Path used to probe Mailman health |
mailman_integration_health_fallback_path |
/lists |
Fallback probe path if the primary returns an error |
List visibility
| Setting | Default | Description |
|---|---|---|
mailman_integration_show_directory |
false |
Show a browseable directory of all advertised lists |
mailman_integration_allow_subscribe |
false |
Enable subscribe actions for users |
mailman_integration_allow_unsubscribe |
true |
Enable unsubscribe actions for users |
mailman_integration_show_archives |
false |
Show archive links when Mailman provides a URL |
mailman_integration_show_list_settings |
false |
Show extra list metadata (volume, member count, etc.) |
mailman_integration_allowed_lists |
[] |
If non-empty, only these list IDs are shown |
mailman_integration_blocked_lists |
[] |
List IDs to always hide |
mailman_integration_exposed_domains |
[] |
If non-empty, only lists hosted on these domains are shown |
Compose settings
| Setting | Default | Description |
|---|---|---|
mailman_integration_compose_detection |
true |
Detect list recipients while composing |
mailman_integration_compose_widget |
true |
Inject the list info widget into the compose page |
mailman_integration_owner_tools |
true |
Show owner send options when a list address is in recipients |
mailman_integration_preflight_require_subject |
true |
Block sending to a list when the subject line is empty |
mailman_integration_preflight_confirm_send |
true |
Prompt for confirmation before sending to a list |
mailman_integration_preflight_append_unsubscribe_footer |
false |
Append an unsubscribe footer when the owner enables it |
mailman_integration_unsubscribe_footer_template |
see dist | Footer template; supports {list_address} placeholder |
mailman_integration_allow_identity_aliases |
false |
When true, all identity addresses are checked for membership, not just the primary |
Outbound headers
| Setting | Default | Description |
|---|---|---|
mailman_integration_add_list_headers |
true |
Inject List-* headers when sending to exactly one recognized list |
mailman_integration_add_list_unsubscribe |
true |
Include List-Unsubscribe in injected headers |
Message templates
Pre-fill subject and body when composing to a list. Defined as an array in config.inc.php:
$config['mailman_integration_message_templates'] = [ ['name' => 'Announcement', 'subject' => 'Announcement', 'body' => "Dear subscribers,\n\n"], ['name' => 'Newsletter', 'subject' => 'Monthly Newsletter', 'body' => "Hello everyone,\n\n"], ];
Leave the array empty (the default) to hide the template picker.
Diagnostics
| Setting | Default | Description |
|---|---|---|
mailman_integration_cache_ttl |
120 |
Seconds to cache list and health data |
mailman_integration_log_level |
warning |
Log verbosity: debug, info, warning, error |
mailman_integration_debug |
false |
Write detailed debug entries to logs/mailman_integration |
Usage
Accessing the Mailman task
After installation the Mailman icon appears in the Roundcube taskbar. Click it to open the Mailman Lists page.
My Lists
The left panel lists every Mailman list the logged-in user is subscribed to (matched against the active Roundcube identity). Selecting a list loads its detail view on the right, showing the list address, description, and available actions.
Directory
When mailman_integration_show_directory is true, all publicly advertised lists appear in a second panel below My Lists. Users can browse and, if subscribe actions are enabled, join lists from this view.
Subscribe / Unsubscribe
Subscribe and unsubscribe buttons appear in the list detail view when the corresponding config options are enabled (mailman_integration_allow_subscribe, mailman_integration_allow_unsubscribe). Actions are confirmed via a page-level flash message.
Compose integration
When composing a message, the plugin checks the To, Cc, and Bcc fields against known list addresses. If a match is found:
- A widget appears below the header area showing the matched list name and address.
- If
mailman_integration_owner_toolsis enabled and the user is a list owner, additional send options appear inline:- Require subject — blocks send if the subject line is empty.
- Confirm before send — shows a confirmation prompt before submitting.
- Append unsubscribe footer — appends the configured footer template to the message body.
Disable the widget entirely with mailman_integration_compose_widget = false while keeping outbound header injection active.
Send to List
From a list detail page, click Send to List to open a compose window pre-addressed to the list. If message templates are configured, a template picker appears next to the send button to pre-fill subject and body.
Skin support
The plugin ships explicit support for:
elasticlarryautumn_larryblack_larryblue_larrygreen_larrygrey_larrypink_larryplata_larrysummer_larryteal_larryviolet_larryclassic
The Larry color variants are created as real skin directories and mirror the Larry templates, styles, and image assets so Roundcube can resolve them without broken paths.
Mailman failure handling
If Mailman is absent, unreachable, or misconfigured:
- the plugin stays loaded
- the lists page renders a degraded status message
- write actions are suppressed
- transport details are not leaked into the UI
Outbound header behavior
The plugin only adds list-style outbound headers when it can match the outgoing recipients to exactly one recognized Mailman list address. It does not add list headers to ordinary mail, and it does not guess when the target is ambiguous.
Headers currently added when configured and available:
List-IdX-BeenThereList-UnsubscribeList-Archive
Roundcube version notes
The plugin follows common Roundcube plugin patterns, but hook payload details can differ slightly between Roundcube releases. The message-send hooks and compose-header injection are the most likely places to need small adjustments on older or customized installations.
Compatibility troubleshooting
If compose loads with disabled toolbar actions (Send, Save, Cancel) or the browser console shows $ is not a function, the issue is almost always a JavaScript conflict from another plugin overriding the global jQuery symbol.
Suggested triage order:
- Temporarily disable third-party compose-related plugins.
- Hard-refresh Roundcube and verify core compose works from the native
New messageaction. - Re-enable plugins one by one until the conflict reappears.
- If needed, keep Mailman compose recognition active but disable widget injection by setting
mailman_integration_compose_widgettofalse.
Known real-world conflict observed during testing:
markdown_editor(caused global jQuery collisions and blocked compose initialization)
Smoke test checklist
Run this quick check after upgrades or plugin changes:
- Open Mailman task and verify list/taskbar icon visibility for your active skin.
- Open a list detail page and click
Send to List(owner role). - Confirm compose opens with recipient prefilled and toolbar actions enabled.
- Send a test message to one list and confirm no send-time server error.
- Inspect received message headers and verify
List-IdandX-BeenThereare present. - If
mailman_integration_show_archivesis enabled, verifyList-Archiveis present.
Translation workflow
This repository includes translate_locales.php to update all locale files in one batch with safer handling for placeholders and markup.
Recommended run with DeepL and Libre fallback:
php translate_locales.php \ --provider=deepl \ --deepl-key=YOUR_DEEPL_KEY \ --deepl-plan=free \ --fallback-provider=libre \ --lt-url=http://localhost:5000
Useful flags:
--force=1: re-translate all keys, not just missing/empty ones--dry-run=1: simulate translation without writing files--locales=es_ES,fr_FR,de_DE: process only selected locales--exclude-locales=ja_JP,zh_TW: skip specific locales--report=localization/mt_report.json: custom report path
Behavior notes:
- English variants (
en_*) are copied from source text by design. - Unsupported locales for the primary provider are captured in the report and can be handled by fallback provider.
- Placeholder tokens and simple markup are masked before translation and restored after translation.
Versioning
mailman_integrationnow keeps its canonical version inmailman_integration::PLUGIN_VERSIONinsidemailman_integration.php.mailman_integration::info()exposes the plugin metadata array used for self-identification.- Development builds should use a
+devsuffix such as1.0.0+dev. - Release builds should use a clean tagged version such as
1.0.0.
For a release bump:
- Update
mailman_integration::PLUGIN_VERSIONinmailman_integration.phpor runsh scripts/bump-version.sh 1.0.0. - Update
CHANGELOG.md. - Create the matching release tag after verification.