⬆️ ⬇️

Sending mail from the Docker container (postfix and sasl dokerization)

When I placed the application in the Docker-container and tried to send email to the mail server in another Docker-container, I ran into an unexpected problem. By default, the postfix mail server sends mail to an arbitrary recipient domain only from the local client. All other domains need to be registered in the relay_domains parameter, and if the mynetwors parameter is configured correctly, mail will be sent to the domains listed in the relay_domains parameter from the client from mynetwors.



In principle, this was enough for me, because the application theoretically had to send mail to exactly one corporate mail server. But this solution did not suit me very well, because the task may change at any time. Therefore, I tried to configure sasl-authorization, which allows sending mail to authorized users on an arbitrary domain.





The first solution I tried was to install postfix outside the Docker container and send messages from the Docker container directly to port 25 on it. Of course, I was disappointed, because localhhost inside a container has nothing to do with localhost outside a container.

')

Therefore, you would have to access postfix not through localhost. Yes, and initially the goal was to install everything in containers, and not to depend on the environment on the server. That is, it was desirable to install postfix in a container.



An additional advantage of installing postfix inside the container is that it is completely closed to the outside world, unless you explicitly publish its port to docker-compose, which is naturally easier to control than the exotic parameters in the configuration files of postfix itself.



In order to be able to access the postfix server that runs inside the container, you need to configure authorization. The most popular solution is sasl authentication. I decided to configure it using sasldb2. As it turned out, there were not too many detailed instructions for installing sasl for postfix using sasldb2. Some instructions contained outdated information and did not contain the necessary information. As a result, from the first time authorization stubbornly refused to work. As it turned out, the two main reasons were: use of the postfix server to the file system in the sandbox / var / spool / postfix /, which sasl knows nothing about, and the need to distribute rights to the database file / etc / sasldb2, which the user sasl creates - user postfix.



The resulting Dockerfile file is quite simple, although I had to tinker with when searching for a solution, mainly with user rights, which I will discuss in more detail.



FROM ubuntu:xenial ARG UID RUN \ useradd -u $UID www-arc && \ apt-get update && apt-get install tzdata && \ echo Europe/Kiev | tee /etc/timezone && \ dpkg-reconfigure --frontend noninteractive tzdata && \ apt-get install -y postfix rsyslog sasl2-bin && \ postconf -e "mydestination = localhost" && \ postconf -e "myhostname = example.com" && \ postconf -e "always_bcc = www-arc@localhost" && \ postconf -e "smtpd_sasl_auth_enable=yes" && \ postconf -e "broken_sasl_auth_clients=yes" && \ postconf -e "smtpd_relay_restrictions=permit_sasl_authenticated,reject_unauth_destination" && \ postconf -e "smtpd_sasl_security_options = noanonymous" && \ echo 123456 | saslpasswd2 -c -p -u example.com postfix && \ ln /etc/sasldb2 /var/spool/postfix/etc/sasldb2 && \ adduser postfix sasl && \ touch /var/log/mail.log COPY ./smtpd.conf /etc/postfix/sasl/smtpd.conf CMD service rsyslog start && service postfix start && tail -f /var/log/mail.log 


ln /etc/sasldb2 /var/spool/postfix/etc/sasldb2 By default, postfix works with the file system in the sandbox / var / spool / postfix /. There he will look for a file with logins / etc / sasldb2. Therefore, we set the link to the / etc / sasldb2 file from the sandbox to the real file. The link should only be hard (without the -s option).



adduser postfix sasl is quite understandable and very important action allows postfix to work with the file / var / spool / postfix / etc / sasldb2.



The postconf -e "smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination" rule allows you to send mail to an arbitrary domain to all authenticated sasl clients.



The sasl authorization configuration in the ./smtpd.conf file:



 log_level: 3 pwcheck_method: auxprop auxprop_plugin: sasldb mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM 


The postconf -e "mydestination = localhost" parameter postconf -e "mydestination = localhost" says that mail for this domain should not be sent further, but received on this host. As experience shows, mail servers that should receive mail are very often configured incorrectly, losing mail. Sometimes this is critical. can harm the business if the mailing message contains a customer application for the purchase of a product or service. Therefore, this configuration is configured to send a copy to the local recipient postconf -e "always_bcc = www-arc@localhost" . This recipient is created with the current user ID of useradd -u $UID www-arc .



