Installing Sendmail/Postfix on Ubuntu and configuring your Ghost blog to use it
If you are using one of the "recommended" email providers such as Mailgun you should be fine following the official setup guide. Unfortunately, if you are hosting your email elsewhere (or, God forbid, running your own MTA), then Ghost can quickly let you down. For me, I have my mail hosted at Lunarpages - and Ghost refused to play nice despite all my efforts. Ghost uses Nodemailer for sending email. I think one of the main problems is that it's using an ancient version of Nodemailer (v0.7, when the current package is past v6). There is an issue on github on updating Nodemailer but nobody seems to care much. Makes one wonder if Ghost truly is dead. I hope not, because it is a good tool for what it does.
Gmail Config
The following worked for me when sending through gmail:
"mail": {
"from": "GMAIL_USERNAME@gmail.com",
"transport": "SMTP",
"options": {
"host": "smtp.gmail.com",
"port": 465,
"secureConnection": true,
"auth": {
"user": "GMAIL_USERNAME@gmail.com",
"pass": "PASSWORD"
}
}
},
You will have to "allow less secure apps" for the above to work.
BUT this post is not about sending Ghost email through Gmail, but about sending it through a "regular" smtp server hosted for you at your ISP!
Quick Reference of Commands Used
# Edit email credentials, "cook" the file, postfix configuration, restart:
$ sudo vi /etc/postfix/sasl_passwd
$ sudo postmap /etc/postfix/sasl_passwd
$ sudo vi /etc/postfix/main.cf
$ sudo service postfix restart
# Send a test email:
$ echo "This is a test email body." | mail -s "Subject" RECIPIENT@EMAIL.ADDRESS
# Restart postfix
Environment
Server: Ubuntu 18.10
Ghost: self-hosted, 2.25.2
Background
My specific setup is super simple. My host allows SMTP either with or without authentication. But however I configured Ghost, I would just run into this error:
I tried various combinations for my config.production.json. I'll share it with you because some of this might work for you:
mail: {
transport: 'SMTP',
options: {
"host": "mail.???.com",
"secure": false,
"secureConnection": false, <!-- see https://www.saotn.org/send-email-ghost-using-smtp-authentication-tls-encryption/
"port": 587, <-- this is the NON-SSL port for me, but I also tried 465
with "secure": true
"ignoreTLS": true, <-- force nodemailer not to use tls
"auth": {
"user": "???@???",
"pass": "???"
},
"tls": {
"rejectUnauthorized": false
},
"debug": true, <-- supposedly instructs nodemailer to write
error messages to stdout
"log": true <-- supposedly adds logging to nodemailer,
but couldn't find the actual logs
}
}
I tried watching the ghost log while using the email test button to see if there is any more info there:
tail content/logs/???_production.log
But the logs were of no help:
..."code":"ETIMEDOUT","name":"EmailError","statusCode":500,"level":"normal","message":"Failed to send email. Reason: Greeting never received.","help":"\"Please see https://docs.ghost.org/mail/ for instructions on configuring email.\"","stack":"EmailError: Failed to send email. Reason: Greeting never received.\n at EmailError.GhostError (/var/www/???.com/en/versions/2.25.2/core/server/lib/common/errors.js:10:26)\n at new EmailError (/var/www/???.com/en/versions/2.25.2/core/server/lib/common/errors.js:34:20)\n at MailComposer.returnCallback (/var/www/???.com/en/versions/2.25.2/core/server/services/mail/GhostMailer.js:77:31)\n at SMTPConnectionPool._onConnectionError (/var/www/???.com/en/versions/2.25.2/node_modules/simplesmtp/lib/pool.js:334:17)\n at SMTPClient.emit (events.js:198:13)\n at SMTPClient.EventEmitter.emit (domain.js:448:20)\n at SMTPClient.<anonymous> (/var/www/???.com/en/versions/2.25.2/node_modules/simplesmtp/lib/client.js:293:18)\n at ontimeout (timers.js:436:11)\n at tryOnTimeout (timers.js:300:5)\n at listOnTimeout (timers.js:263:5)\n at Timer.processTimers (timers.js:223:10)\n\nError: Greeting never received\n at SMTPClient.<anonymous> (/var/www/???.com/en/versions/2.25.2/node_modules/simplesmtp/lib/client.js:289:25)\n at ontimeout (timers.js:436:11)\n at tryOnTimeout (timers.js:300:5)\n at listOnTimeout (timers.js:263:5)\n at Timer.processTimers (timers.js:223:10)"},"msg":"Failed to send email. Reason: Greeting never received.","time":"2019-07-01T08:19:20.343Z","v":0}
After wasting way too much time trying to go the Ghost route, I decided to use a solid, Linux community supported mailer. After considering sendmail, as well as simpler alternatives such as ssmtp and msmtp and opensmtpd I ended up choosing postfix because it is widely used and has a lot of configuration options.
Towards a Solution
First, make sure sendmail exists on your platform: which sendmail
This should return something similar to /usr/sbin/sendmail
Set your FQDN
hostnamectl set-hostname new-hostname
vi /etc/hosts
Make sure local port 25 is open
For postfix to work, it needs to be able to receive incoming connections from localhost. Ensure that port 25 is open:
sudo apt install net-tools
netstat -tulpn | grep :25
Install Postfix
Install postfix and utilities, such as "mail":
$ sudo apt-get install mailutils
...alternatively, install postfix only:
$ sudo apt-get install postfix
On the second screen, set the actual FQDN of your server. This is not the same as hostname of the 3rd party SMTP server that you use.
You can reconfigure postfix at any time with sudo dpkg-reconfigure postfix
Set your Username/Password
This is a rundown of a detailed explanation:
$ sudo vi /etc/postfix/sasl_passwd
Set the file to:
YOUR.ISP.SERVER:587 username:password
$ sudo vi /etc/postfix/main.cf
Make sure you have:
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
$ sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd
$ sudo chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd
$ sudo postmap /etc/postfix/sasl_passwd
$ sudo service postfix reload
Configure Postfix
sudo vi /etc/postfix/main.cf
There are a plethora of options, you will probably need the following:
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
# fresh installs.
compatibility_level = 2
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = www.zensoft.hu
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = zen2, localhost.localdomain, localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_protocols = all
# Enable auth
smtp_sasl_auth_enable = yes
smtp_tls_wrappermode = yes
# Set username and password
# A less secure method would be: smtp_sasl_password_maps = static:USERNAME@SERVER.com:YOUR_PASSWORD
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
# Turn on tls encryption
smtp_use_tls = yes
smtp_tls_security_level = encrypt
header_size_limit = 4096000
# Set external SMTP relay host here IP or hostname accepted along with a port number.
relayhost = mail.generalcomputing.com:465
# accept email from our web-server only
inet_interfaces = localhost
# https://serverfault.com/questions/147921/forcing-the-from-address-when-postfix-relays-over-smtp
sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
smtp_header_checks = regexp:/etc/postfix/header_check
A non-encrypted option would look like the above except:
#smtp_tls_wrappermode = yes
smtp_use_tls = no
#smtp_tls_security_level = encrypt
After updating run service postfix restart
Relay/Forward System Mail
If you want to forward all mail sent to root, then sudo vi /etc/aliases
# See man 5 aliases for format
postmaster: root
root: YOUR_EMAIL@ADDRESS.COM
And then run sudo newaliases
Relay www-data and other mail
You may run into a situation where mail to www-data is not relayed. For example, cron-job results are often emailed here.
/etc/aliases only allows you to forward mail that is headed for a local address, in other words, the recipient's domain must be one of the domains given in the mydestination = ...
line of main.cf. Therefore, to make sure www-data is forwarded to whatever email you want, you must:
(1) Edit the file set in myorigin = /etc/mailname
in main.cf, by default /etc/mailname and set it to one of the addresses listed in the mydestination = ...
line. For example, add "localhost" to both as in this example:
/etc/postfix/main.cf
myhostname = xxx.domain.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = my-host-name, localhost
/etc/mailname:
localhost
/etc/aliases:
clamav: root
www-data: root
root: RECIPIENT_EMAIL@SERVER.COM
Run newaliases
and service postfix reload
after editing these files.
Force the FROM Address
When testing postfix with echo "This is a test email body." | mail -s "Subject" RECIPIENT_EMAIL@SERVER.COM
, the server will set the from address automatically to the user you are logged in as. Additionally, if any local app tries to send mail with sendmail, if it doesn't explicitly specify a from address then again the above will happen.
I have a dedicated email address for each of my servers, so to make things easy, I force the FROM address to always be that dedicated email address. There is a detailed answer to this on stackoverflow. Here's a quick rundown:
$ sudo vi /etc/postfix/main.cf
...add the following to the end:
sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
smtp_header_checks = regexp:/etc/postfix/header_check
$ sudo vi /etc/postfix/sender_canonical_maps
/.+/ newsender@address.com
$ sudo vi /etc/postfix/header_check
/From:.*/ REPLACE From: newsender@address.com
Allow Postfix through your Firewall
You would only need to take this step if you are using postfix to receive email!
sudo ufw allow postfix
Alternatively, you can allow only specific ports: sudo ufw allow 587
Test Postfix
echo "This is a test email body." | mail -s "Subject" -a "From: YOUR_EMAIL@SERVER.COM" RECIPIENT_EMAIL@SERVER.COM
Or, to send from the default address:
echo "This is a test email body." | mail -s "Subject" RECIPIENT_EMAIL@SERVER.COM
To watch for any errors, run this on a separater terminal while running the above:
sudo tail -f /var/log/mail.log
sudo tail -f /var/log/mail.err
Issues? Kill sendmail-mta
If you see something like this while starting postfix sudo systemctl start postfix
and tailing mail.log sudo tail -f /var/log/mail.log
:
fatal: bind 127.0.0.1 port 25: Address already in use
Then try sudo killall sendmail
, if you see:
sendmail: no process found
Then you may need to sudo killall sendmail-mta
Check and Flush the mail queue
Check: sendmail -bp
Flush: postsuper -d ALL
or sendmail -q -v
Explicitly tell ghost to use sendmail
To do so, set your ghost config email section to the following:
mail: {
"from": "Ghost <ghost@???.com>",
"transport": "SMTP",
"options": {
"service": "sendmail",
}
},
Don't forget to service ghost restart
Sources
General Ghost Email Config Tutorials
- Configure SMTP For Outbound Emails
- Adding Custom SMTP Server to Ghost Config
- How to configure mail for Ghost Blog
- Send email with Ghost using SMTP authentication and TLS encryption
- How To Configure Ghost To Send Email
- How To Set Up Email For Ghost Blogs
- Setup SMTP Email for Ghost
- Sending Emails with Nodemailer Explained
- Nodemailer - SMTP CONNECTION
- How to setup Ghost to send email using Gmail?
- Configure SendMail to Use SMTP Relay
PostFix + Ghost
- Install postfix and let Ghost send mails
- Setup email for ghost blog
- UFW Essentials: Common Firewall Rules and Commands
- Configure Sendmail to Relay Emails through Gmail SMTP
- How To Install and Configure Postfix as a Send-Only SMTP Server on Ubuntu 14.04
- How to Setup Postfix as Send-only Mail Server on an Ubuntu 18.04 Dedicated Server or VPS
- Ubuntu mail server switch to Postfix from Sendmail
- Use Postfix instead of Sendmail?
- Postfix relayhost SMTP – Ubuntu 18.04
- Configure Postfix to Send Mail Using an External SMTP Server
- Setup Simple Mail Relay
- How To Install and Configure Postfix on Ubuntu 16.04
- Forcing the from address when postfix relays over smtp