This tutorial will show you how to install Mailtrain on Ubuntu 16.04 server. Mailtrain is an open-source self-hosted newsletter app, an alternative to commercial email service providers like Mailchimp. You can use Mailtrain to send emails to your email subscribers via your own email server or by using any SMTP relay service (Mailjet, SendGrid, AmazonSES, Mailgun, etc).

Mailtrain is released under the terms of GPL v3.0 license, built on Node.js and MySQL/MariaDB. The latest version is v1.24.1, released on September 28, 2018. Features of Mailtrain are as follows:

  • It allows you to easily manage large mailing lists (like 1 million subscribers).
  • You can add subscribers manually, through the API, or import from a CSV file.
  • It supports custom fields (text fields, numbers, drop-downs or check boxes), merge tags and custom forms.
  • List segmentation.
  • RSS campaign: auto-generate newsletter from RSS feed and send it to subscribers.
  • Subscribers can upload their GPG public keys and Mailtrain will encrypt the newsletter for them.
  • Allows you to check individual click statistics for every link.
  • Advanced email template editors and HTML code editor.
  • Automation: send specific emails when user activates your predefined trigger.
  • You can create open email list (allow public subscription) and closed email list (subscribers are added to the list by admin).

Prerequisites of Installing Mailtrain on Ubuntu 16.04 Server

To run Mailtrain, you need a server with at least 1GB RAM. You can click this special link to get $100 free credit on DigitalOcean. (For new users only). If you are already a DigitalOcean user, then you can click this special link to get $50 free credit on Vultr (for new users only). Once you have an account at DigitalOcean or Vultr, install Ubuntu 16.04 on your server and follow the instructions below.

You also need to have a domain name. I registered my domain name from NameCheap because the price is low and they give whois privacy protection for free.

Step 1: Install MariaDB Database Server

Your subscribers data will be stored in a database. Mailtrain supports MySQL and MariaDB. MariaDB is a drop-in replacement for MySQL. It is developed by former members of MySQL team who are concerned that Oracle might turn MySQL into a closed-source product. So let’s install the MariaDB database server.

Enter the following command to install it on Ubuntu 16.04.

sudo apt install mariadb-server mariadb-client

After it’s installed, MariaDB server should be automatically stared. Use systemctl to check its status.

systemctl status mysql

Sample output:

 mariadb.service - MariaDB 10.1.34 database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2018-09-08 11:13:27 UTC; 21s ago
     Docs: man:mysqld(8)
           https://mariadb.com/kb/en/library/systemd/
 Main PID: 3473 (mysqld)
   Status: "Taking your SQL requests now..."
    Tasks: 27 (limit: 505)
   CGroup: /system.slice/mariadb.service
           └─3473 /usr/sbin/mysqld

If it’s not running, start it with this command:

sudo systemctl start mysql

To enable MariaDB to automatically start at system boot time, run

sudo systemctl enable mysql

Now run the post installation security script.

sudo mysql_secure_installation

When it asks you to enter MariaDB root password, press Enter key as the root password isn’t set yet. Then enter y to set the root password for MariaDB server.

Next, you can press Enter to answer all remaining questions, which will remove anonymous user, disable remote root login and remove test database. This step is a basic requirement for MariaDB database security. (Note that the letter Y is capitalized, which means it’s the default answer.)

Step 2: Create a Database and User for Mailtrain

Now we need to log in to MariaDB console and create a database and user for Mailtrain. By default, the MaraiDB package on Ubuntu uses unix_socket to authenticate user login, which basically means you can use username and password of the OS to log into MariaDB console. So you can run the following command to login without providing MariaDB root password.

sudo mysql -u root

Create a database for Mailtrain using the following command. I named it mailtrain, but you can use whatever name you like. (Don’t leave out the semicolon.)

create database mailtrain;

Then enter the command below to create a database user for Mailtrain and grant all privileges of the mailtrain database to the user. Replace mtuser and your-password with your preferred username and password.

grant all privileges on mailtrain.* to mtuser@localhost identified by 'mtuser_password';

Next, create a user with read only access to mailtrain database. I named this user mt_readonly.

grant select on mailtrain.* TO mt_readonly@localhost identified by 'mt_readonly_password';

Flush the privileges table for the changes to take effect and then get out of MariaDB console.

flush privileges;

exit;

Step 3: Install Node.js

Mailtrain is built on Node.js, which is a JavaScript run-time environment that translates human-readable JavaScript code into machine code. So we need to install Node.js on Ubuntu 16.04 in order to run Mailtrain. Mailtrain requires Node.js 7 . This tutorial will install the current LTS release of Node.js (V8.x) from NodeSource repository.

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt install -y nodejs

The nodejs package contains the npm (Node.js package manager) binary, so there’s no need to install it separately. To check your Node.js and npm version, run

node -v

npm -v

Output:

To compile and install native addons from npm you also need to install build tools:

sudo apt install -y build-essential

