openec2 Article Description

Debian 12, Php8.2, Nginx, Dovecot / Postfix / Opendkim / spamtest, virustest/ spamassassin (spamd) on an Akamai/Linode Server

Debian 12, Php8.2, Nginx, Dovecot / Postfix / Opendkim / spamtest, virustest/ spamassassin (spamd) on an Akamai/Linode Server

UNDER CONSTRUCTION – the remaining piece of work is sieve filter, anti-virus, and anti-spam, which I have working, but not documented just yet. Should be a couple of weeks to finish this doco.

This content has taken a couple of years to explore, finally reaching a working service. All work shown uses an iMac terminal, and the vi editor.

There are so many pieces to install, and they keep being removed, updated etc. Some pieces are not recommended, or have poor documentation.

Also, dovecot may have security fixes that you can’t add until the Debian OS includes the latest version.

When i created one test account, iPhone Mail would not always forward emails – staying in the outbox. Sending new emails works fine. On my second test account it was okay.
iMac NEW Outlook requests the password sign in all the time, so you go to system settings and Internet Accounts and add the account there. Fine after that.
My configurations are for Inbox IMAPS SSL port 993, and Sending STARTTLS Port 587 (Not SSL on 465).

I set the email up to sync directly with my Linode server, rather than Outlook. This way it updates correctly on Linode.

Debian 12, Php8.2, Nginx, Dovecot / Postfix / Opendkim / spamtest, virustest / spamassassin (spamd) on an Akamai/Linode Server


High Level Notes
Is it worth having your own email server?

As a standalone service for one domain and personal use, the cost is higher than using a professional service such as MS Exchange. This is because we choose a basic Linode with backups – AUD $140/year compared to MS Exchange Plan 1 of $80.

If we include our website(s) on the same Linode running Debian 12, email is FREE. I believe that costs are like shopping dockets. They add up significantly over a five year period. Most people do not think this way.

If we wish to use iCloud.com for email, it is about AUD $20 per year to have your own domain configured, but in MS NEW Outlook make sure yu set it up NOT to sync directly with iCloud, or you won;t be able to copy or move, or view source code.

VentraIP cPanel provides email on Axigen, but you have no way of configuring the Axigen options that admin would have. The question on Axigen is performance – it may be too slow as I have noticed for some using cPanel with Axigen behind the scenes, and yet the product itself works fast. I personally think companies have had decades to improve email structure and services. It needs a complete re-write, just like IP6 is a rewrite over IP4. There is appalling structure within emails that you can’t work with, let alone terrible problems with configurations and errors, bounces, security, filtering. I mean, by this time there should have been an amazing email system in place with simple easy to follow GUI configuration screens, but it does not exist. Why has technology gone this way?

MS Exchange is good value, but AUD $80 a year. It has lots of admin panels you have to work through, let alone remember, and to work with WordPress SMTP email, you have to call their help desk to learn how to remove some security settings and permit smtp, again via a number of admin panels. THis is absurd for regular people. But there it is.

If using Amazon, the SES/Lambda/IAM/S3 Bucket system is impractical for me since they removed Node16.x javascript, as no one wrote working programs for filtering and forwarding emails correctly. So, we don’t know what is going on with email under these services. To use an email server on Amazon AWS requires you to remove port restrictions for your region, and if using SES as a relay instead, for that regioun – usually Oregon for Australia. Amazon Workmail is about the same cost as MS Exchange Plan 1, but MS provides more functionality – refer to reviews by users on forums. If you develop your own server, you have to ensure no bad reputation. It is all a lot of work overall.

Akamai/Linode clearly states the problems which I can certainly say has been true for my testing over the last two+ years: https://www.linode.com/docs/guides/email/email-services/

What I am showing here is not for business use, multiple domains and users. Why get involved in potential risks and headaches?

I would suggest that critical emails for financials and government communications be on a professional and hence different email service. For instance, a free account with proton mail has half a Gigabyte available. It is however slower than local email processing and viewing.

But then we have the problem of were data centers are located. Why would I want any risk of email on a server in South Korea. It makes no sense from a best practice point of view. Why would I choose an email provider regardless of the advertising, in China? Why would I want servers with connections through countries with typhoons? Why would I want to pay $15 a month for any number of services where costs should be a couple of dollars? Why would I use any service at all that has adds drop into the inbox. It is complete nonsense that these things are happening.


There is no concise or accurate article or book I am aware of that shows how to install dovecot as an end-to-end solution, with robust/reliable/performance configurations, for your own email server and domain name, integrating the above plugins. I have a working version I would like to share – one domain name, using the TLD (domain.com), not using mail.domain.com, and a low cost Positive DV SSL certificate.

DNS records need CAA entries. If your registrar does not provide this, you would have to move your domain name to other name servers that do, or transfer to another registrar. Akamai/Linode is not a registrar, and their instructions for name servers are too complex, so we will assume you have access elsewhere to CAA records. If I work out these details later, I will add them in post-article notes.

I make use of the Dovecot pigeonhole/seive filter for anti-virus testing, followed by Spamassassin (spamd), followed by Dovecot’s anti-spam – all three processes. We may add filter rules such as whitelisting or blacklisting, but further configurations are up to yourself to explore via Internet articles.

One may configure Amazon AWS SES to receive emails if the Dovecot server goes down.

Dovecot and other services have many options, so on the whole, we configure what works, not spend time figuring out why – it would be too labor intensive and never-ending. We already follow this approach for websites – for instance, we use a limited understanding of Nginx configurations, or for Apache, limited .htaccess configurations.

We must emphasise that technology changes. If the notes here do not work, I cannot help to fix issues. You need good Unix/Linux and problem solving skills. There are many components with their integrations involved – postfix, dovecot, opendkim, SSL, spamassassin, sieve, spamtest, virustest, database, and for web services (if we use them) nginx, php, opcache, memcached, database. We assert you can install Debian 12, and make use of Amazon SES for backup to emails that fail if the system is down. This is a lot.

No development should ever be done on a live server.

Disk swap space and resource use will be higher if co-located with a web server on the same Linode. You can restart website services separately to email services, but I like to refresh disk swap space (swapoff/swapon) as well at midnight via a crontab script if resource use is “too high”. Restarting email services or a reboot of the server could lose emails, hence the need for Amazon SES as a backup. I have other extensive articles that show how to configure SES Email. However, in this case it is not to send email, only receive – meaning we only add DKIM, no use of dmarc, and add an Amazon MX record with lower priority to the DNS.

If we were to explore use of Amazon EC2 instances rather than Linode, we would need to request ports be opened for the region we are in, rather than for Oregon. If in Australia we probably use SES in Oregon. Dovecot would need open ports in Sydney. I have not as yet configured email on EC2 in this manner. When testing Dovecot through SES as the relay and use of S3 Buckets, Dovecot will not work correctly.

It is possible to restart web services without restarting email services, or a swapoff/swapon reset – but I would advise only doing so via Crontab at midnight. Once a service is running, you will not be able to reboot the server without email going offline. Due to any known or unkown risk, we need Amazon SES as a backup service.

I have no notes on major upgrades or added security or more complex email filtering.

You must not manually move or delete Dovecot files. “doveadm” has some administrative options, not explored in this article.

Please configure dmarc@, postmaster@, abuse@, noreply@, webmaster@, admin@ as standard procedure. Manage bounced emails. Do not use the service for marketing or bulk mailouts. Stay in line with Akamai/Linode policies. You can add a sieve filter to drop dmarc emails.

We will keep in mind that some configurations need to be enabled or compiled in order to work. We use log files to watch what happens as we build the system and test it. You would comment out various log files on a live system – up to you. Email clients should send and receive emails without delay – a touch delay as sieve/antispam/antivirus scripts execute.

If using MS Outlook as a client on iMac, the New MS Outlook for iMac will not work first off. You have to configure the email on the Old Outlook, then switch to the New, and then add the email service using the IMAP Sync option. Just going ahead without this option will not work. We will use ports 587 and 993. Currently, New Outlook has too many bugs (as confirmed by MS Support) to use on Windows.

Check you Linode IP address is not blacklisted.

See mxtoolbox.com to test all your configurations. Sometimes a blacklist is temporary.

Have Debian 12 with Nginx fully up and running before installing the email service.

The SSH details below are complicated, but worth knowing how to set up. They ensure your vi editor will work, and you can login in the same way as you would with an Amazon AWS EC2 Linux instance. A Linode root login will not go well with the editing you need to do. Hence why I take time to show the details below.

Request Linode support open the ports for email. Once this is granted, it remains open for any new Linodes you start.

Your request should say you have read their policies, it is a personal email, not for marketing, advertising or bulk email, and is required for use with your website as well. Say you will check ongoing for any bounced emails, and you will configure admin@, postmaster@, webmaster@, abuse@, noreply@, and your primary address, e.g. contact@. This shows you are aware of good practice.

Create a Linode with Backups enabled using Debian 12. Check the IP address is not blacklisted (badly anyway).

Add the A and AAAA records to your DNS. We will do further DNS configs later.

See my other articles on Debian installations to assist in the basics. For disk swap space, add 256MB if you wish, which will go on top of the pre-configured 512MB swap space.

For help on basic installation steps, see https://openec2.com/article-items/debian-11-nginx-part-4-first-configurations/

This next bit is confusing. See how you go. The aim is to have another user for a root privileged login that you can log into and then execute a sudo su command from $myser: to #myuser: so that the vi editor works correctly. (I do all my examples with the vi editor: https://openec2.com/vi-editor/ )

Here is the detail to set up a proper SSH environment:

All examples are based on iMac terminal console and the vi editor.
You need to have already added root to your terminal login capability. (See forums on adding root)

Create Linode Instance, Debian 12 using your firewall rules and a password – lowest cost plan in your region.
Let’s say you assigned the name development. Example below is for Sydney, Australia.

Login to Linode instance using the LISH Console via SSH details from the Linode console from your iMac terminal: (e.g….)

$ su root
# set -o vi

(then use the ssh command here:)

ssh -t XXXX@lish-ap-southeast.linode.com development-ap-southeast

Enter your master Linode password.

Then login as root….

