Changes for page How to setup a postfix SMTP server
Last modified by Alexandru Pentilescu on 2025/02/09 14:17
From version 13.1
edited by Alexandru Pentilescu
on 2024/07/02 20:17
on 2024/07/02 20:17
Change comment:
There is no comment for this version
To version 8.1
edited by Alexandru Pentilescu
on 2024/05/19 14:28
on 2024/05/19 14:28
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -5,10 +5,7 @@ 5 5 6 6 But why do we even need an SMTP server in the first place? Well, we don't really need one but, at the end of the day, it's very handy to have one, nonetheless. 7 7 8 -{{toc/}} 9 - 10 -= How does email work? = 11 - 8 += How does email work?= 12 12 Email works on different levels but the general gist of it is that it all boils down to SMTP servers acting as the backbone of all email providers. 13 13 SMTP is a protocol that allows email servers to send an email from one another, either encrypted with TLS on port 25 using the STARTTLS command, or even in plaintext. 14 14 Email clients, i.e. most of the software used to access the emails from one's inbox, use retrieval protocols such as POP3 or IMAP to access the SMTP server and download the relevant emails off the server onto the local machine to display them. ... ... @@ -25,8 +25,7 @@ 25 25 26 26 Excited yet? Well, you should be! In this guide, I'll configure a special type of service called Postfix. Let's start! 27 27 28 -= Postfix configuration = 29 - 25 += Postfix configuration= 30 30 I'll skip the installation part, as that's distro dependent. Moreover, it's been so long since I installed Postfix on my machine that I cannot remember the exact details so that I can write them down in the first place. 31 31 32 32 As such, please follow whatever online guide you can find for your particular Linux distro on how to install and initially configure Postfix. These should be very common. ... ... @@ -94,7 +94,6 @@ 94 94 Basically, what this means is that, all your docker services need to have their IPs listed in this parameter for Postfix to relay their emails further. This is mandatory. If you omit any docker service's IP from this list, that service will not be able to use Postfix as its SMTP server to relay email even if the Postfix server is technically reachable by it via ICMP echo packets. 95 95 96 96 == Getting the right IP list == 97 - 98 98 To find the IP address for a specific docker container, please run "docker inspect <container_id>" and then look up the "IPAddress" field from the resulting output, under the "Networks" JSON property. Note: it's not the "Gateway" field, that's something else! 99 99 100 100 Please be aware, though, that docker allocates IPs dynamically. So even if a container has a specific IP at one point, it doesn't mean that it will have the same IP next time a new container is spawned from the same image (i.e. after a system reboot). As such, this can, in theory, mean that your configuration will work at one point but, after a system reboot, it won't work anymore. This would mean that you either have to specify manual static IP addresses for your docker images so that they will always take the exact same IP all the time (not recommended and it goes against the entire philosophy of docker) or, you can just do what I did and simply whitelist all the possible private IPs under "172.16.0.0/12". This basically resolves to all the 16 continous class B private IP addresses in the IPv4 address space, as seen [[here>>https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses]]. --Docker will, by default, use IPs in a subrange in this address space, when allocating IPs to newly spawned containers.-- As I have found out recently, this may not be the case. Docker can use any private IP address that it wishes to use and, as such, it's best to not rely on this. ... ... @@ -128,7 +128,6 @@ 128 128 In a docker configuration, assuming the services are using a "bridge" network driver, they will all have their own IP addresses in the aforementioned address space, and these addresses will be distinct from the proper address of the machine where Postfix is installed. As such, they need a target to resolve to reach the machine running Postfix. This target will be IP 172.16.0.1. **IMPORTANT note: if you'll use TLS enabled in Postfix, please avoid using the raw IP address as mentioned here, as certain services like Nextcloud check the domain of the SMTP server against the TLS certificates being provided and, if they mismatch, it will reject the connection. This is why I added the "mail.transistor.one" hostname in there, as my TLS certificate is against all subdomains under *.transistor.one and, as such, can be verified successfully by it**. When configuring each individual docker service, enter that IP as the IP of the SMTP server to use, as well as port 25, as its connection port. These should be the only parameters you should need to configure everything to work properly. 172.16.0.1 was a random address that I decided on. Really, it has no real relevance and can be changed to any private IPv4 address, whether in class B, C or A. The only point is that it should be reachable through this network driver. 129 129 130 130 = Instructing Postfix to relay emails through Google's servers, instead = 131 - 132 132 Assuming that running your own postfix server is a pain in the ass (especially since it's quite difficult to get DMARC or other authenticity mechanisms configured by yourself), a proper workaround for that is to simply rely on a third party emailing service to relay your emails for you. 133 133 134 134 This has the benefit of being somewhat easier to use and configure, but with the obvious downside that you will need to have an already existing email address on that service to send the emails through. ... ... @@ -156,17 +156,11 @@ 156 156 157 157 The contents of my "/etc/postfix/config" file looks like this: 158 158 [smtp.gmail.com]:587 <username@gmail.com>:<app_password> 153 +I think I might have needed to generate this file using a postfix utility or something, although I'll assume that writing it by hand can also work. 159 159 160 -Once this file has been written, please run the following utility to generate the necessary files: 161 - 162 -{{code language="bash"}} 163 -postmap /etc/postfix/config 164 -{{/code}} 165 - 166 166 Once this is configured and ready to go, you can safely restart the postfix service and rely on Google to relay your emails for you. 167 167 168 168 = Configuring the Postfix service such that it always restarts when the system is running low on RAM = 169 - 170 170 This has been a major pain in the butt for me. 171 171 172 172 Every so often, I would visit one of my services after a long period of being away and then would request for a password to be delivered to me from them, only to then find out that no email is being received. ... ... @@ -194,40 +194,9 @@ 194 194 195 195 From that, the only genuinely relevant changes that need to be highlighted are the last two lines (i.e. the "Restart" and "RestartSec" assignments). These tell systemd that that, in the event that the service gets killed due to an abnormality (i.e. it receives a SIGKILL system because it is running low on RAM), to automatically restart it. The second rule (i.e. "RestartSec"), tells it to wait an entire second before performing the restart, so that it gives the system the chance to finish whatever it was doing. 196 196 197 -= Opening up port 587 for SMTP traffic = 185 += Troubleshooting issues with Postfix reachability from docker containers= 186 +If whichever docker container you're currently running doesn't seem to connect to 172.17.0.1 and its image contains the ping utility pre-installed in it, you can attach your current terminal session into that container and access it via "docker exec -it <docker_container_id> /bin/bash" and then simply issuing a "ping 172.17.0.1" to send ICMP echo packets to your SMTP server from inside the container itself. If there are replies, this means the container can reach your local Postfix server so the problem is most likely from Postfix dropping the requests intentionally. Alternatively, this could be a firewall misconfiguration problem but this has never happened to me before, although I recognize that it may be theoretically possible. 198 198 199 -Certain services refuse to accept STARTTLS traffic on port 25, as is open, by default, on Postfix (looking at you, Gitea). To account for them, we must open port 587 to attain this. To do so, we must open the master.cf configuration file (mine was under "/etc/postfix/master.cf") and add the following line: 200 - 201 -{{code}} 202 -smtp inet n - y - - smtpd 203 -587 inet n - n - - smtpd 204 -{{/code}} 205 - 206 -The smtp line was already there. I only added the 587 line. This instructs Postfix to bind itself to the 587 port, such that, any services wanting to reach that port in order to start a STARTTLS connection, wil be able to do so. 207 - 208 -Once this is done, restart the Postfix daemon with a systemctl restart command and everything should almost be done. Almost. 209 - 210 -Ubuntu server also comes preinstalled with a firewall utility that will deny traffic towards its own port 587. This can be an impediment. As such, please allow traffic from your docker containers to be able to reach this port: 211 - 212 -{{code language="bash"}} 213 -sudo ufw allow from 172.16.0.0/16 to any port 587 214 -{{/code}} 215 - 216 -If you recall from above, 172.16.0.0/16 was the IP range we configured for our docker engine to use when assigning IPs to its container networks. So that command will effectively allow all traffic originating from docker containers to be explicitly allowed to reach the host's own 587 port, to be able to initiate a STARTTLS encrypted channel. 217 - 218 -While you're on it, you may also do 219 - 220 -{{code language="bash"}} 221 -sudo ufw status numbered 222 -sudo ufw delete <rule number for opening port 25> 223 -{{/code}} 224 - 225 -to delete the firewall rules that allow full access to port 25. This solved an issue where Google would spam my Gmail inbox with unnecessary garbage because it was trying to relay bounced email notifications to me, which was highly annoying to say the least. 226 - 227 -= Troubleshooting issues with Postfix reachability from docker containers = 228 - 229 -If whichever docker container you're currently running doesn't seem to connect to 172.17.0.1 or to mail.transistor.one and its image contains the ping utility pre-installed in it, you can attach your current terminal session into that container and access it via "docker exec -it <docker_container_id> /bin/bash" and then simply issuing a "ping 172.17.0.1" to send ICMP echo packets to your SMTP server from inside the container itself. If there are replies, this means the container can reach your local Postfix server so the problem is most likely from Postfix dropping the requests intentionally. Alternatively, this could be a firewall misconfiguration problem but this has never happened to me before, although I recognize that it may be theoretically possible. 230 - 231 231 To further validate this, issue the following command to see the last log error reports from Postfix, including the notifications of rejected requests: 232 232 233 233 {{code language="bash"}} ... ... @@ -236,16 +236,8 @@ 236 236 237 237 Note, you need sudo privileges to read the mail.log file, as it is owned by the syslog user and it has restricted reading privileges. 238 238 239 -Finally, to get further in depth into this matter, you can run: 240 240 241 -{{code language="bash"}} 242 -docker run --rm busybox telnet mail.transistor.one:587 243 -{{/code}} 244 - 245 -To see if port 587 on localhost is reachable from within a docker container. If it is, this utility should be able to confirm it. Otherwise it will print an error message. 246 - 247 -= Wrapping it up = 248 - 197 += Wrapping it up= 249 249 That's it! As soon as you finish editing the main configuration file, please remember to restart the Postfix service afterwards so that the changes can take effect immediately (or reboot the machine). 250 250 251 251 Happy coding!