Step 4: Run Mailtrain

Go to /var/www/ and fetch Mailtrain files from Github.

cd /var/www/

sudo git clone https://github.com/Mailtrain-org/mailtrain.git

Import the initial SQL data to the mailtrain database by using the following command. You need to enter the password of mtuser.

mysql -u mtuser -p mailtrain < /var/www/mailtrain/setup/sql/mailtrain.sql

Create the production.toml configuration file.

sudo nano /var/www/mailtrain/config/production.toml

In this file, you can add configurations that override the default configurations in /var/www/mailtrain/config/default.toml file.  We only need to add the following configurations.

user="mailtrain"
group="mailtrain"
[log]
level="error"
[www]
secret="Replace this with some random characters"
[mysql]
user="mtuser"
password="mtuser_password"
[queue]
processes=5

Save and close the file. Then create the mailtrain user and group for the mailtrain daemon to run as. Note that we don’t need to create password for this user, so we create a system user instead of a normal user.

sudo adduser --system --group mailtrain

Create a configuration file for the report worker.

sudo nano /var/www/mailtrain/workers/reports/config/production.toml

Add the following configurations. This report worker will have read-only access to mailtrain database.

[log]
level="error"
[mysql]
user="mt_readonly"
password="mt_readonly_password"

Save and close the file. Then change the permission of /var/www/mailtrain/.

sudo chown mailtrain:mailtrain /var/www/mailtrain/ -R

sudo chmod o-rwx /var/www/mailtrain/config/

And install required node packages.

cd /var/www/mailtrain

sudo npm install --no-progress --production --unsafe-perm=true

Copy the systemd service unit file to /etc/systemd/system/ directory.

sudo cp /var/www/mailtrain/setup/mailtrain.service /etc/systemd/system/

Open this file.

sudo nano /etc/systemd/system/mailtrain.service

Because we downloaded Mailtrain to /var/www/mailtrain/ directory, so change the working directory from /opt/mailtrain to /var/www/mailtrain. Save and close this file. Then start mailtrain.service.

sudo systemctl start mailtrain.service

Enable auto-start at system boot time.

sudo systemctl enable mailtrain.service

Check its status. Make sure it is running. If the output says activating (auto-restart), then just wait a few moments for Mailtrain to start.

sudo systemctl status mailtrain.service

Now that Mailtrain is running, you can access Mailtrain web interface via port 3000.

your-server-ip:3000

Setting up Reverse Proxy and Enabling HTTPS

Before using the Mailtrain web interface, let’s put it behind Nginx and then enable HTTPS. Install Nginx web server on Ubuntu 16.04 with:

sudo apt install nginx

Now you can copy the example mailtrain-nginx.conf file to /etc/nginx/conf.d/ directory.

sudo cp /var/www/mailtrain/setup/mailtrain-nginx.conf /etc/nginx/conf.d/

Open this file.

sudo nano /etc/nginx/conf.d/mailtrain-nginx.conf

Find the following line.

server_name mailtrain.org www.mailtrain.org;

Change the value of server_name parameter to your own domain name like newsletter.your-domain.com.  Don’t forget to create an A record for this sub-domain.

server_name newsletter.linuxbabe.com;

Save and close the file. Then test Nginx configurations.

sudo nginx -t

If the test if successful, reload Nginx for the changes to take effect.

sudo systemctl reload nginx

You should now be able to access Mailtrain web interface via your sub-domain: newsletter.your-domain.com.

Now edit /var/www/mailtrain/config/production.toml file.

sudo nano /var/www/mailtrain/config/production.toml

In the [www] section, add the following two lines to indicate that mailtrain is behind the Nginx proxy and make it listen on local host address only.

host="127.0.0.1"
proxy=true

Save and close the file. Then restart Mailtrain for the change to take effect.

sudo systemctl restart mailtrain

Enabling HTTPS With Let’s Encrypt

Install Let’s Encrypt client (certbot) on your Ubuntu 16.04 server.

sudo apt install software-properties-common

sudo add-apt-repository ppa:certbot/certbot

sudo apt update

sudo apt install certbot python3-certbot-nginx

Then you can use the Nginx plugin to automatically obtain and install a TLS certificate by executing the following command.

sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email your-email-address -d newsletter.your-domain.com

Now you can access Mailtrain web interface via your domain name and a secure HTTPS connection.

Login with username admin and password test. Then change your account email address and password. Go to settings page to change default configurations. You should change the service address from http://localhost:3000/ to your sub-domain (https://newsletter.your-domain.com).

Note: The admin account is an easy target for hackers. For best security, it’s recommended that you change the username from admin to something else. The Mailtrain web interface doesn’t provide such option, but you can change the username in MariaDB database using SQL command.

In the Mailer Settings, you can use SMTP if you have your own email server or use Amazon SES.  Actually, you can also use other SMTP relay services in the SMTP tab. In the screenshot below, I use my own email server. Emails will be submitted on port 587 with STARTTLS encryption.

