Oussama GHAIEB

Tips, tricks, and code snippets for developers

How to Test Emails Locally with MailHog and Symfony 7.3: A Complete Developer Guide

Testing emails during development can be challenging. You don't want to send real emails to users while building features, but you need to verify that your email functionality works correctly. MailHog provides the perfect solution for local email testing with Symfony 7.3 applications.

What is MailHog?

MailHog is a lightweight email testing tool designed for developers. It acts as an SMTP server that captures emails sent by your application instead of delivering them to real recipients. All captured emails are displayed in a user-friendly web interface, making it easy to test email templates, content, and delivery logic.

Why Use MailHog with Symfony 7.3?

Symfony 7.3's enhanced Mailer component works seamlessly with MailHog, offering several benefits:

  • Safe Testing Environment: No risk of sending test emails to real users
  • Visual Email Inspection: View HTML and plain text versions of emails
  • Complete Email Headers: Inspect all email metadata and headers
  • Zero Configuration: Simple setup with minimal configuration changes
  • Development Workflow: Perfect for local development and CI/CD pipelines

Installing MailHog

The easiest way to run MailHog is using Docker:

# Pull and run MailHog
docker run -d \
  --name mailhog \
  -p 1025:1025 \
  -p 8025:8025 \
  mailhog/mailhog

Option 2: Direct Installation

For macOS users with Homebrew:

brew install mailhog
mailhog

For other systems, download the binary from the MailHog releases page.

Option 3: Docker Compose Integration

Add MailHog to your existing docker-compose.yml:

version: '3.8'
services:
  mailhog:
    image: mailhog/mailhog:latest
    ports:
      - "1025:1025"  # SMTP port
      - "8025:8025"  # Web UI port
    environment:
      - MH_STORAGE=maildir
      - MH_MAILDIR_PATH=/tmp

Configuring Symfony 7.3 with MailHog

Step 1: Update Your Environment Configuration

In your .env.local file, configure the mailer DSN to use MailHog:

# .env.local
MAILER_DSN=smtp://localhost:1025

Step 2: Configure Mailer in config/packages/mailer.yaml

For development environment, create or update config/packages/dev/mailer.yaml:

# config/packages/dev/mailer.yaml
framework:
    mailer:
        dsn: '%env(MAILER_DSN)%'
        envelope:
            sender: 'dev@example.com'
        headers:
            From: 'Your App <noreply@yourapp.com>'

Step 3: Verify Configuration

Check that your mailer configuration is correct:

php bin/console debug:config framework mailer

Quick Testing with Symfony's Built-in Command

Before diving into custom email services, you can quickly verify your MailHog setup using Symfony's built-in mailer test command:

# Basic test
php bin/console mailer:test test@example.com

# Test with custom subject and body
php bin/console mailer:test test@example.com \
  --subject="MailHog Integration Test" \
  --body="Success! MailHog is working with Symfony 7.3"

This is the fastest way to confirm that:

  • Your mailer configuration is correct
  • MailHog is receiving emails properly
  • The SMTP connection is established successfully

Check MailHog's web interface at http://localhost:8025 to see the test email.

Creating and Testing Emails in Symfony 7.3

Basic Email Service

Create a service to handle email sending:

// src/Service/EmailService.php

namespace App\Service;

use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Address;

class EmailService
{
    public function __construct(
        private MailerInterface $mailer
    ) {}

    public function sendWelcomeEmail(string $to, string $name): void
    {
        $email = (new Email())
            ->from(new Address('welcome@yourapp.com', 'Your App'))
            ->to($to)
            ->subject('Welcome to Our Platform!')
            ->html($this->getWelcomeEmailTemplate($name))
            ->text("Welcome {$name}! Thank you for joining our platform.");

        $this->mailer->send($email);
    }

    private function getWelcomeEmailTemplate(string $name): string
    {
        return "
            <h1>Welcome {$name}!</h1>
            <p>Thank you for joining our platform.</p>
            <p>We're excited to have you aboard!</p>
        ";
    }
}

Testing Email in a Controller

// src/Controller/TestEmailController.php

namespace App\Controller;

use App\Service\EmailService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class TestEmailController extends AbstractController
{
    #[Route('/test-email', name: 'test_email')]
    public function testEmail(EmailService $emailService): Response
    {
        $emailService->sendWelcomeEmail(
            'test@example.com',
            'John Doe'
        );

        return new Response('Email sent! Check MailHog at http://localhost:8025');
    }
}

Advanced Email with Twig Templates

Create email templates using Twig for better maintainability:

