Guides / Laravel

Test Laravel emails locally

RustMail is a local SMTP mail catcher. Your PHP app keeps sending mail the way it does in production, and every message lands in a web UI instead of a real inbox. Four steps, about two minutes.

  1. Start RustMail

    One container, SMTP on port 1025 and the web UI on 8025.

    docker run -p 1025:1025 -p 8025:8025 smyile/rustmail:latest
  2. Point Laravel at it

    In .env, send mail to localhost:1025 with no TLS and no credentials.

    MAIL_MAILER=smtp
    MAIL_HOST=127.0.0.1
    MAIL_PORT=1025
    MAIL_USERNAME=null
    MAIL_PASSWORD=null
    MAIL_ENCRYPTION=null
  3. Send a test email

    Then open localhost:8025: the message is already in the inbox, with its HTML, headers and links.

    php artisan tinker
    > Mail::raw('Hello from Laravel', fn ($m) => $m->to('[email protected]')->subject('Welcome'));
  4. Assert on it in CI

    In GitHub Actions, start RustMail, run tests that send mail with the .env settings from step 2, then fail the job when the email never arrives.

    - name: Start RustMail on localhost:1025
      uses: rustmailapp/rustmail-action@v1
      with:
        mode: start
    
    - name: Run the tests that send mail over SMTP
      run: php artisan dusk
      env:
        MAIL_MAILER: "smtp"
        MAIL_HOST: "127.0.0.1"
        MAIL_PORT: "1025"
    
    - name: Fail if the welcome email never arrived
      uses: rustmailapp/rustmail-action@v1
      with:
        mode: assert
        assert-count: 1
        assert-subject: "Welcome"

Good to know

  • Laravel's phpunit.xml sets MAIL_MAILER=array, so feature tests never reach SMTP. Assert on mail from end-to-end tests such as Dusk, which run against the app with your .env settings.
  • Laravel Sail users can run RustMail as a service in docker-compose.yml and set MAIL_HOST to the service name.
  • Keep MAIL_ENCRYPTION=null: RustMail only speaks STARTTLS when you give it a certificate.

Other frameworks

DjangoRuby on RailsNode.jsSpring Boot