Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Alt Inbound Laravel Package

alt-design/alt-inbound

Alt Inbound is a Laravel package from Alt Design for handling inbound email in PHP applications. It provides a foundation for receiving and processing incoming messages, making it easier to build email-driven workflows with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

The addon is a Statamic IP-blocking layer: it lets you maintain deny/allow lists of addresses (and typically CIDR ranges) and rejects matching inbound requests before they reach your content pipeline.

  1. Install it

    composer require alt-design/alt-inbound
    

    Statamic 3/4/5 addons auto-register via package discovery, so no manual config/app.php edit is required. Confirm it appears under Tools → Addons in the Control Panel.

  2. Publish and read the config first

    php artisan vendor:publish --tag=alt-inbound-config
    

    Open config/alt-inbound.php. This is the single most important file to read — it typically holds the enable flag, the storage driver (config vs. database/CP-managed), the response behaviour for blocked requests, and list of trusted proxy headers. Because the package is small and low-adoption, treat the config comments and src/ as the real documentation.

  3. Look at these files in order

    • config/alt-inbound.php — the contract for behaviour
    • src/ServiceProvider.php — what middleware/tags/routes are registered and under what conditions
    • src/Http/Middleware/* — the actual blocking logic and where getClientIp() is called
    • routes/ and resources/views/ — any Control Panel screens for managing the list
  4. First use case: block one noisy scraper Add the offending IP to the blocklist (either in the config array or via the CP screen, depending on which driver you published), clear caches, then verify:

    php artisan config:clear && php artisan cache:clear
    curl -H "X-Forwarded-For: 203.0.113.5" https://your-site.test/
    

    You should get the configured block response (403, redirect, or a blank page) instead of your homepage. If you still get the homepage, jump to the Gotchas section — static caching is the usual culprit.

Implementation Patterns

Whitelist-first, always. Before adding any block rules, put your own IP, your office/VPN range, and your uptime monitor into the allow list. Most addons of this shape evaluate allow-then-deny; getting this order backwards once can lock you out of your own Control Panel.

Config-driven lists for infrastructure, CP-driven lists for incidents. Keep long-lived rules (known bot ASN ranges, staging IPs, abandoned client ranges) in version-controlled config. Use the Control Panel screen for short-lived incident response so you're not deploying a commit every time a scraper hits you.

Middleware placement matters. The addon's middleware should sit early in the web group — before session, cookies, and Statamic's route resolution — so blocked requests cost as little as possible. If it's registered only on the Statamic front-end routes, CP and asset routes are unaffected; that's usually what you want, but verify it, because a bot hammering /cp or /assets will bypass the block.

Programmatic blocking for application-level logic. Rather than only static lists, drive the list from your own code — e.g. an event listener on repeated failed form submissions, or a scheduled command that pulls a threat feed:

// Pseudo-shape; check the addon's actual repository/service binding.
app(\AltDesign\AltInbound\Blocklist::class)->add($ip, 'auto: failed login x10', now()->addDay());

Temporary/expiring entries are the pattern worth building around — permanent blocks accumulate silently and eventually catch real users on recycled ISP addresses.

Layer it with your edge. Treat this as application-layer blocking, not a replacement for Cloudflare/Fastly rules. The addon sees one request at a time and costs PHP; the edge costs nothing and drops traffic before it reaches your server. Use the edge for volumetric attacks, the addon for rules that need Statamic context (e.g. block an IP that keeps hitting a specific entry, or block based on an authenticated user's actions).

Make blocked responses observable. Whatever the addon logs, forward it somewhere durable — a dedicated log channel or your error tracker. Tag entries with the matched rule so you can tell "manual incident block" from "config rule" months later.

Test with header spoofing locally. Because you'll rarely have a "bad" IP on your dev machine, verify behaviour with X-Forwarded-For (or the header your config trusts) rather than editing your own machine's IP. This also proves your trusted-proxy configuration is correct — the single most common misconfiguration in this class of addon.

Gotchas and Tips

Trusted proxies will silently break everything. Laravel's TrustProxies middleware determines what $request->ip() returns. Behind Cloudflare, an ALB, or a load balancer, an untrusted setup makes every request look like it comes from the proxy IP — so blocking one IP blocks your entire site, and allow-listing your own IP does nothing. Set TrustProxies correctly and confirm which header the addon reads before you add a single rule.

Statamic static caching bypasses middleware. If you use the static cache (or a full-page CDN cache), blocked IPs can still be served the cached HTML for the TTL. The block only takes effect on cache misses. For a real block you need to either exclude blocked traffic at the edge or accept the cache-window delay — this is a genuine limitation, not a bug you can configure away.

Lockout risk is asymmetric. Blocking yourself out of the front end is annoying; blocking yourself out of /cp is an outage, and the only recovery is database/CLI access. Keep a php artisan alt-inbound:...-style escape hatch (or a config flag) documented and tested, and have the allow-list entry committed to config before you need it.

CIDR and IPv6 correctness. Hand-rolled range matching frequently mishandles IPv6 (compressed forms like ::1 vs 0:0:0:0:0:0:0:1) and off-by-one CIDR boundaries. Read the matcher in src/, and if it does naive str_starts_with on the IP string, do not use /8-style rules with it — 10.0.0.1 string-matches 10.0.0.10.

Config caching. Any change to config/alt-inbound.php requires php artisan config:clear (and a redeploy if config:cache runs in your pipeline). The classic symptom of forgetting this is "the rule is right there in the file but nothing is blocked."

Uninstalling leaves data behind. If the addon creates a table or publishes a config, composer remove won't clean it up. Note what it publishes at install time so you can reverse it deliberately.

Extension points are thin. With 3 stars and no dependents, expect no event system worth relying on. If you need custom decision logic, don't fight the config schema — write your own small middleware that consults your own blocklist service and leave this addon for the straightforward cases. Wrapping a tiny package rather than forking it keeps upgrades trivial.

Version-pin it. Last release dated 2026-10-26 with a near-zero user base means regressions won't be caught by anyone else. Pin to an exact version in composer.json and review the diff before bumping, especially around the trusted-proxy and client-IP code.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums