Postfix Email – Debian and Linux2023

Is Postfix of any use?

Basically no. But, if you want to test for certain conditions on your server, you need a way to send an email to let you know.

Email will go through your Amazon SES service as a relay. You should be out of sandbox mode.

The DNS records for you nominated Domain name – to be used in Postfix configurations – should be configured in SES (Oregon for Australia). This will use port 587. (I can’t recall offhand, but I don’t think you need to open Port 587 in your Security Group as it is an outbound scenario.) If using a 3rd party like MS Exchange as the relay, you use port 465 and your email account’s username and password. Amazon relay will use your SMTP keys (effectively a user and password – public and private keys). These keys must have been made previously, as per my other articles on AWS Account & SES.

I will give an example of using the wget command to verify if a website on Amazon can access https://. Uptime Robot is a good service to monitor a website, but it will not detect if your https:// SSL certificate has expired. If your paid or free certificate has expired, wget will not work, so you send an email to let you know. It would be better of course to modify the certbot.sh script (under my Debian articles) to test if the certificate has expired. I may attend to this later, but for now, this is one example. Another could be if you detect a known mysql error whereby the site is not seen as being down.

Your apt packages should include wget. If not, apt install wget.


Postfix on Debian 11


postfix - debian 12

Install Postfix on Debian 12

This should be the same on Debian 11

First, use your SMTP credentials in sasl_passwd. The public key is visible under IAM and your would have kept the private key somehwere safe, e.g. on your PC.
You can change the SMTP values if you lost them, and replace wherever you previously used the old ones.
We disable postfix for better security. In our shell scripts we start it, sleep a couple of seconds, send an email, sleep a couple of seconds, then stop postfix.

apt install postfix

From the GUI, select localhost
Leave the System Mail name as-is. You can modify /etc/postfix/main.cf later.

systemctl stop postfix
systemctl disable postfix

apt install libsasl2-modules

In the next section, we are showing Amazon as the relay, rather than,say, MS Exchange.


cd /etc/postfix

cp -p main.cf main.cf.bak
cp -p master.cf master.cf.bak

vi sasl_passwd
[email-smtp.us-west-2.amazonaws.com]:587 SMTPUSERNAME:SMTPPASSWORD

[save and exit - use the square brackets as shown above]

postmap hash:/etc/postfix/sasl_passwd
chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

cd /etc/postfix

Below are the entire contents of main.cf - yu need to place your own domain name in it, and we will look at the SMTP banner shortly. Edit the SSL certificates for your domain name's SSL.
You will see existing values, which may vary a little, e.g. you may see compatibility_level = 3.6.
I will indent the values we must add and comment out any we do not want.

vi main.cf

# comment out:
# smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)

biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 3.7
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
unknown_local_recipient_reject_code = 550

# smtpd_tls_cert_file=/etc/ssl/certs/......
# smtpd_tls_key_file=/etc/ssl/private/.....
   # ADD YOUR OWN SSL HERE: e.g. letsencrypt mydomain.com: use your own domain and SSL location
   smtpd_tls_cert_file=/etc/letsencrypt/live/mydomain.com/fullchain.pem
   smtpd_tls_key_file=/etc/letsencrypt/live/mydomain.com/privkey.pem

smtpd_tls_security_level=may
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
   smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_tls_security_level = encrypt
# comment out if present:
# smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# comment out:
# smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination

   # Modify or add as follows: do not have any vaues listed twice in the config file - use your own domain
   myhostname = mydomain.com
   mydomain = mydomain.com
   mail_owner = postfix
   myorigin = $mydomain
   inet_interfaces = localhost
   inet_protocols = all
   mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

   debug_peer_level = 2
   debugger_command =
         PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
         ddd $daemon_directory/$process_name $process_id & sleep 5
   sendmail_path = /usr/sbin/sendmail.postfix
   newaliases_path = /usr/bin/newaliases.postfix
   mailq_path = /usr/bin/mailq.postfix
   setgid_group = postdrop
   html_directory = no
   meta_directory = /etc/postfix
   smtp_sasl_security_options = noanonymous
   smtp_use_tls = yes
   smtp_tls_note_starttls_offer = yes
   smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
   smtp_sasl_auth_enable = yes

   # Return to fix this banner value with the IP and region values. Use mxtoolbox: see mxtoolbox.com > super tool > reverse pointer (never add this to the DNS as registrars should have it behind the scenes)
   smtpd_banner = ec2-XXX-XXX-XXX-XXX.ap-southeast-2.compute.amazonaws.com ESMTP mydomain.com postfix

   smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks, reject_unauth_destination
   smtpd_relay_restrictions = reject_unauth_destination

   maillog_file = /var/log/mail.log
   smtpd_tls_loglevel = 3