login: root
Enter your instance password. This is the one you assigned, not the master Linode password.

You need to enter these commands for the vi editor.

root@localhost:~# set -o vi
root@localhost:~# export EXINIT=’set noautoindent’
root@localhost:~# export VISUAL=vim

Let’s add a user called ec2-user, to mimick an Amazon Linxu2023 instance login. You can use any name.
If you get an error saying sss_cache…DB version too old, see the notes below this section, then come back.

adduser ec2-user
It asks for a password, and then use null for name details etc.
passwd ec2-user will change the password later if you need to.

cd /etc
vi sudoers

SHIFT-G to get to the end of the file
o to append below the last line
Press ENTER

Manually type: (we cannot cut and paste at this stage)

ec2-user ALL=(ALL:ALL) ALL

ESC SHIFT: w ! to force a write. ESC means the Escape key. SHIFT means the SHIFT key, not the word.
SHIFTZZ (that is, three key sequence of SHIFT key and ZZ characters)

CTRL D to logout

Login as ec2-user then issue the sudo su command. This will be our future pattern for all work.

localhost login: ec2-user
Password:

ec2-user@localhost:~$ sudo su[sudo] password for ec2-user:
root@localhost:/home/ec2-user#

set -o vi
export EXINIT=’set noautoindent’
export VISUAL=vim

vi /etc/vim/vimrc.local –> use i to insert
let skip_defaults_vim = 1
if has(‘mouse’)
set mouse=r
endif

ESC SHIFTZZ to save the file

Edit root and ec2-user’s .bashrc files: use your own domain.com entry.
My notes show where it is obvious that you save a file after editing it.

cd ~
vi .bashrc
export EXINIT='set noautoindent'
export VISUAL=vim
export PS1="[\u@domain.com: \w]\\$ "
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'


cd /home/ec2-user
vi .bashrc
export EXINIT='set noautoindent'
export VISUAL=vim
export PS1="[\u@domain.com: \w]\\$ "
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

vi /etc/sudoers

manually change the previous entry to read:

ec2-user ALL=(ALL) NOPASSWD:ALL

This will mean we do not have to use a password when loggin in with a .pem security file later on.

Add root privileges:

root@localhost:~# usermod -aG adm ec2-user
root@localhost:~# usermod -aG root ec2-user

(Note: linux2023 would use admin, not adm. You can see groups in the /etc/groups file)

We now have to add /home/ec2-user/.ssh and /home/ec2-user/.ssh/authorized_keys

cd /home/ec2-user
mkdir .ssh
ls -la
drwxr-xr-x 2 root root 4096 Sep 24 01:40 .ssh
chown ec2-user .ssh;chgrp ec2-user .ssh; chmod 700 .ssh
ls -la
drwx—— 2 ec2-user ec2-user 4096 Sep 23 16:17 .ssh
cd .ssh

You need to have a .pem file on your PC and corresponding data in the authorized_keys file.

Here is an example:

On your PC add this file: (no blank lines above or below)

vi instance.pem

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA241I7RglQUumLHtbudmPVPvF7h4TbHDM+3aMzTeqVK3ktqN3
trvqyu3PX1W3p1T+taaE2pIHRgoBewpeX4zJAGUnhRjSbtgFCTtNDukhWgn8xyGN
8Yd/RBi2Ns62r7nr50QMvdMO0j4jMcYCcAUpH3hcyvW4TBqLVIWpTum4r78RFoJv
KTCFGY3If00nHUovCfYU082SdD9yVSAEziw/suQGeFinZfJffPYr43+R+tOTrEFG
XeonsZJ4gQML6N6mUN9iK3m4i1vEjOBsH5PPG5UZcKrwPkHzzETDxa97Oc2ke330
6BWoYC4i9vZN19r8xUX6gw4hFPJd36pRzF6m7QIDAQABAoIBAQDEPSqb0WMrU8S6
KaC5I377xPcLeRJ/cOunMDV2EHVMrwmpPb95M8oPjDQ40FMRW+U21BoXi0K5FaRx
J7lmyl223rNOQfuFW8xUjg64bySCaD7qdlF7O1NDuJrVrjqYIyR6V9bTrNyoiyXG
DWiMW/B/0oOOXcdXLrqu17GXeUy8t/Fbim3hD+uHBRkNycUcK29PPxNJb4pDDdgO
/aaKXocI8SoYdW3muK7qoncV5/EpDg+FaFLDo6+GdprwtKckUdfTeLmVakTsk9md
8ib444KcMcdlKhjr/kmvbU/F7r2vHQGkYuSdTO3N5qCeBt7dmLGwAyQ210vOCRcf
7tuLakO5AoGBAPFGsxsMXaulhz+SrASORgH33407Jxm1Y3z2lkSYWyUv/yF2cKbe
Iv1qOlUrSZrNN/DrjsZO1RLrhraUkOpaylCItLO+xUR3neWGya4f1yDJgCqVuSnj
ZPqovYqhFEXHsQDVnUfty9KORCvSLmme1C5b7/tMHFTWAwSENAdzL3irAoGBAOjz
M3ZKRCrON0EFcKgGrgyzoL/UkAt+4xywZxjLgGw6eDg37uoKY+3fFsRoGYuqdd2Y
kgUUmrfRY/gVKShOoMJQwrVs1i50ma9K+3oCzYaqlhEUMCWDHdZ1MebxKpJkhrFm
Pp0xCDT03X/MWwibezcVm3KkOpptkfykeuqam47HAoGAAJEj9ppO1gpriPC1SsVy
0KpechyDeQH+G9sQe1TIUgwM021N0naPKn1Hac/SOnTk/sHu8fRZd9Pp2x/6PzK7
avkHQ6zdFc4aJuHsM2aLwN34WSFE8B5CrHwdBehe/dL8TX4zAmpColoHOvshdMoU
wY8hvztsjZ57H1WYMbRJlkUCgYBNTnBUoD7RCdByZpDFYjoegvokzzDib8CFA9Gi
+93pjNnapk1GJB6XkUJn+bgIjpBA8uH6h6T0vat0Z+lZtAZLliuXs7+8ePuLndGo
4wc72p6kmlOED2g2hHwEDSK4pF3Cv5Cl7+CuWlirkbDgQWD5ndURjYjZOOWKtzcH
ZjmbfwKBgQDbuj5wVVp7HXCmhrHXfDGLg2d09p6HGR3PVJspUUeJJ/OTg6rKF5kB
i9xRlS7M5ApZY1r75VE2zJcHsvcgK763ohuNv+GVrUpyLvDwU6daq1v2KnfeOEe9
wvKfRBKzyhotebwB3gw3v8z4X1UdBbAnvZQhcnZgZPbO/WISbDGL0A==
-----END RSA PRIVATE KEY-----

On the Linode instance, in .ssh:

vi authorized_keys

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbjUjtGCVBS6Yse1u52Y9U+8XuHhNscMz7dozNN6pUreS2o3e2u+rK7c9fVbenVP61poTakgdGCgF7Cl5fjMkAZSeFGNJu2AUJO00O6SFaCfzHIY3xh39EGLY2zravuevnRAy90w7SPiMxxgJwBSkfeFzK9bhMGotUhalO6bivvxEWgm8pMIUZjch/TScdSi8J9hTTzZJ0P3JVIATOLD+y5AZ4WKdl8l989ivjf5H605OsQUZd6iexkniBAwvo3qZQ32IrebiLW8SM4Gwfk88blRlwqvA+QfPMRMPFr3s5zaR7ffToFahgLiL29k3X2vzFRfqDDiEU8l3fqlHMXqbt instance

You can add multiple lines with similar entries. You can research the Internet on how to create the above data.

YOU NEED TO REPLACE THE ABOVE CODE – which works – WITH YOUR OWN ASAP. I provided the code so you can test and see what works. Refer to Linode SSH documentation.

ls -l
-rw-r–r– 1 root root 389 Sep 24 01:44 authorized_keys
chown ec2-user *;chgrp ec2-user *; chmod 600 *
ls -l
-rw——- 1 ec2-user ec2-user 792 Sep 23 16:17 authorized_keys

Now logout and destroy your terminal, open a new one on your iMac, and type in the ssh command where the instance.pem file is located. e.g…..

# ssh -i “instance.pem” ec2-user@xxx.xxx.xxx.xxx where xxx is your Linode IP address.

If you have conflict with your existing or previous ssh logins, use this command or as a script:

:>/var/root/.ssh/known_hosts

Then try ssh again from where the instance.pem file is located. (You can put this into a script)

# ssh -i “instance.pem” ec2-user@xxx.xxx.xxx.xxx
ec2-user@xxx.xxx.xxx.xxx’s password:
Linux localhost 6.1.0-25-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.106-3 (2024-08-26) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Sep 24 01:54:11 2024 from 144.6.125.35[ec2-user@shawlw.me: ~]$ sudo su[root@mydomain.com: /home/ec2-user]# set -o vi

At this stage we are still typing a password. Also note, the vi editor now works correctly with editing and mouse scrolling and ec2-user operates as root.

To fix this on yur Linode instance:

vi /etc/ssh/sshd_config
PermitRootLogin yes
PasswordAuthentication no

systemctl restart sshd

It will now work when you log back in.

If issues around this, see Linode articles on using SSH.

——————————————————————————————————————————-

DB version too old error:

If you get this error:
——————————-[sss_cache] [sysdb_domain_cache_connect] (0x0010): DB version too old [0.22], expected [0.23] for domain implicit_files!
Higher version of database is expected!
In order to upgrade the database, you must run SSSD.
Removing cache files in /var/lib/sss/db should fix the issue, but note that removing cache files will also remove all of your cached credentials.
Could not open available domains
——————————–
To fix this, do the following:
cd /var/lib/sss/db
rm *
sss_cache -E

——————————————————————————————————————————-

THE ABOVE REPRESENTS IMPORTANT INITIAL LINODE CONFIGURATIONS

We can now commence work…

——————————————————————————————————————————-

These are the ports you open in your Linode firewall:

22 (memcached), 80 (http), 443 (https), 53 (dns), 587 (smtpd), 993 (imaps), 11211 (memcached – for nginx)

