Skip to main content
SaaS Starter Vue uses Laravel’s mail system to send transactional emails including registration confirmations, password resets, subscription notifications, and tenant invitations.

Email Drivers

Laravel supports multiple email delivery methods:
  • SMTP - Standard SMTP server (Gmail, Mailgun, etc.)
  • Mailgun - Mailgun API integration
  • Postmark - Postmark API integration
  • Amazon SES - AWS Simple Email Service
  • Resend - Resend API integration
  • Log - Write emails to log files (development only)
  • Array - Store emails in memory (testing only)
The application defaults to the log driver for development. Configure a real mail driver for production.

SMTP Configuration

The most common email configuration uses SMTP:

Environment Variables

MAIL_MAILER
string
default:"log"
The default mail driver. Set to smtp for SMTP delivery.
MAIL_HOST
string
default:"127.0.0.1"
required
The SMTP server hostname.
MAIL_PORT
integer
default:"2525"
required
The SMTP server port. Common ports:
  • 25 - Standard SMTP (usually blocked by ISPs)
  • 587 - TLS/STARTTLS (recommended)
  • 465 - SSL
  • 2525 - Alternative port (Mailgun, Mailtrap)
MAIL_USERNAME
string
SMTP authentication username.
MAIL_PASSWORD
string
SMTP authentication password.
Store this securely. Never commit to version control.
MAIL_ENCRYPTION
string
Encryption method. Options: tls, ssl, or leave empty for no encryption.
Use tls for port 587, ssl for port 465.
MAIL_FROM_ADDRESS
string
required
The default “from” email address for all outgoing emails.
MAIL_FROM_NAME
string
default:"${APP_NAME}"
The default “from” name for all outgoing emails. Supports variable substitution.

Provider-Specific Configuration

Gmail

Using Gmail for SMTP (not recommended for production):
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=[email protected]
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"
Gmail requires an App Password (not your regular password). Enable 2FA and create an app password at: https://myaccount.google.com/apppasswords

Mailgun

Professional email delivery service:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=[email protected]
MAIL_PASSWORD=your-mailgun-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Mailtrap (Development)

Email testing service for development:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your-mailtrap-username
MAIL_PASSWORD=your-mailtrap-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"
Mailtrap captures all emails without delivering them. Perfect for testing email functionality.

Postmark

Transactional email service with high deliverability:
MAIL_MAILER=postmark
POSTMARK_TOKEN=your-postmark-server-token
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Amazon SES

AWS Simple Email Service:
MAIL_MAILER=ses
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_DEFAULT_REGION=us-east-1
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Resend

Modern email API:
MAIL_MAILER=resend
RESEND_API_KEY=your-resend-api-key
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Development Configuration

For local development, use the log driver to preview emails:
.env
MAIL_MAILER=log
MAIL_LOG_CHANNEL=stack
Emails will be written to storage/logs/laravel.log:
# Watch email logs in real-time
tail -f storage/logs/laravel.log | grep -A 50 "Message-ID"

Testing Email Configuration

Test your email configuration:
php artisan tinker
# Send a test email
Mail::raw('Test email from SaaS Starter Vue', function ($message) {
    $message->to('[email protected]')
            ->subject('Email Configuration Test');
});

# Check for errors
if (Mail::failures()) {
    print_r(Mail::failures());
} else {
    echo "Email sent successfully!";
}

Email Types Sent by the Application

The application sends various transactional emails:

Authentication Emails

  • Email Verification - Sent when new users register
  • Password Reset - Sent when users request password reset
  • Two-Factor Authentication - 2FA codes if enabled

Tenant Management Emails

  • Tenant Created - Welcome email for new tenants
  • User Invitation - Invite users to join a tenant
  • Role Changed - Notification when user role changes

Subscription Emails

  • Subscription Created - Confirmation of new subscription
  • Subscription Renewed - Renewal confirmation
  • Subscription Canceled - Cancellation confirmation
  • Payment Failed - Notification of failed payment
  • Trial Ending Soon - Reminder before trial expires

System Notifications

  • Activity Alerts - Important system activity
  • Security Alerts - Suspicious login attempts
  • System Updates - Maintenance notifications

Customizing Email Templates

Email templates are located in resources/views/emails/:
# Publish vendor email views
php artisan vendor:publish --tag=laravel-mail

# Customize templates in:
resources/views/vendor/mail/

Email Queuing

For better performance, queue emails instead of sending synchronously:
// In your mailable class
public function __construct()
{
    $this->queue();
}
Ensure your queue is configured:
.env
QUEUE_CONNECTION=database
Run the queue worker:
php artisan queue:work
In production, use a process manager like Supervisor to keep the queue worker running.

Advanced Configuration

Multiple Mail Configurations

Use different mail configurations for different email types:
// config/mail.php
'mailers' => [
    'smtp' => [
        // Your primary SMTP config
    ],
    'postmark' => [
        'transport' => 'postmark',
    ],
],
Send via specific mailer:
Mail::mailer('postmark')->send(new WelcomeEmail());

Failover Configuration

Automatically fallback to another mailer if the primary fails:
// config/mail.php
'mailers' => [
    'failover' => [
        'transport' => 'failover',
        'mailers' => [
            'postmark',
            'smtp',
            'log',
        ],
        'retry_after' => 60,
    ],
],
.env
MAIL_MAILER=failover

Per-Tenant Email Configuration

Configure different email settings per tenant:
// In your tenant context
Config::set('mail.from.address', $tenant->email_from_address);
Config::set('mail.from.name', $tenant->email_from_name);

Production Best Practices

Domain Authentication Required: Configure SPF, DKIM, and DMARC records for your sending domain to ensure deliverability.

SPF Record

Add to your DNS:
v=spf1 include:_spf.mailgun.org ~all

DKIM Record

Obtain from your email provider and add to DNS.

DMARC Record

v=DMARC1; p=none; rua=mailto:[email protected]

Rate Limiting

Implement rate limiting to prevent abuse:
RateLimiter::for('emails', function ($job) {
    return Limit::perMinute(100);
});

Email Verification

Ensure your email sender identity is verified with your provider.

Monitoring

  • Track email delivery rates
  • Monitor bounce rates
  • Set up alerts for failed deliveries
  • Log all email sending attempts

Troubleshooting

Emails Not Sending

# Check logs
tail -f storage/logs/laravel.log

# Test connection
php artisan tinker
>>> Mail::raw('Test', fn($msg) => $msg->to('[email protected]')->subject('Test'));

Connection Timeout

  • Verify SMTP host and port
  • Check firewall rules
  • Ensure the port is not blocked by your hosting provider

Authentication Failed

  • Verify username and password
  • Check if 2FA/app passwords are required
  • Ensure SMTP authentication is enabled

Emails Going to Spam

  • Configure SPF, DKIM, and DMARC
  • Use a reputable email service
  • Avoid spam trigger words
  • Include unsubscribe links
  • Maintain a good sender reputation

Environment Examples

MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Next Steps

Build docs developers (and LLMs) love