No Mailtrap, No Problem! (with Docker)

no-mailtrap,-no-problem!-(with-docker)

When developing applications that send emails, having a reliable way to test those emails without actually sending them to real recipients is crucial. While services like Mailtrap offer excellent solutions for this, sometimes you need a lightweight, self-hosted option that’s quick to set up and works entirely offline. Enter Mailhog.

Mailhog is an open-source email testing tool that acts as an SMTP server and a web UI to view intercepted emails. It’s incredibly easy to use, making it a fantastic alternative for local development, especially when an internet connection isn’t available or you prefer to keep everything within your local environment.

The easiest and most recommended way to run Mailhog is via Docker. This ensures a consistent environment and prevents conflicts with other tools on your system.

In this guide, we’ll walk through setting up Mailhog using Docker and demonstrate how to configure popular frameworks like Laravel (PHP), Next.js (Node.js), and Django (Python) to send emails to Mailhog.

Getting Started with Mailhog via Docker

First, ensure you have Docker Desktop (or Docker Engine and Docker Compose) installed on your system.

To run Mailhog, simply execute the following Docker command:

docker run -d --name docker-mailhog -p 1025:1025 -p 8025:8025 mailhog/mailhog

Let’s break down this command:

  • -d: Runs the container in detached mode (in the background).
  • --name mailhog: Assigns the name mailhog to your container, making it easier to manage.
  • -p 1025:1025: Maps port 1025 on your host machine to port 1025 inside the container. This is Mailhog’s SMTP port.
  • -p 8025:8025: Maps port 8025 on your host machine to port 8025 inside the container. This is Mailhog’s web UI port.
  • mailhog/mailhog: Specifies the Docker image to pull and run.

If you are on a windows machine with Docker desktop, you should able to see this running on your docker desktop panel

Image description

After running the command, open your web browser and navigate to http://localhost:8025 to access the Mailhog dashboard. This is where you’ll see all your intercepted emails.

To stop Mailhog:

docker stop mailhog

To remove the container (after stopping):

docker rm mailhog

Now, let’s configure our applications.

1. Laravel Project (PHP)

Laravel makes configuring email very straightforward. We’ll adjust the .env file to point to our Mailhog instance running in Docker.

Configuration:

Open your Laravel project’s .env file and set the following:

MAIL_MAILER=smtp
MAIL_HOST=localhost   # Or the IP of your Docker host if not localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

Important Note: If you are running your Laravel application inside Docker (e.g., via Docker Compose), the MAIL_HOST should typically be the service name of your Mailhog container (e.g., mailhog). However, for simplicity and assuming your Laravel app is running directly on your host machine, localhost is correct for connecting to the Mailhog container’s exposed port.

Sending an Email:

You can quickly test sending an email using a Tinkerwell console or by creating a simple route.

  • Using Tinkerwell (or php artisan tinker):

    php artisan tinker
    

    Inside tinker, run:

    Mail::raw('This is a test email from Laravel.', function ($message) {
        $message->to('test@example.com')
                ->subject('Laravel Mailhog Test');
    });
    

    You should see => null if successful.

  • Using a Route:

    Add the following to your routes/web.php:

    use IlluminateSupportFacadesMail;
    use IlluminateSupportFacadesRoute;
    
    Route::get('/send-mail-laravel', function () {
        Mail::raw('This is a test email from Laravel via a route.', function ($message) {
            $message->to('route-test@example.com')
                    ->subject('Laravel Route Mailhog Test');
        });
        return "Email sent to Mailhog from Laravel!";
    });
    

    Visit http://localhost:8000/send-mail-laravel (assuming your Laravel app is running on port 8000).

Verification:

After sending the email, open your Mailhog UI at http://localhost:8025. You should see the incoming email(s) in the inbox.

2. Node.js with Next.js

For Node.js applications, Nodemailer is the go-to library for sending emails. We’ll set up a simple API route in Next.js to send an email to Mailhog.

Installation:

First, install Nodemailer:

npm install nodemailer
# or
yarn add nodemailer

Configuration and Sending Email (Next.js API Route):

Create an API route at pages/api/send-mail.js:

import nodemailer from "nodemailer";