We do not need to open 25, 465 – and possibly things will still work without 587 as that would be opened up from the Linode support team.

Add your own static IP address to Port 22 for SSH. e.g. xxx.xxx.xxx.xxx/32
Memcached uses 127.0.0.0/16.

We use port 53 (which may already be opened – not sure) for the Nameservers that find email service domains from 8.8.8.8, and 1.1.1.1 (Google and Cloudflare).

These are some first steps you may take for your DNS Records:

If you plan to use Amazon SES as a backup for the event your email goes down, you would have added an SES domain in Oregon (for Australia) with DKIM but no DMARC, as we are only receiving emails as a downtime backup. The DNS record would be: (don;t do this unless you ahve those setps in place along with the S3 bucket, as per my other articles)

mydomain.com MX inbound-smtp.us-west-2.amazonaws.com 3600 30 -> 30 gives a lower priority to the live service that we actually want.

Your actual MX record, as we are not using mail.mydomain.com, is:

mydomain.com MX mydomain.com 3600 10 -> 10 give the higher priority.

Add the SPF record:

mydomain.com TXT v=spf1 ip4:xxx.xxx.xxx.xxx ip6:yyyy:yyyy::yyyy:yyyy:yyyy:yyyy ~all 3600. -> where xxxx and yyyy are the IP4 and IP6 addresses under your Linode’s network tab. (You click on the Linode’s title in blue to get this menu of tabs – which includes backups.) Notice on this tab the Reverse DNS string which will user later in Postfix’s main.cf file.

Add the DMARC records:

*._report._dmarc.mydomain.com TXT v=DMARC1 3600
_dmarc.mydomaincom TXT v=DMARC1;p=quarantine;pct=25;rua=mailto:dmarc@mydomain.com 3600

We will later configure a sieve filter in Dovecot to drop the dmarc emails, unless you really want to capture them to some other folder than the INBOX.

We will want dkim to be added by default to all of our outbound emails:

_adsp._domainkey TXT dkim=all 3600

The default._domainkey.mydomain.com TXT record will be configured when we use opendkim.
It will look like this:

v=DKIM1; h=sha256; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlC/d8/83skStRTVz1POx…….. and so on.

Some DNS services have to break up the length of the p= record by using multiple lines. We will show how to test the opendkim DNS record later.

Your SSL certificates need a CAA record. If using sectigo:

mydomain.com CAA 0 issue sectigo.com
mydomain.com CAA 0 issue digicert.com

I have not tested Let’s Encrypt with the SSL processes that Dovecot uses. If these fail due to incompatibility, you will need a low cost SSL certificate. The entry for Let’s Encrypt is 0 issue letsencrypt.org

When using Amazon SES as the backup, you will have three CNAME records provided by SES.
They look like this:

6hl7melvoc3lxxxxxxxxxxxxxxxxxxxx._domainkey.mydomain.com CNAME 6hl7melvoc3lxxxxxxxxxxxxxxxxxxxx.dkim.amazonses.com

If using a website, you would have a CNAME record pointing www.mydomain.com to mydomain.com

Sectigo allows you to add an authorisation key rather than using admin@mydomain.com, which looks something like this:

_ab28c553cbf6xxxxxxxxxxxxxxx.mydomain.com CNAME xxxxxxxxxxx0494B75456DE54ED2.o5U5855xxxxxxxxxxx.sectigo.com (This sort of thing)

You can check DNS records are pulished with “dns checker” but sometimes your PC needs more time, or at least clear the browser cache.

Note:

It is best to see my other articles for installing Debian, nginx, and memcached in case some parts are missing below. It is a little bit all over the place below, but you should be familiar with installing Debian anyway.

If /var/www or /var/www/html does not exist after installing, just make the directories with chmod 2775 and nginx permissions, and add a dummy /var/www/html/index.html file with any wording in it, with chmod 664. If phpMyAdmin does not work, go to root and check no files with ownership apache exist that may need changing to nginx. e.g. cd /; ls -lRa | grep apache | more

Debian also requires:
apt install libsasl2-modules

First we install the basics for a web service on the same Linode instance. I am installing php8.2.

As a reminder, –> comments and [comments] may be included in the coding that I show. All commands unless otherwise shown are from the root shell, or in this case ec2-user who has root access.

[We add another 256MB to the pre-built 512MB swap space]

echo "vm.swappiness=10" >> /etc/sysctl.conf
echo "vm.vfs_cache_pressure=200" >> /etc/sysctl.conf
sysctl -w vm.swappiness=10
sysctl -w vm.vfs_cache_pressure=200
free -m
dd if=/dev/zero of=/swapfile bs=1024 count=262144
mkswap /swapfile
chmod 0600 /swapfile
swapon /swapfile
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab
free -m

[Use your own Country/City. See /usr/share/zoneinfo]

a="Australia/Brisbane";export a;echo $a
ln -sf /usr/share/zoneinfo/$a /etc/localtime
date

apt update
apt upgrade

apt install software-properties-common ca-certificates lsb-release gnupg2 mariadb-server
apt install php8.2-cli php8.2-mbstring php8.2-xml php8.2-common php8.2-curl php8.2-imap php8.2-bz2
apt install php8.2-mysqli php8.2-fpm gcc libjpeg* zip php8.2-zip

[Can be useful for PDF documents:]

apt install php8.2-gd

[For certbot/lets encrypt:]
[If having installation issues, you should probably "sync;sync;reboot" your instance or at least reboot at some stage.]

apt install python3-venv
apt install php8.2-xmlrpc php8.2-soap php8.2-intl
python3 -m venv /opt/certbot/
/opt/certbot/bin/pip install --upgrade pip
/opt/certbot/bin/pip install certbot
ln -s /opt/certbot/bin/certbot /usr/bin/certbot
apt install certbot

apt install libgd-tools ipset net-tools






We should configure mariadb at this point. If mariadb is running, the following will execute. Otherwise, use the command “systemctl start mariadb”.

mysql_secure_installation
"Enter current password for root" (enter for none): 
OK, successfully used password, moving on...
"Switch to unix_socket authentication [Y/n]"  n
"Change the root password?" [Y/n] Y
(nominate your database password)
Y for the remaining questions]

[Note that we now start and enable our mariadb and php8.2-fpm services. Enabling means they start at a reboot.]

systemctl stop mariadb
systemctl start mariadb
systemctl enable mariadb

Install latest version of nginx: (I have other articles on Apache2 and Linux2023 httpd)

Refer to https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/

[Assuming we have ec2-user. Otherwise, /home/admin]

cd /home/ec2-user

apt install curl ca-certificates lsb-release debian-archive-keyring

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

[This is the verification output:]

pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
      573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid                      nginx signing key <signing-key@nginx.com>

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
    | sudo tee /etc/apt/preferences.d/99nginx

sudo apt update
sudo apt install nginx

cd /etc/nginx
ls

systemctl enable nginx

[remove apache packages if they are hanging around:]

apt remove *apache*

This would be a good point at which to reboot the instance.

Notes: php.ini’s Dynamic section should not need an entry to use memcached.so as we did in Linux2023 configurations.

Systemctl status -l commands are useful to check all services.

Remember you have to enable and start php8.2-fpm for nginx to work, and we use systemctl reload php8.2-fpm rather than a restart,

and systemctl enable memcached with a restart to start using it.

A useful script:

cd /home/ec2-user

vi restart.sh

#!/bin/sh
free -m
systemctl stop nginx
systemctl stop mariadb
systemctl stop memcached
systemctl reload php8.2-fpm
systemctl start mariadb
systemctl start memcached
systemctl start nginx
swapoff -a
swapon -a
free -m
systemctl status -l nginx
systemctl status -l mariadb
systemctl status -l php8.2-fpm
systemctl status -l memcached
exit

[save and exit]

chmod 777 restart.sh

[test it:]

./restart.sh

If you have an SSL certificate, please install into /etc/ssl/certs and /etc/ssl/private. Set your DNS CAA record(s).
If using Let’s Encrypt, please see my articles on that method. That can’t be setup without nginx installed with a CAA record for letsencrypt.org.

Please see my next article for the php, phpMyAdmin, memcached, opcache configurations.

Please modify php.ini, www.conf for use of memcached – see https://openec2.com/article-items/nginx-memcached/

Please see my article for installing ngix – see https://openec2.com/article-items/debian-11-nginx-part-7-nginx-ssl/

As you see, there is always a lot of pre-planning.

WE ARE NOW READY TO CONFIGURE DOVECOT

We will configure the basics before adding filters and anti-virus/anti-spam configurations.

You should not need to do this step, but in case: (use your ip4 address and domain name – we are not using mail.domain.com in our example. If your intended MX record were to be mail.domain.com you’d need an SSL certificate for that and modify the installation details.)

vi /etc/hosts

xxx.xxx.xxx.xxx domain.com

I don’t use pop3, but I have installed it. All logins via root.

apt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql

[Select "Internet Site" when prompted - ENTER key will let the install continue]
[Change localhost to your domain (email domain)]

You previously did the database and phpMyAdmin installation, so you can use that service to create the database, admin user, password, and tables.

Otherwise, see:

https://www.linode.com/docs/guides/email-with-postfix-dovecot-and-mysql/

I use utf8mb4_general_ci and utfgmb4 – you can choose otherwise if you wish.

Create a database called mailserver

Create a user called mailuser

Add full permissions for mailuser and root to mailserver

If using utfbmb4, modify the settings shown in the URL above, and you must change password` varchar(106) to (150) for a larger password.

Use these settings (from the URL above) in the phpMyAdmin SQL section (highlight the mailserver database first)

CREATE TABLE `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

[Once done, do the next SQL command:]

