Manual to Develop EAI Mail Server on CentOS 8
เนื้อหา
EAI Email Server
This manual is designed to guide how to install an Email Server to send Thai email addresses or Email Address Internationalization (EAI) using Opensource Software. It could be further developed on different set of softwares.
Required Software
- CentOS8 for Virtualbox [CentOS for VirtualBox]
- user: root
- pass: rooteai
- VirtualBox [Win] [Mac]
- VirtualBox Extension Pack [Download]
- Filezilla [Win] [Mac]
- putty [Win] (for Windows)
- Postfix 3.x [Download]
- Dovecot 2.x [Download]
- MariaDB 10.x [Download]
- Roundcube 1.4.x [Download] [tar]
- ข้อ 1, 2, 3, 4, 5 แนะนำให้ติดตั้งเตรียมไว้ก่อนอบรม
Setting up CentOS8 for Virtualbox
- Download and install VirtualBox and VirtualBox Extension Pack
- Download CentOS8 for Virtualbox (centos-eai-wokshop.ova)
- Double click at centos-eai-wokshop.ova to import into Virtualbox [1]
- After importing, double click at centos-eai-wokshop on the left menu in the VirtualBox to open the server
- If an error found, due to cannot find network, select "Change network", then click "OK"[2]
- login with the provided user, pass, then use command line "ifconfig" to check IP address of the machine [3]
- remember this IP address for using ssh to access our server later
(for mac, must allow virtualbox to work as show in this picture [4])
Remarks:
- This manual have no explanation for installing Centos 8
- Postfix Version 3.x.x and above will support EAI
- In real setting, DNS server is also required
Installing EAI Email Server
1. Setting hostname
1. Update mail server packages to the latest version
# yum -y update
2. Define a hostname, e.g. mail.eai.in.th with command
# hostnamectl set-hostname mail.eai.in.th
3. Add the defined hostname to "hosts" file
# vi /etc/hosts
sample of hosts file
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 mail.eai.in.th ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 mail.eai.in.th
*Depends on the environment of CenOS installation, you may need to install additional services e.g. you may not be able to use "vi" command
4. Install wget to download additional necessary softwares
# yum -y install wget
5. Install telnet to test email server functionality
# yum -y install telnet
2. Setting firewall
1. Verify "firewalld service" status on the mail server
- It must be active (running)
# systemctl status firewalld
Sample
Active: active (running) since Mon 2019-11-18 14:12:03 +07; 1h 13min ago
2. Check the firewall zone and network interface that are opened
# firewall-cmd --get-active-zones
example
public interfaces: ens32
3. Check services of firewall in public zone
# firewall-cmd --zone=public --list-services
sample
cockpit dhcpv6-client ssh
4. Open firewall services at public zone of mail server (open on services that needed)
# firewall-cmd --permanent --zone=public --add-service={http,https,mysql,smtp,smtps,imap,imaps} # firewall-cmd --reload
5. Check services list of the firewall at the public zone again, will find the just open services
*ref: configure firewall services for mail server (https://spalinux.com/2015/06/centos-7-basic-configure-firewall-by-firewall-cmd)
# firewall-cmd --zone=public --list-services
example
cockpit dhcpv6-client http https imap imaps mysql smtp smtps ssh
6. In this example, we open SELinux for convenience in setting up (it is not recommended for production server)
- change SELinux=enforcing to SELinux=disabled
# vi /etc/selinux/config
example
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
7. Check SELinux status again
- restart server and check the status
# reboot # sestatus
example
disabled
3. Create an SSL Cert
- The step is for creating SSL key for using with postfix and dovecot
1. Create a private key
# cd /etc/pki/tls/certs # /usr/bin/openssl genrsa -aes128 2048 > eai.key
example
Generating RSA private key, 2048 bit long modulus ... ... e is 65537 (0x10001) Enter pass phrase: #set passphrase Verifying - Enter pass phrase: #confirm
2. Remove Passphase from the created private key
# /usr/bin/openssl rsa -in eai.key -out eai.key
example
Enter pass phrase for eai.key: #input passphrase writing RSA key
3. Create csr
# /usr/bin/openssl req -utf8 -new -key eai.key -out eai.csr
example
You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:TH #country State or Province Name (full name) []:Bangkok #state Locality Name (eg, city) [Default City]:Dusit #city Organization Name (eg, company) [Default Company Ltd]:EAI #company Organizational Unit Name (eg, section) []:IT #department Common Name (eg, your name or your server's hostname) []:mail.eai.in.th #server's FQDN Email Address []:xxx@eai.in.th #email address Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: #Enter An optional company name []: #Enter
4. Generate key
# /usr/bin/openssl x509 -in eai.csr -out eai.crt -req -signkey eai.key -days 365
example
Signature ok subject=/C=JP/ST=Hiroshima/L=Hiroshima/O=GTS/OU=Server World/CN=www.srv.world/emailAddress=xxx@eai.in.th Getting Private key
4. Install mariadb, Postfix and Dovecot
1. Install mariadb , Postfix , Dovecot and necessary packages
# yum -y install postfix dovecot mariadb-server dovecot-mysql postfix-mysql
2. Start service of Postfix, Dovecot, MariaDB every time that the server is started
# systemctl start postfix && systemctl start dovecot && systemctl start mariadb # systemctl enable postfix && systemctl enable dovecot && systemctl enable mariadb
3. Check status of the Postfix, Dovecot, MariaDB
# systemctl status postfix # systemctl status dovecot # systemctl status mariadb
5. Setup MariaDB
1. Set UTF8 for mysql to accept Unicode by adding the following command to /etc/my.cnf.d/maridb-server.cnf under [mysqld]
# vi /etc/my.cnf.d/mariadb-server.cnf
# # These groups are read by MariaDB server. # Use it for options that only the server (but not clients) should see # # See the examples of server my.cnf files in /usr/share/mysql/ # # this is read by the standalone daemon and embedded servers [server] # this is only for the mysqld standalone daemon # Settings user and group are ignored when systemd is used. # If you need to run mysqld under a different user or group, # customize your systemd unit file for mysqld/mariadb according to the # instructions in http://fedoraproject.org/wiki/Systemd [mysqld] character-set-server = utf8 collation-server = utf8_general_ci skip-character-set-client-handshake bind-address=127.0.0.1 datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-error=/var/log/mariadb/mariadb.log pid-file=/run/mariadb/mariadb.pid # # * Galera-related settings # [galera] # Mandatory settings #wsrep_on=ON #wsrep_provider= #wsrep_cluster_address= #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 # # Allow server to accept connections on all interfaces. # #bind-address=0.0.0.0 # # Optional setting #wsrep_slave_threads=1 #innodb_flush_log_at_trx_commit=0 # this is only for embedded server [embedded] # This group is only read by MariaDB servers, not by MySQL. # If you use the same .cnf file for MySQL and MariaDB, # you can put MariaDB-only options here [mariadb] # This group is only read by MariaDB-10.3 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand [mariadb-10.3]
2. Restart MariaDB
# systemctl restart mariadb
3. Set security access to mysql by setup password for root user (* define only new password, skip the rest by pressing enter)
# mysql_secure_installation
4. Login to mysql using the new password
# mysql -u root -p
5. Create new DB for keeping records of Email Server usage
# CREATE DATABASE eaimail; # USE eaimail;
6. Create a user with grants to the eaimail database
# GRANT SELECT, INSERT, UPDATE, DELETE ON eaimail.* TO 'yourdbuser'@'localhost' IDENTIFIED BY 'yourdbpassword'; # GRANT SELECT, INSERT, UPDATE, DELETE ON eaimail.* TO 'yourdbuser'@'localhost.localdomain' IDENTIFIED BY 'yourdbpassword'; # FLUSH PRIVILEGES;
7. Check the created user
# SHOW GRANTS FOR 'yourdbuser'@'localhost';
8. Create tables for domains, forwardings (to forward EAI email to ASCII email address), and users for creating mailboxes
# CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) ); # CREATE TABLE forwardings (source varchar(80) NOT NULL, destination TEXT NOT NULL, PRIMARY KEY (source) ); # CREATE TABLE users (email varchar(80) NOT NULL, password varchar(20) NOT NULL, PRIMARY KEY (email) );
9. Select DB of a mail server and define EAI and English domains and email address with passwords to start using the email server
# INSERT INTO domains (domain) VALUES ('eai.in.th'); # INSERT INTO domains (domain) VALUES ('อีเอไอ.ไทย'); # INSERT INTO users (email, password) VALUES ('thai@eai.in.th', ENCRYPT('thaiuserpassword')); # INSERT INTO users (email, password) VALUES ('ไทย@อีเอไอ.ไทย', ENCRYPT('thaiuserpassword'));
10. Setup a forwrding rule to forward all emails to EAI email address to ASCII email address, since the server can creat mailboxes in Unicode
# INSERT INTO forwardings (source,destination) VALUES ('ไทย@อีเอไอ.ไทย','thai@eai.in.th'); # quit
6. Setup Postfix
Create connect file between Postfix and MariaDB
- Create a script file to get domain value from DB
# vi /etc/postfix/mysql-virtual_domains.cf
user = yourdbuser password = yourdbpassword dbname = eaimail query = SELECT domain AS virtual FROM domains WHERE domain='%s' hosts = 127.0.0.1
- Create a script file to forward emails
# vi /etc/postfix/mysql-virtual_forwardings.cf
user = yourdbuser password = yourdbpassword dbname = eaimail query = SELECT destination FROM forwardings WHERE source='%s' hosts = 127.0.0.1
- Create a script file for creating mailbox and use for login
# vi /etc/postfix/mysql-virtual_mailboxes.cf
user = yourdbuser password = yourdbpassword dbname = eaimail query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s' hosts = 127.0.0.1
- Create a script file for forwarding all email to another SMTP server (in the case that referring to a host as an IP address)
# vi /etc/postfix/mysql-virtual_email2email.cf
user = yourdbuser password = yourdbpassword dbname = eaimail query = SELECT email FROM users WHERE email='%s' hosts = 127.0.0.1
- Set access control right to the created script
# chmod 640 /etc/postfix/mysql-virtual_*.cf && chgrp postfix /etc/postfix/mysql-virtual_*.cf
Create user vmail for reading/writing the mailbox
- Create group for using with the mailbox
# groupadd -g 5000 vmail # useradd -g vmail -u 5000 vmail -d /home/vmail -m
Modify "/etc/postfix/main.cf"
# postconf "myhostname=mail.eai.in.th" # postconf "mydomain=eai.in.th" # postconf "myorigin=\$mydomain" # postconf "inet_interfaces=all" # postconf "inet_protocols=ipv4" # postconf "mydestination=localhost, localhost.localdomain" # postconf "mynetworks=127.0.0.1" # postconf "readme_directory=no" # postconf "smtpd_tls_cert_file=/etc/pki/tls/certs/eai.crt" # postconf "smtpd_tls_key_file=/etc/pki/tls/certs/eai.key" # postconf "shlib_directory=no" # postconf "smtpd_sasl_auth_enable=yes" # postconf "smtpd_sasl_type=dovecot" # postconf "smtpd_sasl_path=private/auth" # postconf "smtpd_sasl_authenticated_header=yes" # postconf "broken_sasl_auth_clients=yes" # postconf "smtpd_use_tls=yes" # postconf "smtpd_recipient_restrictions=permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination" # postconf "smtpd_tls_auth_only=yes" # postconf "smtpd_tls_loglevel=1" # postconf "virtual_mailbox_base=/home/vmail" # postconf "virtual_mailbox_maps=proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf" # postconf "virtual_mailbox_domains=proxy:mysql:/etc/postfix/mysql-virtual_domains.cf" # postconf "virtual_alias_maps=proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf" # postconf "virtual_uid_maps=static:5000" # postconf "virtual_gid_maps=static:5000" # postconf "virtual_alias_domains=อีเอไอ.ไทย" # postconf "virtual_transport=dovecot" # postconf "proxy_read_maps=\$local_recipient_maps \$mydestination \$virtual_alias_maps \$virtual_alias_domains \$virtual_mailbox_maps \$virtual_mailbox_domains \$relay_recipient_maps \$relay_domains \$canonical_maps \$sender_canonical_maps \$recipient_canonical_maps \$relocated_maps \$transport_maps \$mynetworks" # postconf "smtputf8_enable=yes"
- Example file
smtp_tls_security_level = may meta_directory = /etc/postfix shlib_directory = no myhostname = mail.eai.in.th mydomain = eai.in.th myorigin = $mydomain mynetworks = 127.0.0.1 smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_authenticated_header = yes broken_sasl_auth_clients = yes smtpd_use_tls = yes smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination smtpd_tls_auth_only = yes smtpd_tls_loglevel = 1 virtual_mailbox_base = /home/vmail virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 virtual_alias_domains = อีเอไอ.ไทย virtual_transport = dovecot virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf smtputf8_enable = yes proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks
Modify "/etc/postfix/master.cf"
# postconf -M smtps/inet="smtps inet n - - - - smtpd" # postconf -P "smtps/inet/syslog_name=postfix/smtps" # postconf -P "smtps/inet/smtpd_tls_wrappermode=yes" # postconf -P "smtps/inet/smtpd_sasl_auth_enable=yes" # postconf -P "smtps/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject" # postconf -P "smtps/inet/smtpd_relay_restrictions=permit_sasl_authenticated,reject" # postconf -P "smtps/inet/milter_macro_daemon_name=ORIGINATING" # postconf -vM dovecot/unix="dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}"
- Sample file
smtps inet n - - - - smtpd -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
- restart postfix
# systemctl restart postfix
7. Setup Dovecot
Create a connect file between Dovecot and Mariadb
- Create a script to let Dovecot to be able to use with SQL
# vi /etc/dovecot/dovecot-sql.conf.ext
driver = mysql connect = host=127.0.0.1 dbname=eaimail user=yourdbuser password=yourdbpassword default_pass_scheme = CRYPT password_query = SELECT email as user, password FROM users WHERE email='%u';
- Allow users in the Dovecot group to use
# chmod 640 /etc/dovecot/dovecot-sql.conf.ext && chgrp dovecot /etc/dovecot/dovecot-sql.conf.ext
Modify "/etc/dovecot/dovecot.conf"
- Backup the exisitng configuration
# mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf-backup
- Config dovecot
# vi /etc/dovecot/dovecot.conf
example
protocols = imap pop3 lmtp log_timestamp = "%Y-%m-%d %H:%M:%S " mail_location = maildir:/home/vmail/%d/%n/Maildir ssl_cert = </etc/pki/tls/certs/eai.crt ssl_key = </etc/pki/tls/certs/eai.key ssl_dh_parameters_length = 2048 ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL namespace { type = private separator = . prefix = INBOX. inbox = yes } service auth { unix_listener auth-master { mode = 0600 user = vmail } unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } user = root } auth_mechanisms = plain login service auth-worker { user = root } protocol lda { log_path = /home/vmail/dovecot-deliver.log auth_socket_path = /var/run/dovecot/auth-master postmaster_address = postmaster@eai.in.th } protocol pop3 { pop3_uidl_format = %08Xu%08Xv pop3_client_workarounds = outlook-no-nuls oe-ns-eoh } passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes }
- Restart Dovecot
# systemctl restart dovecot
8. Test the EAI Email Server
1. Test imap
# telnet localhost imap
2. Should get the result, the use quit to quit from telnet
Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is '^]'. +OK Dovecot ready.
3. Modify /etc/aliases by adding the lines
# vi /etc/aliases
mailer-daemon: postmaster postmaster: root root: postmaster@eai.in.th
4 Update aliases and restart postfix
# newaliases # systemctl restart postfix
5. Test SMTP server
# telnet localhost 25 # ehlo localhost
6. Should get the following results
250-mail.eai.in.th 250-PIPELINING 250-SIZE 30720000 250-VRFY 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 SMTPUTF8
7. Install mailx and test sending emails
# yum install mailx # mailx thai@eai.in.th (ใส่ subject แล้ว enter ตามด้วยเนื้อหา และใช้ Ctrl+D เพื่อส่งออก)
8. Check the log of email sending : /var/log/maillog as following:
Nov 13 15:19:07 mail postfix/pickup[31954]: E9AB020199E5: uid=0 from=<root> Nov 13 15:19:07 mail postfix/cleanup[1938]: E9AB020199E5: message-id=<20171113081907.E9AB020199E5@mail.eai.in.th> Nov 13 15:19:07 mail postfix/qmgr[21141]: E9AB020199E5: from=<root@eai.in.th>, size=434, nrcpt=1 (queue active) Nov 13 15:19:08 mail postfix/pipe[1946]: E9AB020199E5: to=<tanagan@eai.in.th>, relay=dovecot, delay=0.09, delays=0.04/0.01/0/0.03, dsn=2.0.0, status=sent (delivered via dovecot service) Nov 13 15:19:08 mail postfix/qmgr[21141]: E9AB020199E5: removed
9. Check log of dovecot sedning : /home/vmail/dovecot-deliver.log should get the following results
2017-11-13 15:19:08 lda(tanagan@eai.in.th): Info: msgid=<20171113081907.E9AB020199E5@mail.eai.in.th>: saved mail to INBOX
10. Check the mailbox. When there are sendings and receivings emails, you will see the results
# cd /home/vmail/eai.in.th/thai/Maildir # find
. ./dovecot-uidlist ./cur ./new ./new/1285609582.P6115Q0M368794.li172-137 ./dovecot.index ./dovecot.index.log ./tmp
11. Check mailbox by using mail client, mutt, to see emaila inside the mailbox
# yum install mutt # mutt -f .
12. Test sending an EAI mails
# telnet localhost 25 # EHLO localhost # MAIL FROM: ธนากานต์@อีเอไอ.ไทย SMTPUTF8 # RCPT TO: ธนากานต์@คน.ไทย # data # Subject: eai test # เทสอีเมลส์ภาษาไทย # .
- Use “.” to end and sending the message
- Press Ctrl+] to quit
9. Installing Roundcube Webmail
Installing Apache PHP
- Install repo of php 7.4 and all to install php 7.4
# yum -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm # yum module reset php && yum module enable php:remi-7.4 -y
- Install php, php library and apache web server
# yum -y install httpd php php-common php-devel php-imap php-imagick php-json php-xml php-mbstring php-pear php-pdo php-intl php-ldap php-gd php-zip php-pdo_mysql php-curl php-bz2 php-gmp
- Start service apache and php and set to start automatiacally
# systemctl start httpd && systemctl start php-fpm # systemctl enable httpd && systemctl enable php-fpm
- Check apache status
# systemctl status httpd # systemctl status php-fpm
Setup php
- Setup timezone
# vi /etc/php.ini
[Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone date.timezone = Asia/Bangkok
Setup MariaBD database
- Create database roundcubemail with username=rcmail, password=passrc
# mysql -u root -p
# CREATE DATABASE roundcubemail CHARACTER SET utf8 COLLATE utf8_general_ci; # GRANT ALL PRIVILEGES ON roundcubemail.* TO rcmail@localhost IDENTIFIED BY 'passrc'; # FLUSH PRIVILEGES;
Setup RoundCube
# cd /var/www/html/ # wget https://github.com/roundcube/roundcubemail/releases/download/1.4.4/roundcubemail-1.4.4-complete.tar.gz # tar zvfx /var/www/html/roundcubemail-1.4.4-complete.tar.gz # mv /var/www/html/roundcubemail-1.4.4 /var/www/html/roundcubemail # cp /var/www/html/roundcubemail/config/config.inc.php.sample /var/www/html/roundcubemail/config/config.inc.php # chown -R apache:apache /var/www/html/roundcubemail
Create virtualhost
# vi /etc/httpd/conf.d/rcmail.conf
<VirtualHost *:80> ServerName mail.eai.in.th ServerAdmin webmaster@eai.in.th DocumentRoot /var/www/html/roundcubemail <Directory /var/www/html/roundcubemail> Options -Indexes +FollowSymLinks AllowOverride All </Directory> ErrorLog /var/log/httpd/mail.eai.in.th-error.log CustomLog /var/log/httpd/mail.eai.in.th-access.log combined </VirtualHost>
# systemctl restart httpd
- Test accessing host
http://mail.eai.in.th/installer/
- Setup to access the database
host = localhost dbname =roundcubemail user = rcmail password = passrc db_prefix = rc_
- Setup IMAP
ssl://mail.eai.in.th 993
- Setup SMTP
ssl://mail.eai.in.th 465
- user, pass ของ eai email
thai@eai.in.th และ ไทย@อีเอไอ.ไทย thaiuserpassword
- Using self-sign SSL may cause Roundcube to not able to connect to the mail server. Additional configurations are needed
$config
# vi /var/www/html/roundcubemail/config/defaults.inc.php $config['imap_conn_options'] = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, ), ); $config['smtp_conn_options'] = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, ), );