The problem
Handling outgoing emails in a web application can be hard, because it’s very easy things to get wrong and send unwanted test mails to real world customers while testing some functionality.
Ensuring sent emails are designed, parsed and formatted correctly is a painstaking problem, too.
… and the solution
Mailcatcher is a program you can use to test sending email. It gives you the ability to inspect sent emails and their headers. It is a simple SMTP server that can receive emails. It also gives you a nice web interface to preview the sent emails.
We’ll cover installing the dependencies for Mailcatcher. Then we’ll install and set it up for easy use in our development environment. This includes use with PHP. Finally, we will setup password protect subdomain for easier access using Nginx.
Setup
First update yum’s repository list, then install the gcc and g++ compilers, and MailCatcher’s dependencies (Ruby and SQLite).
yum update yum -y install gcc gcc-c++ yum -y install sqlite-devel ruby-devel
Now install and MailCatcher itself.
gem install mailcatcher
Running MailCatcher
Once installed, you can run mailcatcher –help to see what options are available.
Start MailCatcher by running mailcatcher –ip [your-vultr-ip-address] on your terminal. Use 0.0.0.0 to bind to all interfaces. Your output should look similar to the following:
root@install:~# mailcatcher --ip [your-ip-address] Starting MailCatcher ==> smtp://127.0.0.1:1025 ==> http://127.0.0.1:1080 *** MailCatcher runs as a daemon by default. Go to the web interface to quit.
NB: If MailCatcher’s web interface fails to load, then you may have to open port 1080 and enable “http service” on CentOS firewall.
One possible solution is to run the commands bellow to open port 1080 for inbound connections or scroll down and read how to setup nginx proxy and access the mailcatcher web interface on port 80 as regular web site.
firewall-cmd --zone=public --add-port=1080/tcp --permanent firewall-cmd --zone=public --add-service=http --permanent firewall-cmd --reload
Start on Boot
It is useful to setup Mailcatcher to start when the server boots. This lets us forget about having to turn on Mailcatcher whenever we start our development machine.
Rather than install a process monitor, we can use systemd, which currently comes out of the box with CentOS 7.
Create and edit file /etc/systemd/system/mailcatcher.service
Put in the following contents and save the file:
[Unit] Description=Ruby MailCatcher Documentation=http://mailcatcher.me/ [Service] Type=simple ExecStart=/usr/local/bin/mailcatcher --foreground --http-ip=0.0.0.0 Restart=always [Install] WantedBy=multi-user.target
Reload systemd to see the changes
systemctl daemon-reload
Start the mailcatcher service:
systemctl start mailcatcher
Start the service at boot:
systemctl enable mailcatcher
Configure PHP to use Mailcatcher
PHP needs the php.ini configuration sendmail_path set to the path of sendmail. Mailcatcher comes with the catchmail command, which can be used for this purpose.
We’ll add a new configuration in PHP’s /etc/php.d/ directory. Then we’ll enable that configuration for each of PHP’s SAPIs (command line, within PHP-FPM, or loaded in Apache).
# Add config for PHP echo "sendmail_path = /usr/bin/env $(which catchmail) -f test@local.dev" | tee /etc/php.d/mailcatcher.ini # Restart Apache if using mod_php service apache2 restart # Restart PHP-FPM if using FPM service php5-fpm restart
You can test the installation using the following command:
php -r 'mail("info@vladimir-ivanov.net", "Feedback", "This is so useful, thanks!");'
Setup password protected (sub)domain for easier access
First, you need to edit /etc/nginx/nginx.conf and the following directive in order to allow Nginx to proxy websockets, too:
http { # .... # As suggested in http://nginx.org/en/docs/http/websocket.html map $http_upgrade $connection_upgrade { default upgrade; "" close; } # .... }
The next step is to create new virtual host file, for example /etc/nginx/conf.d/mailcatcher.site.com.conf with the following contents:
server { listen 80; server_name mailcatcher.site.com; location / { proxy_pass http://127.0.0.1:1080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; auth_basic "Development server. Restricted access."; auth_basic_user_file /etc/nginx/.htpasswd; } }
You can create new .htpasswd file using the following command
htpasswd -c /etc/nginx/.htpasswd exampleuser
Enjoy!