CREATE TABLE `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `password` varchar(150) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


[And then the next:]

CREATE TABLE `virtual_aliases` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `source` varchar(100) NOT NULL,
  `destination` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

[Next SQL: replace domain.com with your mail server domain, e.g. in my example, domain.com, remembering I am not going a step further and configuring mail.domain.com in my examples]

INSERT INTO mailserver.virtual_domains (name) VALUES ('domain.com');

[Now create a password and paste it into an editor so yu can use it further below]

doveadm pw -s SHA512-CRYPT

[Next SQL: replace the word hash with your password, and user@domain.com with your. primary email user address]

INSERT INTO mailserver.virtual_users (domain_id, password , email) VALUES ('1', 'hash', 'user@domain.com');

[Next SQL: add an alias. You can repeat for more, or use phpMyAdmin to copy and edit]

INSERT INTO mailserver.virtual_aliases (domain_id, source, destination) VALUES ('1', 'admin@domain.com', 'user@domain.com');


[You can test all this worked as follows: with your own user, alias, domain names]

SELECT * FROM mailserver.virtual_domains;

[You should see the number 1 - our example are not dealing with multiple domains at this stage]

SELECT * FROM mailserver.virtual_users;

SELECT * FROM mailserver.virtual_aliases;

Initially we will get a plain version of Dovecot and Postfix working. Then we will add Opendkim for dkim records.

As we add features, like dkim and anti-spam, we will revisit various configuration files.  Always replace domain.com with your own domain, and users or IP addresses.

**** IMPORTANT *****
Please use the critical fixes section below for the main.cf master.cf and opendkim.conf files rather than the content shown here for these fiiles.

When you have spf, dkim/dmarc working, then modify files below to add sieve and spamassassin. I know this is a bit of a mess, but it works.

You can’t use New Outlook to view all the headers as it does not show them all.
********************

Please copy the following to your /etc/postfix/main.cf file (always make an original backup first – e.g. cp -p FILE FILE.o

Ensure there are no repeated lines. If so, the log files will pick this up. You check settings with systemctl restart postfix or whatever service you test, followed by systemctl status -l postfix. You need to widen the terminal screen to see the full results.

cd /etc/postfix
cp -p main.cf main.cf.o
cp -p master.cf master.cf.o

[Here is the content for main.cf. 
Do not use repeat lines - the log files will show if there is an error. You check with systemctl restart postfix and systemctl status -l postfix. Widen your terminal screen to see the output.
I have put domain.com in CAPS so you can replace. The opendkim entries are initially commented out. LINODE_SMTPBANNER is the reverse pointer address in the network tab in Linode.
e.g. xxx-xxx-xxx-xxx.ip.linodeusercontent.com. For instance, xxx-xxx-xxx-xxx.ip.linodeusercontent.com ESMTP snotbat.com postfix -> you could test replacing postfix with another word.
Use your own values for: smtpd_tls_cert_file= and smtpd_tls_key_file=. I have not tested Let's Encrypt certificates for any incompatibiltites.]


# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

# smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_banner = LINODE_SMTPBANNER ESMTP DOMAIN.COM postfix
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 3.6 on
# fresh installs.
compatibility_level = 3.6

# TLS parameters - USE YOUR OWN SSL CERTIFICATE AND DIRECTORY LOCATIONS. E.G. /etc/letsecnrypt/live/domain.com/fullchain.pem and ..../privkey.pem, or /etc/ssl/certs/... and /etc/ssl/private/...
smtpd_tls_cert_file=/etc/ssl/certs/DOMAIN_COM.crt
smtpd_tls_key_file=/etc/ssl/private/DOMAIN_COM.key
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous

# Authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

# Restrictions
smtpd_helo_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_recipient,
        reject_unknown_recipient_domain,
        reject_unlisted_recipient,
        reject_unauth_destination,
        check_policy_service unix:private/policyd-spf
smtpd_sender_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_sender,
        reject_unknown_sender_domain
smtpd_relay_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        defer_unauth_destination

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = DOMAIN.COM
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydomain = DOMAIN.COM
myorigin = $mydomain
mydestination = localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# Handing off local delivery to Dovecot's LMTP, and telling it where to store mail
virtual_transport = lmtp:unix:private/dovecot-lmtp

# Virtual domains, users, and aliases
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf,
        mysql:/etc/postfix/mysql-virtual-email2email.cf

# Even more Restrictions and MTA params
disable_vrfy_command = yes
strict_rfc821_envelopes = yes
#smtpd_etrn_restrictions = reject
#smtpd_reject_unlisted_sender = yes
#smtpd_reject_unlisted_recipient = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtp_always_send_ehlo = yes
#smtpd_hard_error_limit = 1
smtpd_timeout = 30s
smtp_helo_timeout = 15s
smtp_rcpt_timeout = 15s
smtpd_recipient_limit = 40
minimal_backoff_time = 180s
maximal_backoff_time = 3h

# Reply Rejection Codes
invalid_hostname_reject_code = 550
non_fqdn_reject_code = 550
unknown_address_reject_code = 550
unknown_client_reject_code = 550
unknown_hostname_reject_code = 550
unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550

# original
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
myhostname = DOMAIN.COM
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
# myorigin = /etc/mailname.  WE DO NOT USE THIS
# mydestination = $myhostname, DOMAIN.COM, localhost.localdomain, localhost.localdomain, localhost  WE DO NOT USE THIS
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# opendkim
policyd-spf_time_limit = 3600

# Milter configuration
# OpenDKIM -> WE WILL UNCOMMENT THESE LINES AFTER OPENDKIM IS INSTALLED AND READY FOR TESTING

  # milter_default_action = accept
  # milter_protocol = 6
  # smtpd_milters = inet:localhost:8891
  # non_smtpd_milters = $smtpd_milters

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

# mail_home = WE DO NOT USE THIS VARIABLE


Configure master.cf (we will add more to this later)

cd /etc/postfix

[These are the contents of master.cf. We will uncomment milter and spamassassin later. Options always have two space characters before them, so when uncomenting, do so.]

#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd
  -o content_filter=spamassassin
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
#  -o content_filter=spamassassin
smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
#  -o content_filter=spamassassin

pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
#qmgr     unix  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd

# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#

uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)

#
# Other external delivery methods.
#
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
dovecot unix - n n - - pipe
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
policyd-spf  unix  -       n       n       -       0       spawn
  user=policyd-spf argv=/usr/bin/policyd-spf
# spamassassin unix -     n       n       -       -       pipe
  # user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Create the virtual mailbox postfix entries:

cd /etc/postfix

[Replace MAILUSER_PASSWORD with your own mailuser database password - this is visible plain text, and not encrypted]

vi mysql-virtual-mailbox-domains.cf

user = mailuser
password = MAILUSER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

[save and exit]

vi mysql-virtual-mailbox-maps.cf

user = mailuser
password = MAILUSER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

[save and exit]

vi mysql-virtual-alias-maps.cf

user = mailuser
password = MAILUSER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

[save and exit]

vi mysql-virtual-email2email.cf

user = mailuser
password = MAILUSER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT email FROM virtual_users WHERE email='%s'

[save and exit]



The above file permissions should be okay. e.g. -rw-r–r– 1 root root 143 Sep 26 10:17 mysql-virtual-alias-maps.cf

We should not need to alter /etc/postfix permissions. If you get errors, you can run “postfix set permissions” -> good to keep this in your install notes.

We will configure dovecot before we restart and test services.

[We are of course logged in with root permission # in the shell]

cd /etc/dovecot

cp -p /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
cp -p /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
cp -p /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
cp -p /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.orig
cp -p /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig
cp -p /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig

[I am only showing the uncommented lines. Replace with your own domain name:]

vi /etc/dovecot/dovecot.conf

import_environment = $import_environment PR_SET_DUMPABLE=1
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap lmtp
postmaster_address = postmaster at DOMAIN.COM
listen = *, ::
dict {
  #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}
!include conf.d/*.conf
!include_try local.conf

[save and exit]

vi /etc/dovecot/conf.d/10-mail.conf

# mail_location = mbox:~/mail:INBOX=/var/mail/%u
mail_location = maildir:/var/mail/vhosts/%d/%n/
mail_privileged_group = mail

[Save and Exit]

[Make the vhosts email directory for yuor primary email address and domain: e.g. /var/mail/vhosts/snotbat.com/fred]

cd /var/mail
mkdir vhosts
mkdir domain.com
cd domain.com
mkdir PRIMARY_USER

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail

cd /var/mail
sudo chown -R vmail:vmail /var/mail

chown vmail vhosts;chgrp vmail vhosts

For user, I had: drwx--S--- 16 vmail vmail 4096 Sep 26 09:15 info (for info@.....) but while installing for this article, I had drwxr-sr-x 2 vmail vmail 4096 Sep 26 14:24 laurie

cd /etc/dovecot/conf.d

/etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = yes
auth_mechanisms = plain login
!include auth-system.conf.ext
!include auth-sql.conf.ext

[save and exit]

vi 20-imap.conf

mail_location = maildir:/var/mail/vhosts/%d/%n/

[save and exit]

More configurations:

cd /etc/dovecot/conf.d

vi /etc/dovecot/conf.d/auth-sql.conf.ext

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

#userdb {
#  driver = prefetch
#}

# userdb {
  # driver = sql
  # args = /etc/dovecot/dovecot-sql.conf.ext
# }

userdb {
  driver = static
  #args = uid=vmail gid=vmail home=/var/vmail/%u
  args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

[save and exit]

cd /etc/dovecot

[Use your database mailuser password below - not the encrypted version, and the password_query is shown exactly as needed]
vi /etc/dovecot/dovecot-sql.conf.ext

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=MAILUSER_PASSWORD
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

[save and exit]

cd /etc
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
ls -l|grep dovecot
drwxr-x--- 4 vmail    dovecot   4096 Sep 26 14:47 dovecot





 

We now get into the dovecot services configurations.

cd /etc/dovecot/conf.d

[Be careful to configure this correctly. Obviously the ... dots are not to be in the config file. You don't have to enable POP3 if not using pop. I see no reason to use it.]

vi /etc/dovecot/conf.d/10-master.conf

...
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
  ...
}
...
service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}
...

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    #mode = 0666i
    mode = 0600
    user = postfix
    group = postfix
  }
...
}

service auth {
  ...
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }

  # Postfix smtp-auth
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
  }

# Auth process is run as this user.
  # user = $default_internal_user
  user = dovecot

}
...

service auth-worker {
  # Auth worker process is run as root by default, so that it can access
  # /etc/shadow. If this isn't necessary, the user should be changed to
  # $default_internal_user.
  #user = root
  user = vmail
}

[save and exit]

[If using Let's Encrypt/certbot, you would use /etc/letsencrypt/live/domain.com/fullchain.pem and private.pem. Use your own domain name and SSL file name for other certificates.]

vi /etc/dovecot/conf.d/10-ssl.conf

ssl = required

# ssl_cert = </etc/dovecot/private/dovecot.pem
# ssl_key = </etc/dovecot/private/dovecot.key

ssl_cert = </etc/ssl/certs/domain_com.crt
ssl_key = </etc/ssl/private/domain_com.key [save and exit] The certificate names and path must exist and be the same in the postfix main.cf file. [We have postfix logging already in /var/log/mail.log. We can always benefit by using a terminal shell with "tail -f /var/log/mail.log" for testing. You can empty it with ":> /var/log/mail.log" to see only new entries]
[We will now set dovecot logging. REMEMBER - you have to revisit main.cf and 10-logging.conf to turn these off/on or to change the level of details in the logged events.]

vi /var/log/dovecot.log

[Enter a bank line]
[save and exit]

cd /etc/dovecot/conf.d

vi /etc/dovecot/conf.d/10-logging.conf

mail_debug = yes
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot.log
debug_log_path = /var/log/dovecot.log

[save and exit]

[If you want more extensive logging, add: (it is a bit much)]

auth_verbose = yes
auth_verbose_passwords = no
auth_debug = yes
auth_debug_passwords = yes
verbose_ssl = yes


[Install test emailing softeware:]

apt-get install mailutils

systemctl restart postfix
systemctl restart dovecot

systemctl status -l postfix
systemctl status -l dovecot

[If you have an error, the status command will let you now what you mispelt or did wrong.]

[We do not enable the services just yet as we have no blacklisting or open port security installed as yet. If you read my articles with the blacklist.sh and ports, that can help. I'll show the main shell script for open ports here:]

cd /home/ec2-user (or whatever is your shell login with root access)

vi ports.sh

#!/bin/sh
iptables -A INPUT -p tcp --syn --dport 443 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 2 -j DROP
iptables -A INPUT -p tcp --syn --dport 587 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 993 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 465 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 143 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 25 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 53 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 7000 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 8000 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 9443 -m connlimit --connlimit-above 5 -j DROP
iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 5 -j DROP
iptables -L -vn
exit

[save and exit]

chmod 777 /home/ec2-user/ports.sh

./ports.sh

[This script can clean it all out so yu can start over again. These settings will be absent after a reboot.]

vi firewall.sh
#!/bin/bash
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
exit

[save and exit]

chmod 777 firewall.sh






Now we send a test email. I have given some dummy names. Use your vhosts email address and domain, and send to another email service like gmail.

You must have the DNS records set as per the early part of this article, and gmail does require the AAAA record with Linode instances.

[You can set up additional terminal shells and use the tail -f command rather than "cat" as shown below]

[From 2 other terminals:]

tail -f /var/log/mail.log
tail -f /var/log/dovecot.log

echo "Email body text" | sudo mail -s "Email subject line" ME@gmail.com -aFrom:fred@snotbat.com





This test email takes a while for Gmail to register it. Future emails are quicker. The email has sparse content as we do not have our opendkim set up as yet.

NOTE: At this stage spf is not working. The next installation steps will do this.

I added a Firefox recommended configuration /etc/dovecot/conf.d:

vi 15-ssl-intermediate.conf


##
## Dovecot SSL settings with Intermediate compatibility
## Follows Mozilla's Security/Server Side TLS guidelines
## https://wiki.mozilla.org/Security/Server_Side_TLS
##

##
## Optionial:
##   Disable 3DES ciphersuites to prevent CVE-2016-2183
##     by appending ":!3DES" to the ssl_cipher_list
##   Disable TLSv1 for PCI compliance as of June 30, 2018
##     by appending " !TLSv1" to the ssl_protocols for versions < 2.3 ## by changing ssl_min_protocol to "TLSv1.1" for versions >= 2.3
##

# ciphersuites
ssl_cipher_list = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS

# for dovecot >= 2.3
# ssl_min_protocol = TLSv1
# for dovecot >= 2.3
ssl_min_protocol = TLSv1.2

# DH parameter size
# for dovecot < 2.3 #ssl_dh_parameters_length = 2048 # for dovecot >= 2.3
# ssl_dh =

There are other settings that are no longer used in the above file. You can check for errors even when dovecot starts ok, by looking at the dovecot.log file.

You have to run postfix set-permissions to see errors.

*** IMPORTANT ***
MS New Outlook will not show all headers. You have to use another client, or use iCloud on the web to view headers.
These will show if the opendkim is working.
*****************

The final main.cf file is shown here where there were some errors to comment out.
These errors stopped port 587 working.
You must use:
netstat -tulpn|grep 587
tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN 11023/master
tcp6 0 0 :::587 :::* LISTEN 11023/master

to verify port 587 is open. If it should be, but Amazon blocks it, take it out of sandbox mode for your region.The master.cf file:

/etc/postfix/main.cf:

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname
# smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_banner = Lec2-54-79-232-121.ap-southeast-2.compute.amazonaws.com ESMTP shawlw.me postfix
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 3.6 on
# fresh installs.
compatibility_level = 3.6
# TLS parameters - USE YOUR OWN SSL CERTIFICATE AND DIRECTORY LOCATIONS. E.G. /etc/letsecnrypt/live/domain.com/fullchain.pem and ..../privkey.pem, or /etc/ssl/certs/... and /etc/ssl/private/...
smtpd_tls_cert_file=/etc/ssl/certs/shawlw_me.crt
smtpd_tls_key_file=/etc/ssl/private/shawlw_me.key
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
# Authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
# Restrictions
smtpd_helo_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_recipient,
        reject_unknown_recipient_domain,
        reject_unlisted_recipient,
        reject_unauth_destination,
        check_policy_service unix:private/policyd-spf

smtpd_sender_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_sender,
        reject_unknown_sender_domain
smtpd_relay_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        defer_unauth_destination
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
myhostname = shawlw.me
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydomain = shawlw.me
myorigin = $mydomain
mydestination = localhost
# relayhost =
# mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
# mailbox_size_limit = 0
# recipient_delimiter = +
 inet_interfaces = all
 inet_protocols = all
# Handing off local delivery to Dovecot's LMTP, and telling it where to store mail
virtual_transport = lmtp:unix:private/dovecot-lmtp
# Virtual domains, users, and aliases
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf,
        mysql:/etc/postfix/mysql-virtual-email2email.cf
# Even more Restrictions and MTA params
disable_vrfy_command = yes
strict_rfc821_envelopes = yes
#smtpd_etrn_restrictions = reject
#smtpd_reject_unlisted_sender = yes
#smtpd_reject_unlisted_recipient = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtp_always_send_ehlo = yes
#smtpd_hard_error_limit = 1
smtpd_timeout = 30s
smtp_helo_timeout = 15s
smtp_rcpt_timeout = 15s
smtpd_recipient_limit = 40
minimal_backoff_time = 180s
maximal_backoff_time = 3h
# Reply Rejection Codes
invalid_hostname_reject_code = 550
non_fqdn_reject_code = 550
unknown_address_reject_code = 550
unknown_client_reject_code = 550
unknown_hostname_reject_code = 550
unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550
# original
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
# myorigin = /etc/mailname.  WE DO NOT USE THIS
# mydestination = $myhostname, DOMAIN.COM, localhost.localdomain, localhost.localdomain, localhost  WE DO NOT USE THIS
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
# opendkim
# 3600 line does not work:
# policyd-spf_time_limit = 3600
# Milter configuration
# OpenDKIM -> WE WILL UNCOMMENT THESE LINES AFTER OPENDKIM IS INSTALLED AND READY FOR TESTING
   milter_default_action = accept
   milter_protocol = 6
#   smtpd_milters = inet:localhost:8891
smtpd_milters = local:opendkim/opendkim.sock
non-smtpd_milters = local:opendkim/opendkim.sock
   # non_smtpd_milters = $smtpd_milters
maillog_file = /var/log/mail.log
smtpd_tls_loglevel = 3
smtp_tls_loglevel = 3
# mail_home = WE DO NOT USE THIS VARIABLE


master.cf:

/etc/postfix/master.cf

#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd
#  -o content_filter=spamassassin
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
#  -o content_filter=spamassassin
smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
#  -o content_filter=spamassassin
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
#qmgr     unix  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
dovecot unix - n n - - pipe
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
policyd-spf  unix  -       n       n       -       0       spawn
  user=policyd-spf argv=/usr/bin/policyd-spf
# spamassassin unix -     n       n       -       -       pipe
  # user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Other things to check:

The previous listing of main.cf and master.cf should be ok.

/etc/dovecot/dovecot.conf already has protocols but still put in the protocols line:

# Enable installed protocols
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap lmtp

Install the opendkim software:

apt-get install opendkim opendkim-tools postfix-policyd-spf-python postfix-pcre
adduser postfix opendkim

This will already be configured:

vi /etc/postfix/master.cf
policyd-spf  unix  -       n       n       -       0       spawn
  user=policyd-spf argv=/usr/bin/policyd-spf

  [We should also previously have added to the last two lines of the main.cf "smtpd_recipient_restrictions =" stanza:]         
reject_unauth_destination,
check_policy_service unix:private/policyd-spf

main.cf: (we do not do sieve or spamassassin at this point)
milter_default_action = accept
   milter_protocol = 6
  # NOT USING JUST YET - IT MAY WORK IF /etc/opendkin.conf has the same line for Socket: smtpd_milters = inet:localhost:8891   AND   non-smtpd_milters = inet:localhost:8891
smtpd_milters = local:opendkim/opendkim.sock
non-smtpd_milters = local:opendkim/opendkim.sock


do the opendkim.conf file as per my article. No TrustedChain.


/etc/default/opendkim - comment out everything:
RUNDIR=/run/opendkim
SOCKET=local:$RUNDIR/opendkim.sock
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

/etc/opendkim.conf:

Syslog                  yes
SyslogSuccess           yes
LogWhy                  no
Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no
OversignHeaders         From
Domain                  YOUR_DOMAIN (e.g. snotbat.com)
KeyFile                 /etc/opendkim/keys/default.private
KeyTable                /etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table
ExternalIgnoreList /etc/opendkim/trusted.hosts
InternalHosts /etc/opendkim/trusted.hosts
AutoRestart     yes
AutoRestartRate     10/1M
Background      yes
DNSTimeout      5
SignatureAlgorithm  rsa-sha256
# Socket                  inet:8891@localhost
Socket local:/var/spool/postfix/opendkim/opendkim.sock
PidFile             /run/opendkim/opendkim.pid
Nameservers             8.8.8.8,1.1.1.1
#Selector               2020
#KeyFile                /etc/dkimkeys/example.private
UserID                  opendkim
UMask                   002
#Socket                 local:/run/opendkim/opendkim.sock
#Socket                 inet:8891@localhost
#Socket                 inet:8891
#Socket                 local:/var/spool/postfix/opendkim/opendkim.sock
#PidFile                        /run/opendkim/opendkim.pid
# Hosts for which to sign rather than verify, default is 127.0.0.1. See the
# OPERATION section of opendkim(8) for more information.
#InternalHosts          192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12
# The trust anchor enables DNSSEC. In Debian, the trust anchor file is provided
# by the package dns-root-data.
# TrustAnchorFile               /usr/share/dns/root.key
#Nameservers            127.0.0.1


[save and exit]

create /etc/opendkim/keys: drwx------ 2 opendkim opendkim 4096 Oct 25 14:09 keys

create keys.table signing trusted and so on as per my article.


NO: vi /etc/systemd/system/multi-user.target.wants/opendkim.service
PIDFile=/var/run/opendkim/opendkim.pid
I don't think this would work so not done.


Make /var/spool/postfix/opendkim drwxrwxr-- 2 opendkim opendkim 4096 Oct 25 14:13 opendkim
I don't think drwxr-xr-x 2 opendkim postfix  4096 Sep 20 10:35 opendkim is correct ?

cd /etc/opendkim/keys

opendkim-genkey -b 2048 -h rsa-sha256 -r -s default -d domain.com -v
[e.g. opendkim-genkey -b 2048 -h rsa-sha256 -r -s default -d snotbat.com -v]
ls
cat default.key
default._domainkey    IN    TXT    ( "v=DKIM1; h=rsa-sha256; k=rsa; s=email; "      "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1P1dFPOOKzQp14icgeNbl7WeqUiks7JZUpxTbNz8ofV3O8iKb6xX3HFXcWhyeAi1OyYx0WhaLX0H8mhZGXomwawFJe9O3JbWN0LM+Z1GUG6i+K0El4qUrt8Ox2Gk0K377A07mXjjdKwJKQs6siIygbxpzbojaPYKDHz4PaYORann27vukObfp1nEXrdKtiOmUpNoBqqW6d5hk/"
      "iM6tozBa2AzzBoZ9rNz+ysl+ttn AND SO ON......  DKIM key default for domai


Add to the mx record with the correct p= value.

systemctl daemon-reload
systemctl restart postfix
systemctl restart dovecot
systemctl restart opendkim

PORT 587 is not knocked out ! ???

netstat -tulpn|grep 587


fix main.cf - remove duplicate inet_interfaces and no such thing as inet_protocols so remove it. postfix set-permissions can show problems and /var/log/mail.log

Should fix port 587. Check with  netstat -tulpn|grep 587



chown -R opendkim:opendkim /etc/opendkim
chmod go-rw /etc/opendkim/keys

   I don't think we use chown opendkim:postfix /var/spool/postfix/opendkim as postfix is added to opendkim


Recreate in old MS outlook, then New outlook

Old Outlook will show the dkim, spf, dmarc headers working. iCloud Webmail can also show the headers fully. New Outlook will not (!)
















WE HAVE COMPLETED THE BASIC DOVECOT SETUPS.

Next we look at opendkim, then the filtering/anti-virus/anti-spam setups.

It will be vital to return to this section after configs are done below in the section titled “SPF DKIM DMARC – opendkim”. Then come back here.

Use https://www.linode.com/docs/guides/configure-spf-and-dkim-in-postfix-on-debian-9/ as your reference. I think the notes here will work though.

What we want is to use all the configs for chown, chgrp, chmod.
Otherwise we get errors from “journalctl –follow –unit postfix.service –unit opendkim.service” when we send emails.
Also, using the DNS Checker website, you should see port 993 open, but on Amazon AWS while in sandbox mode, port 587 will time out.

Then, here are the final configurations for sockets and various config files you need to change. This is why you must return back to this section of my notes to tidy up the configs.

vi /etc/postfix/main.cf

# policyd-spf_time_limit = 3600
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock
non_smtpd_milters = local:opendkim/opendkim.sock

[save and exit]

The two entries for masgter.cf   -o milter_macro_daemon_name=ORIGINATING must be uncomments and remember the two shite spaces before -o

cd /etc/default

[everything to be commented except the following:]

vi opendkim
RUNDIR=/run/opendkim
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

[save and exit]

cd /etc
[Everything else to be commented out:]

vi opendkim.conf

Syslog                  yes
SyslogSuccess           yes
LogWhy                  no
Mode                    sv
OversignHeaders         From
Domain                  YOUR_DOMAIN (e.g. domain.com)
KeyFile                 /etc/opendkim/keys/default.private
KeyTable                /etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table
ExternalIgnoreList /etc/opendkim/trusted.hosts
InternalHosts /etc/opendkim/trusted.hosts
AutoRestart     yes
AutoRestartRate     10/1M
Background      yes
DNSTimeout      5
SignatureAlgorithm  rsa-sha256
Socket  local:/var/spool/postfix/opendkim/opendkim.sock
PidFile             /run/opendkim/opendkim.pid
Nameservers             8.8.8.8,1.1.1.1
UserID                  opendkim
UMask                   002
PidFile                 /run/opendkim/opendkim.pid

[saave and exit]


chmod u=rw,go=r /etc/opendkim.conf
chown -R opendkim:opendkim /etc/opendkim
chmod go-rw /etc/opendkim/keys
chown -R opendkim:opendkim /etc/opendkim
chmod -R go-rwx /etc/opendkim/keys
cd /etc
chown -R opendkim:opendkim /etc/opendkim
chmod -R go-rw /etc/opendkim/keys
chown opendkim:postfix /var/spool/postfix/opendkim

postfix set-permissions

Good idea to reboot, or at least restart opendkim, postfix, dovecot.

When sending an email from an existing account to your server, use two terminal shells with:

cd /var/log
tail -f mail.log

AND on 2nd terminal

journalctl --follow --unit postfix.service --unit opendkim.service

You can check the service file is ok:

cat /usr/lib/systemd/system/opendkim.service

[Unit]
Description=OpenDKIM Milter
Documentation=man:opendkim(8) man:opendkim.conf(5) man:opendkim-lua(3) man:opendkim-genkey(8) man:opendkim-genzone(8) man:opendkim-testkey(8) http://www.opendkim.org/docs.html
After=network-online.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/opendkim/opendkim.pid
ExecStart=/usr/sbin/opendkim
ExecReload=/bin/kill -USR1 $MAINPID
Restart=on-failure

[Install]
WantedBy=multi-user.target

I found too many issues trying to install on Linux 2023. The above is all on Debian 12 ARM.

/etc/postfix/main.cf has the line “policyd-spf_time_limit = 3600” but we have not installed software for it.

Also make sure your DNS Records are configured as shown at the top of this article.

apt-get install opendkim opendkim-tools postfix-policyd-spf-python postfix-pcre
adduser postfix opendkim

[Add the following to the end of master.cf and have two spaces before user=policyd-spf IF NOT ALREADY ADDED - it should be there from previous steps]

vi /etc/postfix/master.cf
policyd-spf  unix  -       n       n       -       0       spawn
  user=policyd-spf argv=/usr/bin/policyd-spf

[We should also previously have added to the last two lines of the main.cf "smtpd_recipient_restrictions =" stanza:]         

reject_unauth_destination,
check_policy_service unix:private/policyd-spf

systemctl restart postfix
systemctl restart dovecot

[Send an email to an existing address you own, using your new primary user@domain.com address:]

echo "Email body text" | sudo mail -s "Email subject line" me@myemail.com -aFrom:info@domain.com

[This is a good point at which to tail -f the mail.log and dovecot.log files. Check your Inbox, view the raw code, and you should see:]

Received-SPF: Pass


Important note: we see some documentation saying to use /var/run/opendkim/opendkim.pid as the PidFile or PIDFile.
/var/run is a softlink to /run, so do not configure this way. Only use /run/opendkim/opendkim.pid.

Opendkim and Milter will not work unless you ensure these couple of steps:

THESE MUST BE CHECKED AFTER THE CONFIGURATIONS BELOW

cd /etc/opendkim/keys
chown opendkim:opendkim *
ls -l

Make sure /run/opendkim/opendkim.pid is used in: /etc/systemd/system/multi-user.target.wants/opendkim.service
which I think is a soft link to /usr/lib/systemd/system/opendkim.service -> make sure it uses /run and not /var/run

cd cd /run/opendkim
chown opendkim:opendkim *
ls -l

and check /etc/opendkim.conf uses:
PidFile                 /run/opendkim/opendkim.pid

I believe -rw-r--r-- 1 root root    5 Sep 28 14:08 opendkim.pid can remain as root. 

IF EMAILS GET no DKIM signing, it means milter is not being executed.

If the first attempt to a gmail address did not work, but the logs show it should have, send again. Google may be determining if a new address is safe.

Your gmail raw source code should show: “received-spf: pass (google.com: domain of ….”

Next – opendkim. This was messy, but I got there in the end.

vi /etc/default/opendkim and comment out everything. We want none of it. e.g. RUNDIR, SOCKET, USER – comment all of these out.

cd /etc
cp -p opendkim.conf opendkim.conf.o

[Uncomment and modfiy various values as shown, and use your domain name. Recall, I am not doing mail.domain.com configurations in this article.]
[We use 8891 as shown for the socket, and /var/run in the PidFile for this Debian12 installation]

vi /etc/opendkim.conf

LogWhy                  no
Mode                    sv
SubDomains              no
Domain                  domain.com
KeyFile                 /etc/opendkim/keys/default.private
KeyTable                /etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table
ExternalIgnoreList /etc/opendkim/trusted.hosts
InternalHosts /etc/opendkim/trusted.hosts
AutoRestart     yes
AutoRestartRate     10/1M
Background      yes
DNSTimeout      5
SignatureAlgorithm  rsa-sha256
Socket                  inet:8891@localhost
PidFile             /run/opendkim/opendkim.pid
Nameservers             8.8.8.8,1.1.1.1

[save and exit]

[You need to create a directory /etc/opendkim, with the permissions shown here...]

cd /etc
mkdir opendkim
chmod 755 opendkim; chown opendkim opendkim; chgrp opendkim opendkim;

drwx------ 2 opendkim opendkim  4096 Sep 27 10:20 dkimkeys
drwxr-xr-  2 opendkim opendkim  4096 Sep 27 11:52 opendkim
-rw-r--r-- 1 root     root      2529 Sep 27 11:50 opendkim.conf
-rw-r--r-- 1 root     root      2104 Nov 26  2023 opendkim.conf.o

Under /etc/opendkim, create these:

drwx------ 2 opendkim opendkim 4096 Sep 20 10:23 keys
-rw-r--r-- 1 opendkim opendkim   67 Sep 20 10:22 key.table
-rw-r--r-- 1 opendkim opendkim   26 Sep 20 10:21 signing.table
-rw-r--r-- 1 opendkim opendkim   58 Sep 20 10:22 trusted.hosts

[IMPORTANT: the word default is what we will use for dmarc values, e.g. default._domainkey.domain.com and the default.private key in the DNS Records. You can have other names though if it matches the tables, DNS and key names you create]

vi key.table

default domain.com:default:/etc/opendkim/keys/default.private

[save and exit]

[Again, use your own domain name, and the use of "default" as mentioned above:]

vi signing.table

*@domain.com default

[save and exit]

[Of course, if you work out how to do multiple domains, or mail.domain.com, these values may differ: (use your own domain name)]

vi trusted.hosts

127.0.0.1
::1
localhost
domain.com
*.domain.com

[save and exit]


We will create default.private and default.txt under /etc/opendkim/keys. One could use /etc/opendkim/…./keys or anything really, so long as it is referenced correctly elsewhere, which you will see during these configurations.

[Do this fix:]

vi /etc/systemd/system/multi-user.target.wants/opendkim.service

PIDFile=/var/run/opendkim/opendkim.pid

[save and exit]

[I'm not sure why I did the next step...]

mkdir /var/spool/postfix/opendkim

[Make permissions:]
drwxr-xr-x 2 opendkim postfix  4096 Sep 20 10:35 opendkim

[Create the default keys for your domain.com name - use your own domain.]

cd /etc/opendkim/keys
pwd

opendkim-genkey -b 2048 -h rsa-sha256 -r -s default -d domain.com -v

[e.g. opendkim-genkey -b 2048 -h rsa-sha256 -r -s default -d snotbat.com -v]

ls

cat default.key

default._domainkey	IN	TXT	( "v=DKIM1; h=rsa-sha256; k=rsa; s=email; "	  "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1P1dFPOOKzQp14icgeNbl7WeqUiks7JZUpxTbNz8ofV3O8iKb6xX3HFXcWhyeAi1OyYx0WhaLX0H8mhZGXomwawFJe9O3JbWN0LM+Z1GUG6i+K0El4qUrt8Ox2Gk0K377A07mXjjdKwJKQs6siIygbxpzbojaPYKDHz4PaYORann27vukObfp1nEXrdKtiOmUpNoBqqW6d5hk/"
      "iM6tozBa2AzzBoZ9rNz+ysl+ttn AND SO ON......  DKIM key default for domain.com


In the above key, I have shown domain.com, but it must be your own domain.

We take this content and place in your DNS record…

[Add your own record, e.g. default._domainkey.snotbat.com TXT and so on. There must be no double quotes in the p=section, but some registrars require you to make multiple lines for the p value. See your own registrar's instructions, and it they need quotes.]
[Sample:]

default._domainkey.domain.com    TXT   v=DKIM1; h=sha256; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1P1dFPOOKzQp14icgeNblasdjhss7JZUpxTbNz8ofV3O8iKb6xX3HFXcWhyeAi1OyYx0WhaLX0H8mhZGXomwawFJe9O3JbWN0LM+Z1GUG6i+K0El4qUrt8Ox2Gk0K377A07mXjjdKwJKQs6siIygbxpzbojaPYKDHz4PaYORann27vukObf AND SO ON...

Now uncomment the lines we previously used in /etc/postfix/main.cf

milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = $smtpd_milters

Uncomment the lines we placed previously in /etc/postfix/master.cf

[Under submission inet n       -       y       -       -       smtpd, and use twp space characters before it:]

  -o milter_macro_daemon_name=ORIGINATING

[Under smtps     inet  n       -       -       -       -       smtpd:]

  -o milter_macro_daemon_name=ORIGINATING

[We still have spamassasin commented out]

[Save and exit]

[Now run these commands...]


systemctl daemon-reload
systemctl restart postfix
systemctl restart dovecot
systemctl restart opendkim

ps -ef | grep opendkim

opendkim   25872       1  0 12:31 ?        00:00:00 /usr/sbin/opendkim
opendkim   25873   25872  0 12:31 ?        00:00:00 /usr/sbin/opendkim

systemctl status -l opendkim

[Test your opendkim key: use your own domain name and dmarc id - in this case I have configured for "default._domainkey.domain.com]

opendkim-testkey -d domain.com -s default default.private -vvv

opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/opendkim/keys/default.private
opendkim-testkey: checking key 'default._domainkey.shawlw.me'
opendkim-testkey: key not secure
opendkim-testkey: key OK

[The key not secure above is meant to be this way.]

We will not be too concerned with systemctl status -l opendkim just yet, but do run the command.

** FIXES **

Below I mentioned user_prefs to stop DNS warnings in spamd.log, but it seems it is to do with nameservers 8.8.8.8 and 1.1.1.1 and so on.

So I tried removing all of them, and then no error message, and removing 1.1.1.1 which I think is Cloudflare, and was ok.

WE HAVE COMPLETED THE SPF DKIM DMARC SETUPS.

Next we configure basic filtering/anti-virus/anti-spam setups – we use both the dovecot spam and the spamassassin setups.

[Install sieve filters]

apt-get install dovecot-sieve
apt-get install dovecot-managesieved
apt install dovecot-antispam

[We will create a simplistci default:]

cd /var/mail/vhosts

vi default.sieve

require ["fileinto"];

require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
  fileinto "Junk";
}

[save and exit]

ls -l
-rw-r--r-- 1 vmail vmail  107 Sep 21 11:44 default.sieve

[You always need to compile sieve...]

sievec ./default.sieve

ls -l
-rw-r--r-- 1 root  vmail  256 Oct  2 09:19 default.svbin

[Create sieve rules under the user's email. Replace dmarc@domain.com with your own.
There are too many rules to go over this. See internet forums. Note the logic needs to know when to stop processing, or you get multiples of the same email in yur folders.
You will be able to block bad users. I have not looked into IP address blocking, but your blacklisted ports in nginx can take of that.]

cd /var/mail/vhosts/domain.com/USER

vi .dovecot.sieve

require ["fileinto", "envelope", "subaddress", "comparator-i;ascii-numeric","relational", "spamtestplus", "virustest"];


/* Other messages get filed into INBOX */

/* Not scanned ? */
 if virustest :value "eq" :comparator "i;ascii-numeric" "0" {

/*    fileinto "Unclassified"; */
      /* fileinto "Quarantine"; */
      /* stop; */

/* Infected with high probability (value range in 1-5) */
} elsif virustest :value "eq" :comparator "i;ascii-numeric" "4" {
    /* Quarantine it in special folder (still somewhat dangerous) */
    fileinto "Quarantine";
    stop;

/* Definitely infected */
} elsif virustest :value "eq" :comparator "i;ascii-numeric" "5" {
    /* Just get rid of it */
/*    discard; */
    fileinto "Quarantine";
    stop;
}


if header :contains "X-Spam-Flag" "YES" {
  fileinto "Junk";
  stop;
}
if header :contains "X-Spam-Level" "**********" {
  discard;
  stop;
}
if address :is "from" "dmarc@mydomain.com"
{
    discard;
    /* fileinto "History"; */
    stop;
}
if envelope :detail "to" "spam"{
  fileinto "Junk";
  stop;
}

/* If the spamtest fails for some reason, e.g. spam header is missing, file
 * file it in a special folder. */
if spamtest :value "eq" :comparator "i;ascii-numeric" "0" {
/*    fileinto "Unclassified"; */
      fileinto "Inbox";
      stop;

/* If the spamtest score (in the range 1-10) is larger than or equal to 3,
 * file it into the spam folder: */
} elsif spamtest :value "ge" :comparator "i;ascii-numeric" "9" {
    fileinto "Junk";
    stop;

/* For more fine-grained score evaluation, the :percent tag can be used. The
 * following rule discards all messages with a percent score
 * (relative to maximum) of more than 85 %: */
} elsif spamtest :value "gt" :comparator "i;ascii-numeric" :percent "95" {
/*    discard; */
    fileinto "Quarantine";
    stop;
}

[save and exit]

At this point it will not compile, as we have other software to install and configure.
We will need to do it later with this command:

sievec ./.dovecot.sieve

ls -la


Let’s configure some files:

[Under the plugin section, comment out and add the lines as shown:]

cd /etc/dovecot/conf.d

vi 90-sieve.conf

  sieve = ~/.dovecot.sieve
sieve_global_dir = /var/mail/vhosts
 # sieve_global_path = /var/mail/vhosts --> did not work, had to use _dir
  sieve_dir = ~/sieve
  sieve_default = /var/mail/vhosts/default.sieve
#  sieve = file:~/sieve;active=~/.dovecot.sieve


[Then at the bottom of the file before the last } bracket, add these lines: there are various versions of what to do here - you'd have to research it. These confis are for dovecot's virust and spam testing. We will also install spamassassin as first line of defence further below.]

sieve_extensions = +spamtest +spamtestplus +virustest

  sieve_spamtest_status_type = score
  sieve_spamtest_status_header = \
    X-Spam-Score: score=(-?[[:digit:]]+\.[[:digit:]]).*
  sieve_spamtest_max_header = \
   X-Spam-Score: score=-?[[:digit:]]+\.[[:digit:]] required=([[:digit:]]+\.[[:digit:]])

  sieve_virustest_status_type = text
  sieve_virustest_status_header = X-Virus-Scan: Found to be (.+)\.
  sieve_virustest_text_value1 = clean
  sieve_virustest_text_value5 = infected


[save and exit]

[Add the sieve plugin in the lmtp stanza]
[antispam below is if dovecot-antivirus is installed - perhaps can go in 20-imap.conf if not here]
vi 20-lmtp.conf

protocol lmtp {
  mail_plugins = $mail_plugins sieve antispam
}

[save and exit]

[We previously added logging to 10-logging.conf]

[Add postmaster to 15-lda.conf. Use your won domain. We have to do this.]

vi 15-lda.conf

postmaster_address = postmaster@domain.com

[save and exit]

[We need to create an sieve directory under the user's email location]

cd /var/mail/vhosts/domain.com/USER
mkdir sieve
chmod 2777 sieve
chgrp vmail sieve
ls -l
drwxrwsrwx  2 root  vmail  4096 Sep 21 10:34  sieve


We will install spamassassin.

After installing spamassassin, some ***** CRITICAL FIXES ****

Remove pyzor:

apt remove pyzor

(Otherwise errors on spamd.log)

Add "imap4flags" to the required list in .dovecot.sieve and recompile it.
Then you can use: addflag "\\Seen";   for emails you want marked as read.

/usr/share/spamassasin:

60_whitelist cannot use wildcards. Not sure yyet how we block domains???

local.cf:

use:  required_score 10.0

Do the same for /etc/spamassassin/local.cf

vi /etc/dovecot/conf.d/90-sieve.conf	

In the plugin section:

#  sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_extensions = +spamtest  +spamtestplus +virustest +virustestplus
  sieve = ~/.dovecot.sieve
  sieve_global_path = /var/mail/vhosts
  sieve_dir = ~/sieve
  sieve_default = /var/mail/vhosts/default.sieve


Before the last curly bracket at the end: (I'm not sure why we have a difference to .dovecot.sieve as yet)

sieve_extensions = +spamtest +spamtestplus +virustest
  sieve_spamtest_status_type = score
  sieve_spamtest_status_header = \
    X-Spam-Score: score=(-?[[:digit:]]+\.[[:digit:]]).*
  sieve_spamtest_max_header = \
   X-Spam-Score: score=-?[[:digit:]]+\.[[:digit:]] required=([[:digit:]]+\.[[:digit:]])
  sieve_virustest_status_type = text
  sieve_virustest_status_header = X-Virus-Scan: Found to be (.+)\.
  sieve_virustest_text_value1 = clean
  sieve_virustest_text_value5 = infected
# sieve_spamtest_max_value = 10.0

We can't use the sieve_spamtest_max_value = 10.0 line with the above configs.


/etc/dovecot/conf.d/20-lmtp.conf:

protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  #mail_plugins = $mail_plugins
mail_plugins = $mail_plugins sieve
#postmaster_address = postmaster@shawlw.me
}

I don't yet have the spamassasin cron timer file working. It is disabled by default.
It does not help that there was a change from spamassassin to spamd in the configurations. However…

apt insall libgssapi-perl  razor pyzor libencode-detect-perl libgeoip2-perl libnet-patricia-perl libbsd-resource-perl
apt-get --install-recommends install spamassassin

[Check spamc is installed after this]

groupadd spamd
useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd
mkdir /var/log/spamassassin
chown spamd:spamd /var/log/spamassassin

vi /etc/default/spamd

CRON=1
ENABLED=1
SAHOME="/var/log/spamassassin/"
OPTIONS="--create-prefs --max-children=5 --helper-home-dir=/var/lib/spamassassin --username=spamd --syslog=/var/log/spamassassin/spamd.log"

PIDFILE="/run/spamd.pid"

[save and exit]

[There are variations on the above]

sudo mkdir /var/log/spamassassin && sudo chown spamd:spamd /var/log/spamassassin


vi /etc/logrotate.d/spamassassin

/var/log/spamassassin/spamd.log {
      copytruncate
      rotate 12
      weekly
      compress
      missingok
      postrotate
        /bin/systemctl restart spamd.service > /dev/null
      endscript
  }

[save and exit]

[Change spamassassin to spamd:]

vi /etc/cron.daily/spamassassin

test -f /etc/default/spamd && . /etc/default/spamd

[save and exit]

[For convenience:]

cd /var/log
ln -s /var/log/spamassassin/spamd.log spamd.log
ls -l

systemctl restart spamd
systemctl status -l spamd
systemctl enable spamd

[This takes a while"]
sa-update

:>/var/log/spamassassin/spamd.log

systemctl restart spamd

[Wait a moment...]
cat /var/log/spamd.log

[Append to the postfix master.cf file:]

vi /etc/postfix/master.cf

spamassassin unix -     n       n       -       -       pipe
  user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

[save and exit]

[Change spam rating from 5 to 10.]

cd /usr/share/spamassassin

vi local.cf

# required_score 5.0
required_score 10.0

[save and exit]

[Examples of white and black listing, but also add the pyzor line as shown. This is a new file]

vi 60_whitelist.cf
# whitelist_auth me@gmail.com you@gmail.com
# blacklist_from ..... ....

use_pyzor 0

[save and exit]

[Now we return to /var/mail/vhosts/domain.com/user:]

sievec .dovecot.sieve

[Restart all services and check the status with -l.
Here is a helpful script:]

vi /home/ec2-user/post.sh

#!/bin/sh

systemctl stop opendkim
systemctl stop dovecot
systemctl stop postfix
systemctl stop spamd

systemctl start opendkim
systemctl start spamd
systemctl start postfix
systemctl start dovecot

systemctl status -l opendkim > tmp.txt
systemctl status -l postfix >> tmp.txt
systemctl status -l dovecot >> tmp.txt
systemctl status -l spamd >> tmp.txt

cat tmp.txt

exit

[save and exit]
chmod 777 /home/ec2-user/post.sh

cd /home/ec2-user
./post.sh



After more use of spamassassin, it is /etc/spamassassin/local.cf you need to configure for changes to spam level 10.0

Also, your spamd.log may show a warning about pyzor if you have not removed pyzor.

And, it may show these messages which you can remove:

Sat Oct 26 12:55:40 2024 [7639] warn: check: dns_block_rule RCVD_IN_ZEN_BLOCKED_OPENDNS hit, creating /var/log/spamassassin/.spamassassin/dnsblock_zen.spamhaus.org (This means DNSBL blocked you due to too many queries. Set all affected rules score to 0, or use “dns_query_restriction deny zen.spamhaus.org” to disable queries)
Sat Oct 26 12:55:40 2024 [7639] warn: check: dns_block_rule RCVD_IN_DNSWL_BLOCKED hit, creating /var/log/spamassassin/.spamassassin/dnsblock_list.dnswl.org (This means DNSBL blocked you due to too many queries. Set all affected rules score to 0, or use “dns_query_restriction deny list.dnswl.org” to disable queries)

To remove this, either whitelist your domain with the above entities, or use a “score” of 0 as follows:

cd /var/log/spamassassin/.spamassassin
cp -p user_prefs /var/mail/vhosts/YOUR_DOMAIN/YOUR_USER/user_prefs

You can of course just manuallu edit a new file instead of copying


vi /var/mail/vhosts/YOUR_DOMAIN/YOUR_USER/user_prefs

score RCVD_IN_ZEN_BLOCKED_OPENDNS 0
score RCVD_IN_DNSWL_BLOCKED 0

[save and exit]

You will not longer see those spamd.log messages.

[save and exit]
Microsoft has a proprietary format for Mime attachments used by older mail servers. There should be no need to use a filter for tnef today.

As usual, online documentation is really thin, without good explanations of what is going on, or applicable to current software.

After reviewing this, I found no ability to install TNEF. It is available in Axigen.

TNEF mime attachments need to be converted back to normal formats.

These are the apt packages:

apt-get install libconvert-tnef-perl libfile-mmagic-perl libmime-tools-perl
We cannot use it as it eats up all the swap space and freezes the system.

apt install clamav clamav-daemon
https://wiki.debian.org/ClamAV
https://medium.com/@wingsuitist/set-up-clamav-for-osx-1-the-open-source-virus-scanner-82a927b60fa3
https://vpsie.com/knowledge-base/how-to-install-clamav-on-debian-12/

https://askubuntu.com/questions/1413657/clamav-make-freeze-to-laptop

To replace antispam with IMAPSieve as per doc.dovecot.org/2.3 (search on antispam)
Try removing apt antispam, and see if a received Email still has a Virus line in the raw source code, which means you don;t need the package.

MS TNEF Decoder / and check emails are base 64, not open html.

quota in imap and lmtp .conf files?

Fix .dovecot.sieve to put spam etc. into junk folder instead of dropping, for testing.

Where to block *@domain.com entries?

use of mail.domain.com, not domain.com

Multi Domains – how, as the above configs have some specific references to postmaster, and domain.com

Dovecot dictionary ??

Dovecot cleanups

Can we use a soft link ln -s on say the archive or a new History folder where emails would be encrypted on the Amazon EFS disk?

The .time cleanups not tested as yet.

Keep an eye on swap space.

Can we monitor and drop bad IP addresses from spam?

How to implement grey listing? (ClamAV not acceptable) – Denial of Service to look more into

If system down, using S3 bucket as the backup with a generic S3 email notifying of an email

MS New Outlook – still asking for password if dovecot is restarted – what about exiting the app and coming back in ? Not an issue in Old Outlook

CHeck deleted emails still show the body text extract