Save your settings. Then you can create a list to test the functionalities of Mailtrain.

How to Handle Bounce Messages in Mailtrain

Sooner or later, you email list will contain addresses that you can’t send emails to. For example, when a subscriber who uses a company email address leaves the company, that email address will be deleted. So your email server will receive bounce message saying that the email can’t be delivered.

If you use a SMTP relay service to send email, they will handle bounce messages for you. If you use your own email server to send email, then you need to handle bounce messages in Mailtrain. Mailtrain offers two ways to handle bounced messages.

  • via VERP
  • via Postfix log

I personally use the VERP method, because it’s widely used in the email community and also because the second method causes high CPU usage on my server.

VERP Bounce Handling

With VERP (variable envelope return path), your email list manager uses unique envelope addresses for each subscriber. To enable VERP, edit the production.toml file.

sudo nano /var/www/mailtrain/config/production.toml

If your Mailtrain host has no SMTP server running, then add the following text.

[verp]
enabled=true
port=25
disablesenderheader=true

If your Mailtrain server has a SMTP server like Postfix running, then add the following text. The bounce handling server will listen on 127.0.0.1:2525.

[verp] 
enabled=true 
port=2525 
host="127.0.0.1"
disablesenderheader=true

Save and close the file. Then restart Mailtrain for the changes to take effect.

sudo systemctl restart mailtrain

In Mailtrain web interface, go to Settings -> VERP Bounce Handlding. Check Use VERP to catch bounces. Save your settings.

Next, you need to create a MX record for the server hostname (bounces.your-domain.com), then add A record for this hostname, pointing to your Mailtrain host, so bounce messages can be sent to your Mailtrain host. Each subscriber in your list will have an unique envelope address like [email protected].

Note that if you deployed DMARC record for your domain name, then the SPF alignment must be set to relaxed mode. If it’s set to strict mode, your newsletter could fail DMARC check.

If the Mailtrain bounce handling server is listening on port 2525 of 127.0.0.1 and Postfix SMTP server is listening on port 25 of the public IP address, then you need to set up transport map so that Postfix can relay the bounce message to Mailtrain. Create the transport map file.

sudo nano /etc/postfix/transport

Add the following line to this file. This tells Postfix to relay emails with address like [email protected] to the Mailtrain bounce handling server.

bounces.your-domain.com  smtp:[127.0.0.1]:2525

Save and close the file. Then generate the index file.

sudo postmap /etc/postfix/transport

Edit Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following line to the file.

transport_maps = hash:/etc/postfix/transport

Save and close the file. Then restart Postfix for the change to take effect.

sudo systemctl restart postfix

Cron Job to Automatically Clean Unsubscribed Email Addresses

You can manually delete unsubscribed email addresses in the Mailtrain web-based admin panel, but it’s much more efficient to delete them using MySQL/MariaDB commands, then you just create a Cron job to automate this task.

First, log into MySQL/MariaDB database server.

sudo mysql -u root

Then connect to the mailtrain database.

use mailtrain;

The subscribers’ info are stored in the subscription tables. If you have several mailing lists, then you will have several subscription tables. You can list all these tables using the following SQL command.

show tables like 'subscription%';

Output on my server.

 ------------------------------------- 
| Tables_in_mailtrain (subscription%) |
 ------------------------------------- 
| subscription                        |
| subscription__1                     |
| subscription__2                     |
 -------------------------------------

The first table is an empty table. I have two lists in Mailtrain. They are stored in subscription__1 and subscription__2 table. Subscribed email addresses have status code set to 1. Unsubscribed email addresses have status code set to 2. So, to delete unsubscribed email addresses, you can run the following SQL commands.

DELETE FROM subscription__1 where status = '2';
DELETE FROM subscription__2 where status = '2';

To exit MySQL/MariaDB database server, run

exit;

Now open the root user’s crontab file.

sudo crontab -e

Add the following two lines.

# Delete unsubscribed email addresses from mailing list daily
@daily /usr/bin/mysql -u root mailtrain -Bse "DELETE FROM subscription__1 where status = '2';DELETE FROM subscription__2 where status = '2';"

Save and close the file. And you’re done.

Dealing with Malicious Signup

There are people who don’t have anything to do but use fake email address to sign up for your email list, so the signup confirmation email will be sent to a fake email address and you may get undelivered email report at your inbox.

You can use your webmail such roundcube to create a filter, which automatically deletes this kind of email message. In the following screenshot, you can see I created a filter that automatically delete a message if

  • The subject contains “Undelivered Mail Returned to Sender
  • The undelivered message report is sent to my address.
  • The body contains “Please Confirm Subscription”. (Because the signup confirmation email contains this phrase.)

Wrapping Up

I hope this tutorial helped you install Mailtrain on Ubuntu 16.04 server. You can go to Mailtrain wiki to find more information on using Mailtrain. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial

[Total: 1 Average: 5]