Hello, in this article, I will try to answer the question of how to set up an SMTP (Simple Mail Transfer Protocol) server in our local environment and send emails from our remote server using our own postfix server. I will continue explaining through the following points:
1- What is SMTP and SMTP Server?
2- What is Postfix?
3- What is a Gmail App Password and How to Obtain It?
4- Let’s create our server in a Docker environment.
- What is SMTP and SMTP Server?
SMTP (Simple Mail Transfer Protocol) is a communication protocol used for sending emails.
SMTP server: It is the server that receives and forwards incoming and outgoing emails using this protocol. The SMTP server receives email messages created by the sender and performs the necessary actions to route them to the destination server.
The process of sending a message usually consists of the following steps:
- The sender creates an email message through an email client (such as Outlook, Thunderbird, Gmail, etc.) and writes a message with the desired recipient, subject, and content.
- The email client establishes a connection with the SMTP server and uses the SMTP protocol to transmit the email messages to the server. The connection is usually made over TCP/IP and uses port 25 by default.
- The SMTP server authenticates the sender’s identity and performs the necessary actions to route the message to the destination server. These actions may include checking recipient addresses, formatting email headers, encoding the message in the appropriate format, and attempting to deliver it to the destination server.
- When the SMTP server successfully delivers the message to the destination server, the message is deposited into the recipient’s mailbox on that server.
SMTP server can also be used for email retrieval. In this case, the email client connects to the SMTP server using protocols like POP3 (Post Office Protocol) or IMAP (Internet Message Access Protocol) to retrieve the messages.
In this article, we will not configure our server for email retrieval, but only for send-only purposes.
2. What is Postfix?
Before diving into the details, let’s briefly answer the question “What is Postfix?”:
Postfix is an email server software used in Unix-based operating systems. In other words, Postfix functions as a Mail Transfer Agent (MTA) and facilitates the transmission and distribution of emails. Postfix is known for being a high-performance, reliable, flexible, and scalable email server. It is an open-source software that uses the SMTP protocol to handle sending, receiving, and forwarding email operations.
3. What is a Gmail Application Password and How to Obtain It?
A Gmail Application Password is a security feature used to access third-party applications or devices using your Gmail account. It allows us to sign in to our Gmail account without using the regular password. Gmail App Passwords are designed for accounts with two-factor authentication (2FA) enabled. This process is not applicable to accounts without 2FA, and we cannot obtain an App Password in such cases. To be able to send emails from our own server using a Gmail account, we need to sign in to our Gmail account. However, it is not possible to log in to a Gmail account with 2FA enabled directly through the Postfix server. Therefore, we will use an application password in Postfix to access our Gmail account.
After creating our application password, let’s continue with step 4.
4. Let’s Create Our SMTP Server in Docker Environment
Let’s quickly start creating the smtp server. I will use Docker for this process, this docker image for which we have made the necessary configurations will actually perform the task of a ready-made smtp server for us. We will have created a server that we can use independently of the platform.
We will install Postfix on an ubuntu image and make all the settings we need on this image.
You can download the latest version of the ubuntu image with the following command:docker pull ubuntu
But since I will be using a Dockerfile in this article, I don’t need to run the above command. The Dockerfile we have prepared will perform this process for us. Let’s examine:
FROM ubuntu:latest
ARG EMAIL
ARG EMAIL_PASSWORD
ARG MAIL_NAME
ARG SMTP_DOMAIN
ARG SMTP_PORT
RUN apt-get update && \
apt-get install -y mailutils && \
apt install -y postfix
COPY main.cf /etc/postfix/main.cf
RUN sh -c 'echo "root: ${EMAIL}" >> /etc/aliases' && \
sh -c 'echo "${MAIL_NAME}" >> /etc/mailname' && \
sh -c 'echo "[${SMTP_DOMAIN}]:${SMTP_PORT} ${EMAIL}:${EMAIL_PASSWORD}" >> /etc/postfix/sasl_passwd' && \
postmap /etc/postfix/sasl_passwd && \
chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
CMD service postfix restart && tail -f /dev/null
1- FROM ubuntu:latest
In this line, we have determined the image that we will use as the basis. We are using the latest version of ubuntu for our scenario.
2- ARG EMAIL
Here, we define the variables that we will use in our configuration. The values of these variables will come from the docker-compose file that we will create later, during the construction of the image.
3- RUN apt-get update
After our Ubuntu image is installed, we will specify the commands we want to run in it with RUN. In this line, we perform the update process of the packages with the update operation.
4- apt-get install -y mailutils && apt install -y postfix
In this line, we install the necessary packages for our smtp operations on our system. With the -y configuration, we stated that we will answer yes to the questions that will come during the installation phase.
5- COPY main.cf /etc/postfix/main.cf
In the previous step, postfix was installed on our system. After the postfix installation, a folder named postfix will be created under etc, which contains the postfix settings. In this folder, there is a file named main.cf that contains the necessary configurations. We will create these settings ourselves and replace the main.cf file we created with the automatically created file in this directory. This operation is performed on this line. (After this step, the contents of the main.cf file will be displayed)
6- RUN sh -c ‘echo “root: ${EMAIL}” >> /etc/aliases’
There are aliases that we will use in the aliases file under etc. Here we write our e-mail address serving on the server where we will receive the root value. gmail for our case.
7- RUN sh -c ‘echo “${MAIL_NAME}” >> /etc/mailname
In this line, we create a file called mailname, which is also under etc. We will write the MAIL_NAME value that we will take as an argument in it.
8-sh -c ‘echo “[${SMTP_DOMAIN}]:${SMTP_PORT} ${EMAIL}:${EMAIL_PASSWORD}” >> /etc/postfix/sasl_passwd’
The part that is covered in red is the application password we created before. Dockerfile will do this automatically. We do not need to enter this file and write our password in this way.
9- postmap /etc/postfix/sasl_passwd
In short, using this command, we convert the SMTP authentication information in the /etc/postfix/sasl_passwd file into a database and Postfix becomes able to authenticate using this database.
10- chown 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
This command makes the /etc/postfix/sasl_passwd and /etc/postfix/sasl_passwd.db files belong to the “root” user and “root” group, ensuring that the files are only accessible by the authorities with the necessary permissions and increases system security.
11- CMD service postfix restart && tail -f /dev/null
Finally, in this line, we run the service postfix restart command to activate the changes we made for postfix with the CMD command. Then, with the tail -f /dev/null command, we ensure that our service (container) is running continuously.
Creating the main.cf file:
The main.cf file that we mentioned in the 5th item above is necessary for us to perform the settings correctly. We will position this file to be in the same directory as the Dockerfile. Let’s create a file called main.cf and paste the following settings into it:
# 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 (Ubuntu)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# See http://www.postfix.org/COMPATIBILITY_README.html - default to 3.6 on
# fresh installs.
compatibility_level = 3.6
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_security_level=may
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $myhostname, /etc/mailname, localhost, localhost.localdomain, localhost
relayhost = [smtp.gmail.com]:587
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = loopback-only
inet_protocols = all
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
Yes, the settings of the image we will use and our main.cf file are ready. Now let’s create a docker-compose file to be able to use it:
version: '3.8'
services:
smtp-server:
#container_name: smtp-server
build:
context: .
args:
EMAIL: ${EMAIL}
EMAIL_PASSWORD: ${EMAIL_PASSWORD}
MAIL_NAME: ${MAIL_NAME}
SMTP_DOMAIN: ${SMTP_DOMAIN}
SMTP_PORT: ${SMTP_PORT}
ports:
- ${PORT}:25
Here we create our service named smtp-server. We specify the container name and which image this container will run using. Finally, we defined the variables that we specified parametrically in the Dockerfile with args. Now let’s define the values of these variables by creating an .env file:
.env:
EMAIL=your gmail address
EMAIL_PASSWORD=your application password
PORT=25
MAIL_NAME=aedemirsen.com (your mailname)
SMTP_DOMAIN=smtp.gmail.com
SMTP_PORT=587
In the last case, our working folder should have the following structure:
We have completed all the necessary settings in this way and now our server is ready to work. Let’s create our image using the following command and let our container run:
docker-compose up -d
When the image is created and the container is up, let’s send our first email for testing. For this, let’s login to the container with the following command:
docker exec -it [container_id yada container_name] sh
Now you can send an e-mail to any e-mail address with the following command:
echo "This is a test email." | mail -s "Test" recipient_mail_address@gmail.com
In the above example, we have sent an e-mail with the subject Test to the address recipient_mail_address@gmail.com. Here you can send an e-mail to any e-mail address you want. Our smtp server will use the Gmail client and protocols to send e-mails through our own gmail address. By accessing this server running on port 25 through different applications, we can handle our mail sending processes.
All config files are available from the following github repo:
https://github.com/aedemirsen/training/tree/main/smtp_server
Reference:
Comments are closed