The current user is defined in the docker-compose configuration:



  postfix: build: context: ./docker/postfix args: - UID volumes: - ./docker/postfix/mail:/var/mail 


When building, the current user is transferred from the env UID=$UID docker-compose build environment.



To connect from another docker container to this service, you need to specify postfix (the name of the service from docker-compose.yml) as the host, and the name with regard to the domain (postfix@example.com) and password. In all cases, the postfix name is optional and is configured in the configuration.



Setting up mail on the application side and on the mail service side is not even half of what needs to be done. All that needs to be done in addition to this in the settings of the domain often lies outside the control of the developer or devops, and for some specialist with the rights to edit the domain account. With whom you have to communicate on the damaged phone. While there will be a leisurely dialogue in the style of “hey guys, look there at your place, this is your back” - your ip-address will be blacklisted by various mail services, from where it will be difficult to exclude them. Therefore, it makes sense to immediately use the services of paid mail services, for example, docs.aws.amazon.com/ses/latest/DeveloperGuide/postfix.html . You can integrate with them through the API, but from my point of view, it is more reliable to do this via postfix (which is relayhost = [email-smtp.us-west-2.amazonaws.com]:587 it is for this purpose) by setting the parameter relayhost = [email-smtp.us-west-2.amazonaws.com]:587 . For more integration, see the AWS website (link above). They are, on the one hand, ensuring that your ip is not blacklisted and your mail is spam, but they themselves can declare you a spammer at any time and block your mail. Toak that there are no ideal solutions.



Addition.



Of course, when solving a problem, I “peeped” like other developers in open repositories do it and learned a lot from these sources. Therefore, I will analyze how some of the configurations solve similar problems.



For this review I used the keyword phrase in Google search “docker sasl postfix”. Therefore, if someone advises some other repositories, I will include it in this list.



1) github.com/MarvAmBass/docker-versatile-postfix



The author did not use the postfix auxprop_plugin: sasldb plugin, but the standard sasl pwcheck_method: saslauthd tool. This is another additional process that runs in a container, and which is not very convenient to configure, because by default it is off. Therefore, the author uses the following constructions in his configuration:

 RUN sed -i 's/^START=.*/START=yes/g' /etc/default/saslauthd; \ sed -i 's/^MECHANISMS=.*/MECHANISMS="shadow"/g' /etc/default/saslauthd RUN sed -i 's/^OPTIONS=/#OPTIONS=/g' /etc/default/saslauthd; \ echo 'OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"' >> /etc/default/saslauthd 




2) github.com/cloudposse/postfix



Similar to the previous one, pwcheck_method: saslauthd



3) github.com/floriandejonckheere/docker-postfix



The author used sasldb2 with the postfix plugin, but turned off the sandbox mechanism: smtp inet n - n - - smtpd , and used supervisor to start processes, thus including several processes in the container.



4) github.com/catatnight/docker-postfix

Like the previous one, the author turned off the sandbox: postconf -F '*/*/chroot = n' and used the supervisor.



5) github.com/juanluisbaptiste/docker-postfix



Uses flat password file: echo "[$SMTP_SERVER]:587 $SMTP_USERNAME:$SMTP_PASSWORD" >> /etc/postfix/sasl_passwd



6) github.com/container-images/postfix



Disables the sandbox sed -i 's/^smtp\(\s*\)inet\(.*\)/docker_smtp\1inet\tn\ty\tn\t-\t-\tsmtpd -v/g' "$MASTER"



In general, I do not claim that, for example, disabling the sandbox or building several processes in one container is a more unsuccessful solution, I just note how these problems were solved by other authors.



I would be grateful for the addition of this list of repositories, and I promise to quickly supplement this list by your comments.



List of useful literature



1. Install and configure Docker + Docker Compose + Postfix + OpenDKIM on Debian in VScale to send an e-mail with a signature. Vadim Khakulov. December 7, 2016 19:25



apapacy@gmail.com

April 8, 2018

Source: https://habr.com/ru/post/353068/



All Articles