step-by-step SMTP server configuration

server OS: ubuntu 16.04
SMTP service: Postfix
IMAP service: Dovecot
external database: MySQL 5.7

server hostname: smtp.test.com

SSH login into the machine as root and install Postfix, Dovecot and MySQL integrations
# apt-get update
# apt­get install postfix postfix­mysql dovecot­core dovecot­imapd dovecot­lmtpd dovecot­mysql

the data inserted during the Postifix configuration wizard:
– Internet Site
– test.com
they can be modified in the file /etc/main.cfg

# apt-get install mysql-server-5.7

create a MySQL root user before starting using MySQL Server and login
# mysql -u root -p[here-the-password-without-blank]

create a new database, called ims (in-mail-server) to manage domains and e-mail users

create a specific in-mail-user only for this database (don’t use root user for queries)
mysql> GRANT SELECT ON ims.* TO ‘imu’@’’ IDENTIFIED BY ‘imp123’;


select the inmailserver database and create two tables: for domains and for users
mysql> USE ims;


mysql> CREATE TABLE `virtual_users` (`id` INT NOT NULL AUTO_INCREMENT,`domain_id` INT NOT NULL,`password` VARCHAR(106) NOT NULL,`email` VARCHAR(120) NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `email` (`email`),FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert the domains in the virtual_domains table
mysql> INSERT INTO `ims`.`virtual_domains`(`id` ,`name`)VALUES(‘1’, ‘test.com’),(‘2’, ‘test2.com’),(‘3’, ‘test3.com’);

mysql> INSERT INTO `ims`.`virtual_users`(`id`, `domain_id`, `password` , `email`) VALUES (‘1’, ‘1’, ENCRYPT(‘NyreI0Y2WfTCUQqRvigPxWtmS’, CONCAT(‘$6$’, SUBSTRING(SHA(RAND()), -16))), ‘send@test.com’), (‘2’, ‘2’, ENCRYPT(‘hrZT#8[RF2{ruiGwu’, CONCAT(‘$6$’, SUBSTRING(SHA(RAND()), -16))), ‘send@test2.com’), (‘3’, ‘3’, ENCRYPT(‘tukrXZ19lDIWYITtACfgPZhnb’, CONCAT(‘$6$’, SUBSTRING(SHA(RAND()), -16))), ‘send@test3.com’);

generate a free Dovecot SSL certificate (self signed )
# openssl req ­new ­x509 ­days 1000 ­nodes ­out “/etc/ssl/certs/dovecot.pem” ­keyout “/etc/ssl/private/dovecot.key”

open the main.cf file and modify it like this
# nano /etc/postfix/main.cf

modify this section from:
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_use_tls = yessmtpd_tls_auth_only = yes

change these parameters:
mydestination = localhost
myhostname = smtp.test.com

add these lines:
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated permit_mynetworks reject_unauth_destination

modify the method to save email to local mailboxes from LDA to LMTP:
virtual_transport = lmtp:unix:private/dovecot­lmtp

enable local mail delivery for all the domains listed in the MySQL database (tell Postfix that is used an external database to manage the domains and users):
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

create these 3 configuration files that will contain the informations to query the database
# cd /etc/postfix/

# vi mysql-virtual-mailbox-domains.cf
user = imu
password = imp123
hosts =
dbname = ims
serverquery = SELECT 1 FROM virtual_domains WHERE name='%s'

# vi mysql­virtual­mailbox­maps.cf
user = imu
password = imp123
hosts =
dbname = ims
serverquery = SELECT 1 FROM virtual_users WHERE email='%s'

to test if they work:
# service postfix restart

# postmap ­q test.com mysql:/etc/postfix/mysql­virtual­mailbox­domains.cf
have to output 1

# postmap ­q test2.com mysql:/etc/postfix/mysql­virtual­mailbox­domains.cf
have to output 1

# postmap ­q test3.com mysql:/etc/postfix/mysql­virtual­mailbox­domains.cf
have to output 1

modify master.conf
# nano /etc/posfix/master.conf
decomment these lines:
submission inet n - y - - smptpd
- o syslog_name=postfix/submission
- o smtpd_tls_security_level=encrypt
- o smtpd_sasl_auth_enable=yes
- o smtpd_client_restrictions=permit_sasl_authenticated,reject

# service postfix restart

these configuration files will allow IMAP protocol to connect to the external database and to Postfix

uncomment it:
!include conf.d/*.conf

enable imap and lmtp:
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap lmtp

update the “mail_location” parameter in:
mail_location = maildir:/var/mail/vhosts/%d/%n

set “mail_privileged_group” parameter to “mail”:
mail_privileged_group = mail

for that to work, create set mail folders for each domains in the MySQL table inside this folder “/var/mail/vhosts” and set proper ownerships/permissions
# mkdir ­p /var/mail/vhosts/test.com
# mkdir ­p /var/mail/vhosts/test2.com
# mkdir ­p /var/mail/vhosts/test3.com

# groupadd -g 5000 vmail
# useradd -g vmail -u 5000 vmail -d /var/mail
# chown -R vmail:vmail /var/mail

to ensure security:
disable_plaintext_auth = yes
auth_mechanisms = plain login

#!include auth-system.conf.ext
!include auth-sql.conf.ext

uncomment and set to:
driver = mysql

set the connection parameters:
connect = host =

modify password default scheme and the query for it:
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

set permissions on the /etc/dovecot directory so the vmail user can use it
# chown -R vmail:dovecot /etc/dovecot
# chmod -R o-rwx /etc/dovecot

change all these sections, so that they are the same as the screenshoots

change this parameter to enable SSL for the incoming/outgoing connections:
ssl = required

specify the SSL cert and key file location:
ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.key

# service dovecot restart



to kill or stop a process in linux, you have to use the kill command
kill comes in different variants, depending on what kill signal is specified
if there are no signal specifications, by default, is send the TERM signal

linux and unix-like operating system supports these standard terminate signals
SIGHUP (1) – hangup detected on controlling terminal or death of controlling process, used to reload configuration files and open/close log files
SIGKILL (9) – kill signal, used as last resort to kill process: will not save data or cleaning kill the process
SIGTERM (15) – termination signal, the default and safest way to kill process

a unix process that is a running instance of a program has a PID
each time you start your browser, to the process is automatically assigned a unique process identification number
a PID is automatically assigned to each process when it is created on the system

to find out the PID if a program
# pidof httpd
# pidof apache2
# pidof chrome
# ps aux | grep httpd
# ps aux | grep apache2
# ps aux | grep chrome

kill command syntax
# kill [signal] [pid]
# kill -15 [pid]
# kill -sigterm [pid]

to kill two or more process
# kill [pid1] [pid2] [pid3]
# kill -15 [pid1] [pid2] [pid3]
for example
# kill -15 3546 5557 4242

it is a linux only command to kill processes by names (not on unix operating systems)

# killal [signal] [process name]
for example
# killall -15 chrome



# ps -aux | less
a – select all processes
u – select all processes on a terminal, including those of other users
x – select processes without controlling ttys
ps -aux | less

list every process except those running as root
# ps -U root -u root -N

list processes run by [user]
# ps -u [user]

for dynamic real-time view of a running system
# top
to close the program press q, to access help section press h

other two programs similar to top (they have to be installed) are:
atop – advanced system and process monitor
htop – interactive process viewer

to save the process snapshot in a file
# top -b -n1 > /tmp/process.log
b – start top in batch-mode; in this mode, top will not accept input and runs until the iterations limit, set with the -n command line option
n – specifies the maximum number of iterations top shoul reproduce before ending

# top -b -n1| less
top -b -n1
show a tree of running processes
if a user name is specified, all process trees rooted at processes owned by that user are shown
# pstree | less
ps tree | less
how to find a process id (pid) starting by the process name
# pgrep [process-name]

this command will list the process called chrome which is owned by [user]
# pgrep -u [user] chrome



to see actual position in the filesystem

to create a dir

to create a file

to navigate the file system

list all files and directories
ls -a (also hidden file, starting with .)
ls -l (long format)
access rights / number of hard links / username of file’s owner / group that own the file / size of file in bytes / date and time the file was last modified / the name of the file dir
ls -t (by modification time)

cp a.txt b.txt /dir
copy two file in the dir
(first arguments: list of source files to copy / last argument: place where to copy)
cp * dir/
copy all the files in the current dir to the new one
cp m*.txt dir/
* is a special character called wildcard

mv wonderwoman.txt batman.txt superhero/
moving two files in a new directory
mv batman.txt spiderman.txt
batman is renamed spiderman)

rm file.txt
remove a file
rm -r dir/ (r is an option meaning “recursive”)
remove a directory

echo “hello” (“hello” is called “standard input” abbreviated in stdin)
echo “hello” > hello.txt
cat hello.txt
cat oceans.txt > bottles.txt (put oceans in bottles :3)
cat oceans.txt >> continents.txt (oceans merge with continents, >> appends the standard output on the left and adds it to the file on the right)
cat < lakes.txt (takes the stdin from the file on the right and inputs it into the program on the left)

standard input or STDIN, is information inputted into the terminal through the keyboard or input device
standard output, or STDOUT, is the information outputted after a process is run
standard error, or STDERR, is an error message outputted by a failed process
redirection reroutes standard input, standard output, and standard error to or from a different location

cat bananas.txt | wc | cat > apples.txt
cat apples.txt
// 17 26 204
| is a PIPE that takes the stdout of the command on the left and pipes it as a stdin in the command on the right
pipe permits “command-to-command” redirection
WC (word count) output the number of lines, words and characters

cat bananas.txt | sort > sorted-bananas.txt
SORT takes stdin and orders it alphabetically as stdout

sort desert.txt | uniq > uniq-desert.txt
UNIQ filters out adjacent, duplicate lines in a file

grep -i mOuNt mountains.txt
GREP stands for “global regular expression print” and searches files for lines that match a pattern, returning the results (it’s case sensitive, but the option -i enables the command to be case insensitive)
grep -R pie /home/giada/desktop/recipe
/home/giada/desktop/recipe/coconut.txt: coconut pie
/home/giada/desktop/recipe/hazelnut.txt: hazelnut pie
/home/giada/desktop/recipe/chocolate.txt: chocolate pie
search all files in a dir and outputs filenames and lines with matched results
grep -Rl pie /home/giada/desktop/recipe
searches all files in a dir and outputs only filenames with matched results

SED stands for “stream editor”: accepts stdin and modifies it based on an expression, before displaying it as output data (similar to “find and replace”)
sed ‘s/snow/rain/’
s for “substitution” (always use when using sed for substituting)
snow is the text to find
rain is  the replacement text
!!! this command will only replace the first instance of the searched string per line !!!
sed ‘s/snow/rain/g’
for “globally”
all instances of the searched string will be substituted

each time you launch the terminal application, it creates a new session and the session immediately loads settings/preferences that make up the command line environment
you can configure the environment to support the commands and programs you create, enabling you to customize greetings and command aliases, and create variables to share across commands and programs

~/.bash_profile is the name of file used to store environment setting: when a session starts, it will load the contents of the bash profile before executing commands
represents the user’s home directory
. indicates a hidden file
the name ~/.bash_profile is important, since this is how the command line recognizes the bash profile

you can modify it with a text-editor
nano ~/.bash_profile
writing echo “hello, yourName”
source ~/.bash_profile
this command activates the changes in ~/.bash_profile for the current session: instead of closing the terminal and needing to start a new session, source makes the changes available right away

in this file, you can set the command alias by declaring it (without white spaces)
alias pd=”pwd”
alias hy=”history” (history of commands)
alias ll=”ls -la”
before using the alias, remember to give the source command

finally, under aliases, can be setted environment variables
environment variables are variables that can be used across commands and programs and hold information about the environment

export USER=”Giada”
export option makes the var available to all child session initiated from the session you are in
after the source command, type echo $USER to see effects

export PS1=”>> “
change the prompt from $ in >>
PS1 is the var that defines the makeup of command prompt

other two environment variables (that usually aren’t modified) are:
echo $HOME
echo $PATH
PATH is an environment variable that stores a list of directories separated by a colon (:) and each directory contains scripts for the command line to execute
PATH variable simply lists which directories contain scripts

for example, many commands are scripts stored in the /bin directory
typing ls is equal to type /bin/ls
typing pwd is equal to type /bin/pwd

to see all environment variables
// print all environment variables setted
env | grep PATH
// print only the searched variable



commands that list installed packages on your pc

the command to use depends on linux distro

  • aptitude-based distros (ubuntu, debian, etc): dpkg -l
  • rpm-based distros (fedora, rhel, etc: rpm -qa
  • pkg*-based distros (openbsd, freebsd, etc): pkg_info
  • portage-based distros (gentoo, etc): equery list or eix -I
  • pacman based distros (arch linux, etc): pacman – Q

all these commands will list the packages rather than the programs

if you want to list programs only, you really want to list executables in your $PATH, which can be done using this bash command:
compgen -c

there is no way, in general, to list manually installed programs and their components: they are not recorded anywhere, unless you use a package manager
all you can do is finding the binaries in standard locations and guessing where some libraries or some manual pages come from

so, whenever possible, it’s better to install programs using your package manager



how to make linux insults you when typing the wrong password

edit the /etc/sudoers file with a text editor (I choose nano)

near env_reset of Default add ,insults

where are located linux insults

insults are stored in a binary file /usr/lib/sudo/sudoers.so

enable source download with the command
sed -i ‘/^#sdeb-src /s/^#//’ “/etc/apt/sources.list”

type apt source sudo

the files are located under plugins/sudoers

usually are this, but they can be modified or you can create new ones