#  Edit for your email relay service - Oregon for Australia, or your 3rd Party. e.g. MS Exchange could be smtp-mail.outlook.com TLS on port 587, with your email address and password in sasl_pssword. MS Exchange may need changes to the account to allow your domain as external, the account to permit SMTP or possibly in Azure/Identity panel to disable security on your email account.

   relayhost = [email-smtp.us-west-2.amazonaws.com]:587



# Comment out where shown
# mydestination = $myhostname, ip-172-31-43-2, localhost.localdomain, localhost
# mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
# mailbox_size_limit = 0
# recipient_delimiter = +
# inet_interfaces = loopback-only
# default_transport = error
# relay_transport = error
# inet_protocols = all
# smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
# smtp_tls_note_starttls_offer = yes
# smtp_use_tls = yes
# smtp_sasl_auth_enable = yes
# smtp_sasl_security_options = noanonymous
                                                               
[save and exit]

You need the following lines: just check it is uncommented

vi /etc/postfix/master.cf

smtp      inet  n       -       y       -       -       smtpd


[save and exit]

As we are not configuring postfix in conjuction with a mail server, we don't need further configurations.

systemctl start postfix
systemctl status -l postfix

We not test it. Use addresses verified in SES.

sendmail -f admin@mydomain.au me@gmail.com
From: admin <admin@mydomain.au>
Subject: Postfix Test
This is a test message from AWS Postfix and SES
.



You press return key after typing the full stop "." above. Then WAIT a moment and check with the following command:

mailq
Mail queue is empty

postfix stop

Review what happened in /var/log/mail.log:

cat /var/log/mail.log

Here you see any errors. You may see google reject the email if SPF/DKIM is not configured.
You should also test dkim with mxtoolbox and https://dmarcian.com/dkim-inspector/

You may have a mix of dkim records under CNAME and TXT that are seemingly all correct but one or more may appear to be published but have incorrect syntax. If all typing or cur & paste is correct, you would need to re-build the dkim records and wait some hours to re-test.





 


Postfix on Linux2023


postfix linxu2023

Install postfix on Linux2023

Here is a complete version of postfix /etc/main.cf. See the Debian notes above for the installation and sasl_password tasks. master.cf is the same as well.

For Linux 2023:
Use your own values for hostname and domain, etc. I have put XXX.XXX and mydomain.com below.
Make sure no duplicate values. systemctl start postfix will show if an error, and then use systemctl status -l postfix.
Please follow the notes for Debian 12 above, and then have the contents below for main.cf

cd /etc/postfix
cp -p main.cf main.cf.bak

vi main.cf

compatibility_level = 3.7
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix

# Edit for your own values
myhostname = ec2-XXX-XXX-XXX-XXX.ap-southeast-2.compute.amazonaws.com
mydomain = mydomain.com

myorigin = $mydomain
inet_interfaces = localhost
inet_protocols = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
unknown_local_recipient_reject_code = 550
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

# Edit for your own values - refer to Debian notes above
smtpd_banner = ec2-XXX-XXX-XXX-XXX.ap-southeast-2.compute.amazonaws.com ESMTP mydomain.com (postfix)

debug_peer_level = 2
debugger_command =
         PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
         ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix/samples
readme_directory = /usr/share/doc/postfix/README_FILES

# edit for your own SSL
smtpd_tls_cert_file = /etc/pki/tls/certs/mydomain_com.crt
smtpd_tls_key_file = /etc/pki/tls/private/mydomain_com.key

smtpd_tls_security_level = may
smtp_tls_CApath = /etc/pki/tls/certs
smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt

smtp_tls_security_level = encrypt
shlib_directory = /usr/lib64/postfix
meta_directory = /etc/postfix

# Edit for your email relay service - Oregon for Australia, or you 3rd Party. e.g. MS Exchange could be smtp-mail.outlook.com TLS on port 587, with your email address and password in sasl_pssword.

