标签:
Here is the original guid:
Postfix+Dovecot+MySQL搭建邮件服务器
The reference above was written for Ubuntu, I found some changes must be done to apply the techniques with my CentOS scenario.
Another helpful guid:
Email with Postfix, Dovecot and MariaDB on CentOS 7
The second one uses likely design of database. More important, it has some things the first reference doesn‘t talk about.
My scenario
I planed to build a mail server working with gitlab, for internal development using. The mail server is also the one running gitlab. The idea makes things simple.
For local network, you have to use "/etc/hosts" as the alternative.
Let‘s say the host name of server is: devsrv,
Server File: /etc/hosts
# hosts for devsrv 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 # DNS configuration 192.168.1.10 mail.devsrv.lan www.devsrv.lan devsrv.lan devsrv
Client File: /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.1.10 devsrv devsrv.lan www.devsrv.lan mail.devsrv.lan imap.devsrv.lan smtp.devsrv.lan git.devsrv.lan
Under CentOS, the commands cloud be:
sudo yum install -y postfix dovecot dovecot-core mariadb
Following the instruction of the first reference, initialize the database. I also wrote some procedures to help managing account:
Create Database
create database if not exists mailserver; create user mailserver@'localhost' identified by 'mailserver123'; grant all on mailserver.* to mailserver@localhost' identified by 'mailserver123';Create tables and procedures
use mailserver;
delimiter //
drop procedure if exists proc_log;
create procedure proc_log(msg varchar(1024))
begin
select ifnull(msg, '') as DEBUG;
end //
-- Procedure: proc_show_error
-- Show error message with error code
drop procedure if exists proc_log_error;
create procedure proc_log_error(err_code int, msg varchar(255))
begin
call proc_log(concat('ERROR(', err_code, '): ', msg));
end //
-- Procedure proc_add_mail_account
-- Create a new mail account
drop procedure if exists proc_add_mail_account;
create procedure proc_add_mail_account
(uname varchar(64),
pwd varchar(64))
begin
declare def_domain varchar(100) default 'devsrv.lan';
declare err int default 0;
declare num int;
declare uname_len int default 0;
declare at_pos int default null;
declare domain varchar(100);
declare domain_id int;
declare pwd_len int;
-- initialize
set uname = lcase(ltrim(rtrim(uname)));
set uname_len = length(uname);
set at_pos = ifnull(instr(uname, '@'), 0);
set pwd = ltrim(rtrim(pwd));
set pwd_len = length(pwd);
-- validate username
if uname is null or uname_len = 0 then
set err = 1;
call proc_log_error(err, 'Empty username');
end if;
-- check '@'
if err = 0 and at_pos > 0 then
-- if username has only '@' character
set domain = right(uname, uname_len - at_pos);
if uname_len = 1 or length(domain) = 0 then
set err = 2;
call proc_log_error(err, 'Invalid username');
end if
end if;
end if;
-- validate domain
if err = 0 then
if domain is null or length(domain) = 0 then
set domain = def_domain;
-- use default domain if not specified.
set uname = concat(uname, '@', domain);
end if;
end if;
-- validate domain existence
if err = 0 then
select id into domain_id from virtual_domains where name = domain;
if domain_id is null then
set err = 4;
call proc_log_error(err, 'Invalid domain');
end if;
end if;
-- validate user existence
if err = 0 then
select count(*) into num from virtual_users where email=uname;
if num > 0 then
set err = 5;
call proc_log_error(err, 'User exists');
end if;
end if;
-- validate password
if err = 0 then
if pwd_len = 0 then
set err = 6;
call proc_log_error(err, 'Empty password');
else
-- validate security rules
-- validate length
if pwd_len < 6 then
set err = 7;
call proc_log_error(err, 'Password must be 6 characters long');
end if;
-- NOTE: following rules are ignored now.
-- validate uppercase letters
-- validate digit
end if;
end if;
if err = 0 then
-- create account
set pwd = encrypt(pwd, concat('X7X', substring(sha(rand()), -16)));
insert virtual_users (domain_id, password, email)
values(domain_id, pwd, uname);
if last_insert_id() is null then
set err = 8;
call proc_log_error(err, 'Failed to create account');
else
select 'Account has been created successfully!';
end if;
end if;
end //
-- end of procedure
drop procedure if exists proc_del_mail_account;
create procedure proc_del_mail_account(uname varchar(64))
begin
set uname = lcase(ltrim(rtrim(uname)));
delete from virtual_users where email=uname;
if row_count() = 0 then
call proc_log('User does not exist');
else
call proc_log('User account has been removed successfully!');
end if;
end //
drop procedure if exists proc_add_mail_alias;
create procedure proc_add_mail_alias(src varchar(100), dest varchar(100))
begin
declare err int default 0;
declare num int;
declare domain_id int;
declare dest_len int;
declare dest_at_pos int;
declare dest_name varchar(100);
declare dest_domain varchar(100);
declare src_len int;
declare src_at_pos int;
declare src_name varchar(100);
declare src_domain varchar(100);
set dest = lcase(ltrim(rtrim(dest)));
set dest_len = length(dest);
set dest_at_pos = ifnull(instr(dest, '@'), 0);
set src = lcase(ltrim(rtrim(src)));
set src_len = length(src);
set src_at_pos = ifnull(instr(src, '@'), 0);
-- validate dest length
if dest_len = 0 then
set err = 1;
call proc_log_error(err, 'Empty dest');
else
-- check '@'
if dest_at_pos = 0 then
set err = 2;
call proc_log_error(err, 'Invalid dest');
else
set dest_name = left(dest, dest_at_pos - 1);
set dest_domain = right(dest, dest_len - dest_at_pos);
-- re-check dest
if length(dest_name) = 0 or length(dest_domain) = 0 then
set err = 3;
call proc_log_error(err, 'Invalid dest');
else
-- check existence
select count(*) into num from virtual_users where email=dest;
if num = 0 then
set err = 4;
call proc_log_error(err, 'dest does not exist');
end if;
end if;
end if;
end if;
-- validate
if err = 0 then
if src_len = 0 then
set err = 5;
call proc_log_error(err, 'Empty alias');
else
if src_at_pos = 0 then
set err = 6;
call proc_log_error(err, 'Invalid alias');
else
set src_name=left(src, src_at_pos - 1);
set src_domain=right(src, src_len - src_at_pos);
if length(src_name) = 0 or length(src_domain) = 0 then
set err = 7;
call proc_log_error(err, 'Invalid alias');
end if;
end if;
end if;
end if;
call proc_log(concat('Validate domains', err));
-- validate both domains
if err = 0 then
if dest_domain != src_domain then
set err = 8;
call proc_log_error(err, 'Domain does not match');
else
call proc_log('Check domain id');
select id into domain_id from virtual_domains where name=dest_domain;
call proc_log(concat('Get domain id:', ifnull(domain_id, 'null')));
if domain_id is null then
set err = 9;
call proc_log_error(err, 'Domain does not exist');
else
select count(*) into num from virtual_aliases where source=src and destination=dest;
call proc_log(concat('num of match:', num));
if num > 0 then
set err = 10;
call proc_log_error(err, 'Alias already exists');
else
call proc_log('Insert into...');
insert into virtual_aliases(domain_id, source, destination)
value(domain_id, src, dest);
call proc_log('Inserted.');
if last_insert_id() is null then
set err = 11;
call proc_log_error(err, 'Failed');
else
call proc_log('Alias has been added successfully');
end if;
end if;
end if;
end if;
end if;
end //
drop procedure if exists proc_del_mail_alias;
create procedure proc_del_mail_alias(src varchar(100), dest varchar(100))
begin
declare err int default 0;
declare num int;
declare src_len int;
declare src_at_pos int;
declare src_domain varchar(100);
declare src_domain_len int;
declare dest_len int;
declare dest_at_pos int;
declare dest_domain varchar(100);
declare dest_domain_len int;
declare alias_id int default null;
set src = lcase(ltrim(rtrim(src)));
set src_len = length(src);
set src_at_pos = ifnull(instr(src, '@'), 0);
set src_domain = right(src, src_len - src_at_pos);
set src_domain_len = length(src_domain);
set dest = lcase(ltrim(rtrim(dest)));
set dest_len = length(dest);
set dest_at_pos = ifnull(instr(dest, '@'), 0);
set dest_domain = right(dest, dest_len -dest_at_pos);
set dest_domain_len = length(dest_domain);
if src_len = 0 or src_at_pos = 0 or src_domain_len = 0 then
set err = 1;
call proc_log_error(err, 'Invalid alias');
end if;
if err = 0 and (dest_len = 0 or dest_at_pos = 0 or dest_domain_len = 0) then
set err = 2;
call proc_log_error(err, 'Invalid account');
end if;
if err = 0 then
if src_domain != dest_domain then
set err = 3;
call proc_log_error(err, 'Different domain');
end if;
end if;
if err = 0 then
select id into alias_id from virtual_aliases where source = src and destination = dest;
if alias_id is null then
set err = 4;
call proc_log_error(err, 'Not found');
else
delete from virtual_aliases where id = alias_id;
if row_count() = 0 then
set err = 5;
call proc_log_error(err, 'Failed to remove record');
else
select 'Alias has been removed successfully';
end if;
end if;
end if;
end //
NOTE: Change the default domain to your favorite one before run the script.
Copy and run the sql code in query window of MySql Workbench.
Or save the code to a file and run mysql command:
[igame@devsrv:~]$mysql -u root -u < untitled.sql
Account maintenance
Under mysql command prompt, run statements to maintenance mail account:
$mysql -u mailserver -p
Create user
call proc_add_mail_account('igame', '123456');call proc_add_mail_alias('postmaster@devsrv.lan', 'igame@devsrv.lan');
4. Postfix configuration
Following the reference above to configure postfix, but some small differences :
File: /etc/postfix/main.cf
myhostname = mail.devsrv.lan mydomain = lan mydestination = $myhostname, localhost.$mydomain, localhost # restrict in intranet, for internet, should be 0.0.0.0/0 mynetworks = 192.168.1.0/24, 127.0.0.0/8NOTE: CentOS stores dovecot certs in different path, if you use the default dovecot certs, keep that in mind:
smtpd_tls_cert_file=/etc/pki/dovecot/certs/dovecot.pem smtpd_tls_key_file=/etc/pki/dovecot/private/dovecot.pem
NOTE: If you have problems when sending mail, try make unset mydestination
mydestination =
The reference above doesn‘t talk about "/etc/postfix/master.cf" which is crucially important, here is how:
File: /etc/postfix/master.cf
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#smtp inet n - n - 1 postscreen
#smtpd pass - - n - - smtpd
#dnsblog unix - - n - 0 dnsblog
#tlsproxy unix - - n - 0 tlsproxy
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
#628 inet n - n - - qmqpd
# NOTE: do not forget dovecot
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
5. Dovecot configuration
Again, the most occurring error is the path of ssl certs, for default dovecot certs, it should be:
File: /etc/dovecot/dovecot.conf
ssl_cert = </etc/pki/dovecot/certs/dovecot.pem ssl_key = </etc/pki/dovecot/private/dovecot.pemUnder CentOS 7, there is no *.protocol files for dovecot.conf, so this following line coming from the first reference has no meaning:
!include_try /usr/share/dovecot/protocols.d/*.protocol
6. Create Account
In query dialog of "MySql Workbench Community" or mysql command line prompt, run the following sql statement:
use mailserver;
call proc_add_mail_account('test', '123456');
7. Thunderbird Configuration
The Thunderbird is not smart enough if you choose to let it detect the configuration from mail server. The faster way is manually configuring:
Add new account:
Use manual config
NOTE: Remove the "." before server hostname which is a mistake. Configure the port, SSL and authentication like the following picture:
Re-test
Now the Thunderbird shows off how clever it is.
Add Security Exception
Probably Thunderbird warns about security exception, choose "Confirm Security Exception".
Overview of Account Settings
When all done, we can check the settings of account.
Server Settings:
Outgoing Server(SMTP) Settings:
Edit the smtp setting:
Congratulations! All done, now we can send and receive mail. Enjoy!
Good luck!
Using Postfix, Dovecot and MySql as Mailserver under CentOS 7
标签:
原文地址:http://blog.csdn.net/igame/article/details/51206180