export default async function handler(req, res) {
  if (req.method === "POST") {
    try {
      // Create a Nodemailer transporter using Mailhog's SMTP settings
      let transporter = nodemailer.createTransport({
        host: "localhost", // Mailhog Docker container's exposed port
        port: 1025,
        secure: false, // Mailhog runs without SSL/TLS by default
        ignoreTLS: true, // Also ignore TLS for simple local setup
      });

      // Send mail with defined transport object
      let info = await transporter.sendMail({
        from: '"Next.js Mailhog Test" ', // sender address
        to: "recipient@example.com", // list of receivers
        subject: "Next.js Mailhog Test Subject", // Subject line
        text: "Hello from Next.js with Mailhog!", // plain text body
        html: "Hello from Next.js with Mailhog!", // html body
      });

      console.log("Message sent: %s", info.messageId);
      res.status(200).json({ message: "Email sent successfully!", info });
    } catch (error) {
      console.error("Error sending email:", error);
      res.status(500).json({ error: "Failed to send email." });
    }
  } else {
    res.setHeader("Allow", ["POST"]);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

CLI Verification:

To trigger this API route and send an email, you can use curl from your terminal. Ensure your Next.js development server is running (npm run dev or yarn dev).

curl -X POST http://localhost:3000/api/send-mail

You should receive a JSON response similar to:

{"message":"Email sent successfully!","info":{"accepted":["recipient@example.com"],"rejected":[],"ehlo":["PIPELINING","SIZE 31457280","ETRN","STARTTLS","AUTH PLAIN LOGIN CRAM-MD5","ENHANCEDSTATUSCODES","8BITMIME","DSN","VRFY","XACK","XTEXTC","XEXCH50"],"envelopeTime":11,"messageTime":8,"messageSize":364,"response":"250 2.0.0 Ok: queued as C12B89547","envelope":{"from":"no-reply@example.com","to":["recipient@example.com"]},"messageId":""}}

Verification:

Head over to http://localhost:8025 and confirm that the email from your Next.js application has been received by Mailhog.

3. Python with Django

Django has robust email capabilities built-in, and configuring it to use a local SMTP server like Mailhog is straightforward.

Configuration:

Open your Django project’s settings.py file and add or modify the following:

# settings.py

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost' # Mailhog Docker container's exposed port
EMAIL_PORT = 1025
EMAIL_USE_TLS = False  # Mailhog typically doesn't use TLS/SSL by default
EMAIL_USE_SSL = False
# EMAIL_HOST_USER = '' # Not needed for Mailhog unless configured
# EMAIL_HOST_PASSWORD = '' # Not needed for Mailhog unless configured
DEFAULT_FROM_EMAIL = 'webmaster@localhost.com'

Sending an Email:

You can send an email from the Django shell or through a simple management command or view.

  • Using Django Shell:

    python manage.py shell
    

    Inside the shell, run:

    from django.core.mail import send_mail
    
    send_mail(
        'Django Mailhog Test Subject',
        'Here is the message from Django.',
        'from@example.com', # From address
        ['to@example.com'], # List of recipient email addresses
        fail_silently=False,
    )
    

    You should see 1 as the output if one email was sent successfully.

  • Using a Django Management Command (for CLI testing):

    Create a new management command. In your app (e.g., my_app), create management/commands/send_test_email.py:

    # my_app/management/commands/send_test_email.py
    
    from django.core.management.base import BaseCommand
    from django.core.mail import send_mail
    
    class Command(BaseCommand):
        help = 'Sends a test email to Mailhog'
    
        def handle(self, *args, **options):
            self.stdout.write("Attempting to send a test email to Mailhog...")
            try:
                send_mail(
                    'Django CLI Mailhog Test',
                    'This email was sent from a Django management command.',
                    'cli@example.com',
                    ['cli-recipient@example.com'],
                    fail_silently=False,
                )
                self.stdout.write(self.style.SUCCESS('Email sent successfully! Check Mailhog.'))
            except Exception as e:
                self.stdout.write(self.style.ERROR(f'Failed to send email: {e}'))
    
    

CLI Verification (Django Management Command):

Run the newly created management command:

python manage.py send_test_email

You should see output similar to:

Attempting to send a test email to Mailhog...
Email sent successfully! Check Mailhog.

Verification:

Go to your Mailhog web interface at http://localhost:8025 and observe the incoming email from your Django application.

Conclusion

Using Mailhog with Docker provides a robust, isolated, and easy-to-manage solution for local email testing across various development stacks. By integrating it into your development workflow, you can confidently test email functionalities without relying on external services or accidentally spamming real users. So, the next time you’re working on an application that sends emails, remember: No Mailtrap, No Problem! – Mailhog has got you covered, especially with the power of Docker.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
renault-group-finalizes-strategic-partnership-with-next-gen-robotics-company-wandercraft

Renault Group Finalizes Strategic Partnership with Next Gen Robotics Company Wandercraft

Next Post
how-toy-helicopters-lead-to-a-career-with-real-robots

How Toy Helicopters Lead to a Career with Real Robots

Related Posts