relayhost = [email-smtp.us-west-2.amazonaws.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_note_starttls_offer = yes

smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks, reject_unauth_destination
smtpd_relay_restrictions = reject_unauth_destination

maillog_file = /var/log/mail.log
smtpd_tls_loglevel = 3

[save and exit]


Example shell script using postfix


example shell script using postfix

Using postfix emails for your server

Linux based systems should permit you to use the wget command. cPanel systems do not.

If you can use wget to retrieve a file from a server, it means https:// is working.
If SSL has expired, this will return an error which you can use to send an email to admin using postfix. You can then check SSL.
Utime Robot is a free service that monitors the website, but it does not let you know if SSL has stopped working.

This script will show how to use postfix.

You basically add a file called up.dat to the domain’s website directory, with the name of the domain.
For instance, on your own server:

cd /var/www/html

vi up.dat
mydomain.com
[save and exit]

Have no blank lines. Use the permissions for your system, e.g. debian or linux2023, using apache/httpd/nginx. I have shown debian's www-data:

chmod 664 up.dat; chown www-data up.dat; chgrp www-dat up.dat

Now add the script to your server, where it will contact itself and the other servers you want.

The servers you wish to contact should each have their own up.dat file.

The following file needs to list all the domains you are checking:

Use /home/admin or /home/ec2-user depending on your operating system.

cd /home/admin

vi up.txt
mydomain.com
your_domain.net
subdomain.mydomain.com.au
[save and exit without blank lines]

Just use the domains you have configured with their own up.dat files.

We now add the shell script:

Replace admin with ec2-user for Linu2023.
Replace admin@mydomain.com me@gmail.com with your own from/to addresses.

cd /home/admin

vi up.sh

#!/bin/bash
echo up.sh: `date` >> /home/admin/info.log

# up.txt website domains
# up.dat file each domain has to validate wget can get it
# up.log where errors are logged with each run of the script

IFS=$'\n'
cd /home/admin
rm -f /home/admin/up.dat >/dev/null 2>&1
:> up.log
err=0
for i in `cat up.txt`
do
wget https://$i/up.dat
if [ -f "/home/admin/up.dat" ] ;
then
rm -f /home/admin/up.dat >/dev/null 2>&1
else
err=1
echo $i >> up.log
fi
done

if [ $err = "1" ] ;
then
/usr/bin/systemctl start postfix
sleep 3
cat /home/admin/up_error.txt > /home/admin/up_tmp.txt
echo "Please check the following website(s) that appear to be unreachable..." >> /home/admin/up_tmp.txt
echo "" >> /home/admin/up_tmp.txt
cat /home/admin/up.log >> /home/admin/up_tmp.txt
echo "" >> /home/admin/up_tmp.txt
echo "." >> /home/admin/up_tmp.txt
echo "" >> /home/admin/up_tmp.txt
# note: admin is a recgnised user on the system and email goes to gmail otherwise it goes to /var/spool/mail/admin
sudo /usr/sbin/sendmail -f admin@mydomain.com me@gmail.com < /home/admin/up_tmp.txt
echo `date` >> /home/admin/info.log
echo "UP SERVICE: AN AWS WEB SERVICE WAS DOWN" >> /home/admin/info.log
 sleep 10
 /usr/bin/systemctl stop postfix
fi

exit

[save and exit]

Notice the script's use of sleep, so that we are not too quick for postfix and leave the email in the queue. mailq will show if the queue is empty. You can look at postfix options to reload and flush.

We now create the up_error.txt file which has the sendmail content: (there is a blank line at the end)

vi up_error.txt
From: admin@shaw-au.net
To: admin@shaw-au.net
Subject: UP SERVICE: An AWS Web service appears to be down.

[save and exit with one blank line at the end of the file, so that sendmail will work]

touch up_tmp.txt
chown root up.* up_*
chgrp admin up.* up_*
chmod 777 up.* up_*

The up.sh script is bash rather than sh. The script will add the domains that it cannot wget up.dat from, and put that into the email.

Test the script with: (my examples always have me logged in as sudo su - root user)

bash -x /home/ec2-user/up.sh

Have a look at the output.

We need to add to crontab. This example shows one test every night at 1:30am.

crontab -e

30 1 * * * sudo bash /home/admin/up.sh >/dev/null 2>&1

[save and exit]

Start typing and press Enter to search