mrsleeps/vexim-web-plugin-rspamd-core
A Vexim web plugin that brings Rspamd core integration to Laravel/PHP applications, adding spam-filtering controls and configuration hooks to the Vexim admin interface for managing Rspamd settings from your web panel.
Before anything else, calibrate your expectations: this is not a Laravel package. There is no ServiceProvider, no publishable config, no facade, and no composer require workflow that drops into vendor/ and auto-boots. It is a plugin for Vexim, a legacy procedural-PHP mail administration tool, and it extends Vexim's Rspamd integration surface. Your job as a Laravel developer is usually to consume it (via HTTP/shell from your app) or to extend it (rare, and only if you're already running Vexim).
Where to look first:
config/ or plugin loader pulls in. That tells you which hooks are wired and what the plugin actually contributes (menus, routes, Rspamd API calls).rspamd/local.d/multimap.conf. Understand the file format before you trust anything.Your first real use case: a domain you control forwards mail through a relay, and legitimately-aligned mail is being scored as spam. The plugin lets you push whitelist entries from the mail-admin side rather than hand-editing Rspamd maps on every node. With v1.0.2 the plugin now recognises From addresses that pass DMARC verification — i.e. the From header is aligned with an authenticated domain — rather than only SPF- or IP-based signals. That is the correct bar for whitelisting a sender identity, and it's the reason to be on this version.
Minimum viable setup:
# 1. Pin the version you actually audited
composer require mrsleeps/vexim-web-plugin-rspamd-core:1.0.2
# 2. Confirm the plugin loads and the whitelist endpoint responds
rspamadm configtest
rspamadm control reload
Then add a single low-risk test sender, verify it appears in the Rspamd map, and confirm the map is actually read by the running worker (rspamc stat / rspamadm configdump).
Bridge it into Laravel as a service, not a dependency. Keep the plugin in Vexim's world and give your Laravel app a thin client:
// config/services.php
'rspamd' => [
'endpoint' => env('RSPAMD_CONTROLLER_URL'),
'password' => env('RSPAMD_CONTROLLER_PASSWORD'),
'timeout' => 5,
],
Wrap whitelist mutations in a single WhitelistClient class with add(string $fromDomain), remove(string $fromDomain), list(). Every caller goes through it, so when the plugin's API shape shifts you patch one file.
Push from a queued job, not the request cycle. Whitelist writes touch a file or an Rspamd controller endpoint that may need a reload. Doing this synchronously in a web request will stall on Rspamd latency and give you flaky UX:
class SyncRspamdWhitelist implements ShouldQueue
{
public function handle(WhitelistClient $whitelist): void
{
foreach (Domain::where('whitelist_rspamd', true)->cursor() as $domain) {
$whitelist->add($domain->name);
}
}
}
Make it idempotent and authoritative. Whitelists rot. The clean pattern is: your database is the source of truth, the Rspamd map is a projection. Recompute the full desired set on a schedule and diff against list() rather than appending blindly. This also protects you from duplicate entries after a failed mid-run.
Gate the DMARC behaviour behind your own policy flag. v1.0.2 changes which senders qualify for whitelisting. If you have forwarding domains where DMARC legitimately fails (no alignment, mailing lists that mangle From), the new rule will silently stop whitelisting them. Encode the intent in your own model (whitelist_mode: dmarc_aligned | legacy) so the upgrade doesn't quietly change deliverability for a subset of your domains.
Pair it with observability. Log every add/remove with the reason (dmarc_pass, manual, import). When someone asks "why did mail from X get through/blocked," you want an answer that isn't "go read the Rspamd log from Tuesday."
1.0.1 → 1.0.2 as a no-op.rspamadm control reload. If "it didn't work" — check rspamc stat for the map's last reload time before you debug your code.trigger_error, or silent failure). Always wrap calls and assert post-conditions — re-read the map after a write instead of assuming success.composer.json ("1.0.2", not "^1.0"). A patch-level release here altered whitelist semantics; you do not want that arriving unreviewed via composer update.rspamadm configtest for config validity, rspamadm configdump to see the effective multimap, rspamc stat for map state, and the Rspamd log for map read failures. The plugin's own logs rarely tell you the truth about whether the whitelist took effect.How can I help you explore Laravel packages today?