Laravel Email Testing with SendPit
Introduction
Laravel makes sending emails straightforward with its built-in Mail facade, Mailables, and Notifications. But during development and QA, you need a safe place to send those emails without accidentally reaching real inboxes. That is exactly what SendPit solves.
SendPit provides isolated SMTP mailboxes that capture every outgoing email from your application. Your team can inspect email content, headers, HTML rendering, and attachments all from a shared dashboard. Because SendPit uses standard SMTP, there are no SDKs to install and no code changes beyond updating your environment variables.
Why SendPit for Laravel?
- Zero code changes -- configure once in
.envand every email your app sends is captured automatically. - Team collaboration -- share a mailbox across your team so QA, designers, and developers all see the same test emails.
- Isolated environments -- create separate mailboxes for local development, CI pipelines, and staging servers.
- Instant delivery -- emails appear in your SendPit mailbox within seconds of being sent.
Prerequisites
Before you begin, make sure you have:
- Laravel 8 or later (this guide works with Laravel 8, 9, 10, 11, and 12)
- Composer installed
- A SendPit account with at least one mailbox created
- Your mailbox SMTP credentials (available in your SendPit dashboard under Mailbox Settings)
Step 1: Configure Your Environment Variables
Open your .env file in the root of your Laravel project and update the mail settings:
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendpit.com
MAIL_PORT=587
MAIL_USERNAME=mb_xxxxxxxxxxxxxxxx
MAIL_PASSWORD=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=test@example.com
MAIL_FROM_NAME="${APP_NAME}"
Replace mb_xxxxxxxxxxxxxxxx and the password with your actual SendPit mailbox credentials. You can find these in your SendPit dashboard by navigating to your mailbox and clicking Settings.
The MAIL_FROM_ADDRESS can be any email address you like since SendPit captures all outgoing mail regardless of the sender address.
Step 2: Verify Your Mail Configuration
Laravel ships with a config/mail.php file that reads from environment variables by default. Open it and confirm the smtp mailer configuration looks like this:
'smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST', '127.0.0.1'),
'port' => env('MAIL_PORT', 2525),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
],
If you have not modified config/mail.php from its default state, no changes are needed. Laravel will automatically pick up the values from your .env file.
After changing environment variables, clear the config cache:
php artisan config:clear
Step 3: Send a Test Email
The quickest way to verify your configuration is with Artisan tinker. Open your terminal and run:
php artisan tinker
Then send a test email:
use Illuminate\Support\Facades\Mail;
Mail::raw('Hello from SendPit!', function ($message) {
$message->to('recipient@example.com')
->subject('SendPit Test Email');
});
Check your SendPit mailbox. The email should appear within a few seconds. If it does, your configuration is working correctly.
Using Mailables
For production-quality emails, Laravel provides Mailable classes. Generate one with Artisan:
php artisan make:mail WelcomeEmail
This creates app/Mail/WelcomeEmail.php. Update it with your content:
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class WelcomeEmail extends Mailable
{
use Queueable, SerializesModels;
public function __construct(
public string $username
) {}
public function envelope(): Envelope
{
return new Envelope(
subject: 'Welcome to Our App',
);
}
public function content(): Content
{
return new Content(
view: 'emails.welcome',
with: [
'username' => $this->username,
],
);
}
}
Create the corresponding Blade view at resources/views/emails/welcome.blade.php:
<!DOCTYPE html>
<html>
<body>
<h1>Welcome, {{ $username }}!</h1>
<p>Thanks for signing up. We are glad to have you on board.</p>
</body>
</html>
Send the mailable from a controller or tinker:
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
Mail::to('user@example.com')->send(new WelcomeEmail('Jane'));
The rendered HTML email will appear in your SendPit mailbox, letting you inspect the layout, content, and headers.
Using Notifications
Laravel Notifications let you send emails through the mail channel. Here is a quick example:
php artisan make:notification OrderShipped
In the generated notification class:
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class OrderShipped extends Notification
{
use Queueable;
public function via(object $notifiable): array
{
return ['mail'];
}
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Your Order Has Shipped')
->greeting('Hello!')
->line('Your order #12345 has been shipped.')
->action('Track Order', url('/orders/12345'))
->line('Thank you for shopping with us!');
}
}
Trigger the notification:
$user->notify(new \App\Notifications\OrderShipped());
The notification email will be captured by SendPit just like any other outgoing mail.
Environment-Specific Configuration
A common pattern is to use SendPit in development and staging while using your production mail provider (e.g., Amazon SES, Postmark, Mailgun) in production.
Laravel makes this easy with separate .env files per environment:
.env (local development)
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendpit.com
MAIL_PORT=587
MAIL_USERNAME=mb_dev_mailbox_user
MAIL_PASSWORD=your_dev_mailbox_password
MAIL_ENCRYPTION=tls
.env.staging
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendpit.com
MAIL_PORT=587
MAIL_USERNAME=mb_staging_mailbox_user
MAIL_PASSWORD=your_staging_mailbox_password
MAIL_ENCRYPTION=tls
.env.production
MAIL_MAILER=ses
MAIL_FROM_ADDRESS=noreply@yourdomain.com
By using separate mailboxes for each environment, you get clean separation between development noise and staged QA testing.
Testing with Pest and PHPUnit
When running automated tests, you typically do not want to send actual SMTP requests. Laravel provides Mail::fake() to intercept all outgoing mail in memory:
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeEmail;
test('welcome email is sent after registration', function () {
Mail::fake();
// Perform the action that triggers the email
$this->post('/register', [
'name' => 'Jane Doe',
'email' => 'jane@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
Mail::assertSent(WelcomeEmail::class, function ($mail) {
return $mail->hasTo('jane@example.com');
});
});
However, if you want to run integration tests that verify the actual rendered email content (HTML, headers, attachments), you can point your test environment at a dedicated SendPit mailbox. Set these values in your phpunit.xml or .env.testing:
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendpit.com
MAIL_PORT=587
MAIL_USERNAME=mb_test_mailbox_user
MAIL_PASSWORD=your_test_mailbox_password
MAIL_ENCRYPTION=tls
This way, integration test emails land in their own isolated mailbox and do not clutter your development inbox.
Laravel Sail and Docker
If you are running Laravel inside Docker (including Laravel Sail), the container needs to reach the external SendPit SMTP server. In most cases, the default configuration works because smtp.sendpit.com is an external hostname that Docker containers can resolve.
If you experience connectivity issues, verify that your container has outbound internet access:
# Inside your Docker container
php artisan tinker
$socket = fsockopen('smtp.sendpit.com', 587, $errno, $errstr, 10);
if ($socket) {
echo 'Connection successful';
fclose($socket);
} else {
echo "Connection failed: $errstr ($errno)";
}
Laravel Sail users: Sail containers have outbound internet access by default. Your .env configuration should work without any Docker-specific changes.
Custom Docker setups: If your Docker network restricts outbound traffic, ensure that port 587 is open for outgoing connections to smtp.sendpit.com.
Troubleshooting
Connection Timed Out
Swift_TransportException: Connection could not be established with host smtp.sendpit.com
- Verify your server or container can reach
smtp.sendpit.comon port 587. - Check firewall rules to ensure outbound connections on port 587 are allowed.
- Try alternative ports:
1025or2525.
Authentication Failed
Expected response code 235 but got code "535"
- Double-check your
MAIL_USERNAMEandMAIL_PASSWORDin.env. - Ensure you copied the full credentials from your SendPit mailbox settings (no leading or trailing spaces).
- Run
php artisan config:clearto ensure cached config is not stale.
Emails Not Appearing in Mailbox
- Confirm you are looking at the correct mailbox in your SendPit dashboard.
- Check that
MAIL_MAILERis set tosmtp(notlog,array, or another driver). - If using queued mail, ensure your queue worker is running:
php artisan queue:work. - Verify your
.envvalues are not overridden byconfig/mail.phphardcoded values.
TLS / Encryption Errors
stream_socket_enable_crypto(): SSL operation failed
- Ensure
MAIL_ENCRYPTION=tlsis set (notssl). - Verify your PHP installation has the OpenSSL extension enabled.
- If running in Docker, ensure the container has up-to-date CA certificates.
Next Steps
- View the full SMTP integration guide for examples in Python, Ruby, Node.js, Java, Go, and more.
- Read the developer documentation for advanced features like email search, filtering, and team management.
- Create additional mailboxes for different projects or environments from your SendPit dashboard.