Skip to content

Mailable

Mailable carries Domain data for a Laravel mail representation.

Generated facts

Layer
domain
Generated path
app/Pulsar/Domain/{Domain}/Mail/{Name}.php
Generator command
make:mailable
Workflow method
None
Stability
Current manifest surface (Pulsar 0.4.1)

Canonical example

Generated src/stubs/mailable.stub — canonical synchronized stub.

<?php

namespace {{namespace}};

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Mail\Mailable;

class {{name}} extends Mailable
{
    use Queueable;

    public function __construct(
        public readonly string $message,
    ) {
        // Carry DTOs or Value Objects when the mailable needs structured domain data.
    }

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: '{{name}}',
        );
    }

    public function content(): Content
    {
        return new Content(
            view: '{{view}}',
        );
    }

    /**
     * @return list<mixed>
     */
    public function attachments(): array
    {
        return [];
    }
}

Responsibility

Mailable owns the responsibility stated above; it must not absorb delivery, transaction, or unrelated cross-layer behavior.

Placement and dependencies

Keep this type in its generated Domain path. Domain is independent of delivery concerns; Infrastructure implements Domain-owned Contracts at its boundary.

Workflow and tests

Mailable is consumed by the owning Domain or Service workflow and returns a delivery-neutral result. Test its direct contract, its rejected boundary cases, and the caller or callee that proves the rule in application flow.

Three pitfalls

  1. ❌ Prohibited: move this responsibility into a neighboring type merely because it is nearby.
  2. ✅ Correct: keep the generated placement and depend only on the documented layer direction.
  3. ✅ Correct: test the boundary through the caller and the return or side effect visible to its callee.

Related reading

Read architecture placement for shared rationale and follow this page’s related concept links for the adjacent responsibility.

Boundaries

❌ Prohibited: Do not treat a Mailable as a durable external-delivery guarantee.

✅ Correct: Use Listener and delivery rules to decide queueing and error handling.