{# templates/emails/welcome.html.twig #}
<html>
<head>
    <style>
        .email-container { 
            max-width: 600px; 
            margin: 0 auto; 
            font-family: Arial, sans-serif; 
        }
        .header { 
            background-color: #007bff; 
            color: white; 
            padding: 20px; 
            text-align: center; 
        }
        .content { 
            padding: 20px; 
        }
    </style>
</head>
<body>
    <div class="email-container">
        <div class="header">
            <h1>Welcome {{ name }}!</h1>
        </div>
        <div class="content">
            <p>Thank you for joining our platform.</p>
            <p>Here are your next steps:</p>
            <ul>
                <li>Complete your profile</li>
                <li>Explore our features</li>
                <li>Connect with other users</li>
            </ul>
        </div>
    </div>
</body>
</html>

Update your service to use Twig:

// Updated EmailService.php

namespace App\Service;

use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Address;
use Twig\Environment;

class EmailService
{
    public function __construct(
        private MailerInterface $mailer,
        private Environment $twig
    ) {}

    public function sendWelcomeEmail(string $to, string $name): void
    {
        $htmlContent = $this->twig->render('emails/welcome.html.twig', [
            'name' => $name
        ]);

        $email = (new Email())
            ->from(new Address('welcome@yourapp.com', 'Your App'))
            ->to($to)
            ->subject('Welcome to Our Platform!')
            ->html($htmlContent)
            ->text("Welcome {$name}! Thank you for joining our platform.");

        $this->mailer->send($email);
    }
}

Using MailHog Web Interface

Once MailHog is running, access the web interface at http://localhost:8025. The interface provides:

  • Email List: View all captured emails
  • Email Preview: See HTML and plain text versions
  • Header Inspection: View complete email headers
  • Search Functionality: Find specific emails
  • Delete Options: Clear emails individually or in bulk

Advanced MailHog Features

Email Attachments Testing

Test file attachments with your emails:

public function sendEmailWithAttachment(string $to): void
{
    $email = (new Email())
        ->from('sender@yourapp.com')
        ->to($to)
        ->subject('Document Attached')
        ->text('Please find the attached document.')
        ->attachFromPath('/path/to/document.pdf');

    $this->mailer->send($email);
}

Multiple Recipients and CC/BCC

Test complex recipient scenarios:

public function sendBulkEmail(): void
{
    $email = (new Email())
        ->from('newsletter@yourapp.com')
        ->to('user1@example.com')
        ->cc('manager@example.com')
        ->bcc('admin@example.com')
        ->subject('Monthly Newsletter')
        ->html('<h1>Monthly Update</h1><p>Here is our monthly newsletter...</p>');

    $this->mailer->send($email);
}

Automated Testing with MailHog

Create functional tests that verify email sending:

// tests/Functional/EmailTest.php

namespace App\Tests\Functional;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class EmailTest extends WebTestCase
{
    public function testWelcomeEmailSending(): void
    {
        $client = static::createClient();
        
        // Trigger email sending
        $client->request('GET', '/test-email');
        
        // Check that email was sent
        $this->assertEmailCount(1);
        
        // Get the sent email
        $email = $this->getMailerMessage();
        
        // Verify email properties
        $this->assertEmailHtmlBodyContains($email, 'Welcome');
        $this->assertEmailTextBodyContains($email, 'Thank you');
    }
}

Production Considerations

Environment-Specific Configuration

Use different mailer configurations for different environments:

# config/packages/prod/mailer.yaml
framework:
    mailer:
        dsn: '%env(MAILER_DSN)%'  # Use real SMTP in production
        
# config/packages/test/mailer.yaml
framework:
    mailer:
        dsn: 'null://null'  # Disable email sending in tests

Security Best Practices

  • Never use MailHog in production environments
  • Keep MailHog ports closed to external access
  • Use environment variables for configuration
  • Implement proper email validation before sending

Troubleshooting Common Issues

Connection Refused Errors

If you encounter connection errors:

  1. Verify MailHog is running: docker ps or check the process
  2. Confirm port 1025 is accessible
  3. Check firewall settings
  4. Verify Docker network configuration

Emails Not Appearing

If emails aren't showing in MailHog:

  1. Check your MAILER_DSN configuration
  2. Verify the SMTP port (1025) is correct
  3. Clear Symfony cache: php bin/console cache:clear
  4. Check Symfony logs for mailer errors

Performance Issues

For high-volume email testing:

  • Regularly clear MailHog emails
  • Use memory storage instead of file storage
  • Consider MailHog alternatives for heavy testing

Conclusion

MailHog provides an excellent solution for testing emails in Symfony 7.3 applications. Its simple setup, comprehensive web interface, and seamless integration make it an essential tool for any developer working with email functionality. By following this guide, you can confidently develop and test email features without worrying about sending test emails to real users.

The combination of Symfony 7.3's robust Mailer component and MailHog's testing capabilities creates a powerful development environment that ensures your email functionality works perfectly before deployment.

Additional Resources

Tags: #symfony #mail #testing #tools
Oussama GHAIEB - Laravel Certified Developer in Paris

Oussama GHAIEB

Laravel Certified Developer | Full-Stack Web Developer in Paris

14+ years experience 20+ projects
Read more about me →

Comments (0)

No comments yet. Be the first to comment!


Leave a Comment

More Posts :