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

Contact Laravel Package

graham-campbell/contact

A Laravel package for adding a contact form and managing submitted enquiries. It provides the model, migrations, validation, and email notifications needed to capture and store contact messages in your application.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. graham-campbell/contact is a single-purpose Laravel 5 package that wires four things together: a route pair (show form / accept POST), a controller with hardcoded validation (name, email, message), a Blade view, and a synchronous Mail::send to a configured recipient. There is no domain layer, no persistence, no events, no contracts, and no repository interface. For a TPM this matters less as a code-quality critique and more as an ownership statement: the package is a pre-built controller plus a form, not a platform component. It fits only where the requirement is literally "accept a message and email it to an address" — marketing landing pages, support inboxes, internal notification forms. It fits nowhere the requirement involves routing rules, ticketing/CRM handoff, audit trails, PII retention policy, or multi-tenant recipient logic.

Integration feasibility. Mechanically trivial if and only if the framework gate passes. composer require resolves only against illuminate/* 5.x; on Laravel 6+ the constraint conflicts and forcing it with --ignore-platform-reqs or aliasing produces runtime breakage in container bindings and mail/event signatures — the expensive, hard-to-diagnose kind. On a genuine 5.x app the integration is: register ContactServiceProvider in config/app.php (no auto-discovery before 5.5), vendor:publish, set a recipient, set MAIL_DRIVER=log, submit the form, confirm in storage/logs/laravel.log. A one-hour spike validates provider registration, routing, view resolution, and mail config simultaneously. That is the acceptance test for the feasibility question, and it should be run before any planning commitment is made.

Technical risk. Ranked by what actually hurts:

Risk Severity Why
Laravel 5 EOL (both the app and the package) High Security patching is your problem, not the maintainer's. The framework line itself is unsupported.
No extension points Medium-High No events, no contracts, no bindables. Any customisation means binding your own controller, editing a fork, or both. The dependency leaks into application code by default.
No rate limiting / no honeypot / no bot mitigation Medium-High Public form = abuse vector on day one. This is your requirement to add, not a package feature.
Synchronous Mail::send Medium Request latency tracks SMTP round-trip; a slow or failing mailer degrades the user-facing response path.
Silent delivery failure Medium Submitter sees the success redirect whether or not mail left the building. Lost inquiries surface as customer complaints weeks later.
Header injection via subject/Reply-To Medium User input into headers without strict validation turns the form into an open relay and a domain-reputation incident.
Zero stars, zero dependents, no evident CI or disclosure channel Medium This is vendoring with extra steps. Score 0.3 and zero dependents are the signal, not noise.

Key questions (answers close the evaluation, roughly in this order):

  1. What framework version is the host app on, exactly? Binary gate. composer why-not graham-campbell/contact settles it in minutes. Laravel 6+ → stop, extract requirements, build natively.
  2. Is a 1–3 day native build genuinely blocked, or just inconvenient? A FormRequest, a queued Mailable, a migration, and throttle:5,1 is the whole feature. The package saves hours, not weeks.
  3. Who owns this in twelve months? If the answer is "whoever's on call," the adoption decision is really a fork-and-maintain decision and must be resourced as such.
  4. Is there an existing contact route name or ContactController? Collisions either shadow yours or throw on duplicate route names depending on load order.
  5. What are the product's abuse, PII-retention, and deliverability requirements? None are in scope for the package; all become your tickets. Naming them now is the more valuable output than the adoption call.
  6. Do we need any behaviour beyond notify-one-address? If yes, the package is the wrong shape and the answer is native build.

Integration Approach

Stack fit. Narrow by design. It assumes Laravel 5.x, Blade, the framework's Mail facade, and the framework's translation system. It plays acceptably with a conventional Laravel app layout (config/, resources/views/vendor/, app/Http/Controllers/) and badly with anything that has its own abstraction over notifications, its own form-handling conventions, or a non-Laravel mail path. There is no adapter surface, so fit is evaluated once, at adoption, and does not improve.

Migration path. Two viable paths, and the choice should be made explicitly at adoption rather than discovered later:

  • Path A — thin embed (fastest, highest lock-in). Install, publish config and views, set CONTACT_RECIPIENT via .env, include the published partial in your layout. The package owns the route, controller, validation, and send. Ship in hours. Accepted debt: the package is on your request path with no seam.
  • Path B — isolated fork (recommended default). Publish routes and views, point the URI at a first-party ContactController extending the package controller (or replacing it), and put everything behind a first-party interface — ContactSender — so the dependency never appears in application code. Pin the fork by commit SHA in a private VCS. This is the only path that survives the eventual framework upgrade without a rewrite scramble, and it costs perhaps half a day more.

Whichever path is chosen, write the behavioural contract down: field names, validation rules, recipient resolution, subject/copy, success and failure UX, redirect target. That document is the artefact you reimplement natively later; it is also the acceptance criteria for the spike.

Compatibility. Three constraints to verify rather than assume:

  • Framework line. Laravel 5.x only. On 5.0–5.4 the provider must be registered manually. Confirm with php artisan route:list | grep -i contact after install.
  • Laravel 5.2+ for throttle middleware. Below that, a hand-rolled limiter. Verify before promising the abuse-control checkbox.
  • Config caching. php artisan config:cache freezes config/contact.php; subsequent .env changes silently do nothing until re-cache. This must be in the deploy runbook, not learned on staging.

Sequencing. Do not parallelise this; each step gates the next.

  1. Version gate (30 min) — composer why-not. Kill or continue.
  2. Spike (half day) — install on a branch, MAIL_DRIVER=log, one round-trip submission, confirm the log entry.
  3. Requirements gap list — abuse controls (throttle + honeypot + optional CAPTCHA), persistence (contact_messages for the silent-failure gap), queued send, deliverability (verified From: with SPF/DKIM on your own domain; submitter address in Reply-To only), retention policy. Size each. This list is usually larger than the adoption itself and belongs in the same estimate.
  4. Harden — queued Mailable replacing synchronous Mail::send; persistence write before dispatch; throttle:5,1; prohibited honeypot; header-injection defence by using ->replyTo($validatedEmail) rather than string-assembled headers.
  5. Test the three states — happy path (Mail::fake + assertSent), validation failure (assertSessionHasErrors), honeypot (assert no mail sent). Fifteen minutes of work that catches every future regression.
  6. Ship behind the first-party interface, publish config and views once, commit them, and never run vendor:publish --force in a loop.

Operational Impact

Maintenance. The honest framing is build for free, maintain forever. Zero stars, zero dependents, no visible CI, no disclosure channel means there is no upstream to depend on — you are the maintainer the moment it merges. Concrete tail: reading the source once at adoption (it is a few hundred lines; budget the afternoon), patching for any PHP or framework bump on the host app, and responding yourself to any security issue in the form path. Put this in capacity planning as a line item, not a footnote. The mitigating move is isolation behind ContactSender so the eventual native reimplementation is a swap, not an excavation.

Support. No vendor, no SLA, no issue-triage expectation. Internal support means whoever adopted it. Two mitigations that cost little: the behavioural contract document (so a second engineer can pick it up cold) and the three feature tests (so a future edit cannot silently break validation or the honeypot). Debugging order should be documented in the runbook because it is non-obvious and highly repeatable: route:list (routing) → config:clear (recipient/subject) → MAIL_DRIVER=log (isolate mailer from SMTP/DNS) → storage/logs/laravel.log (exceptions, including validation). Roughly ninety percent of "the form doesn't work" resolves in those four steps.

Scaling. Not a scaling concern in the throughput sense — a contact form is low-volume by nature, and the package imposes no meaningful per-request cost beyond one synchronous SMTP round-trip. Two scaling axes do matter:

  • Volume of abuse. Unthrottled, un-honeypotted, the form is a spam target and a reputation risk the first time it is discovered. throttle:5,1 plus a prohibited honeypot field is the floor; a public marketing page warrants a CAPTCHA behind a feature flag.
  • Operational visibility. There is no queue, no metrics, no delivery confirmation. If volume grows, moving to a queued Mailable is a two-line change in the forked controller and should be treated as the first hardening task, not a later optimisation.

Failure modes. Enumerate these in the runbook, because several are silent:

Failure Symptom Detection
Mail transport fails Submitter sees success redirect anyway None by default — requires logging send results or a contact_messages table
Cached config after deploy Recipient still the old address on staging config:clear / re-cache in deploy script
Route name or URI collision Form posts to the wrong place route:list at boot
Missing CSRF in a JS-injected modal 419 that reads like a validation error Keep csrf_field() inside the partial
Validation field rename Confusing "required" errors, not a crash Pin field names in the contract doc
Header injection via Reply-To Spam-folder delivery, domain-reputation damage Strict validation + ->replyTo() + newline stripping
Queued send exhausts retries Inquiries lost with no alert Failed-job alerting if you move to a queue

The single most important line in that table is the first: a contact form that only sends mail has no record when transport fails. Persisting to contact_messages before dispatch is the minimum-viable close of that gap and should be scoped as a required addition, not a nice-to-have.

Ramp-up. Low individual ramp, moderate organisational ramp. An engineer familiar with Laravel reads the source and ships in a day. The organisational cost is the framing: this must be recorded as adoption plus fork ownership, never as vendor selection, so the maintenance tail shows up in future capacity planning rather than as a surprise in someone's sprint. Realistic total for a competent team on a Laravel 5.x app: one day to adopt and spike, two to three days to harden (persistence, queue, throttle, honeypot, deliverability, three tests) — against a one-to-three day native build that you own outright with no fork tail. That comparison, not the package's feature list, is the decision worth putting in front of stakeholders.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console