最近做了一個應用,需要用郵件發通知,但是免費的郵箱每天發信數量是有限制的,所以呢就想著搭建一個自己的郵件伺服器,能夠實現郵件的傳送和接收即可,其中大概花了一個星期找資料,測試,終於成功了,寫個教程分享給大家。
本教程基於 ubuntu 18.04(其他的 linux 理論上也是可以的,只是安裝的軟體包不一樣)。用到的主要軟體為:postfix,dovecot,mysql.廢話不多說,下面是教程:
前置條件
- mysql 資料庫。本教程中使用 mysql 儲存域名,使用者資訊等。
- 域名。需要有域名才能實現向公網發郵件/收郵件。這裡以 test.com 為例。
- ssl 證書。有不少免費的 ssl 證書提供商,或者使用自簽證書,百度即可。
安裝環境
安裝軟體
切換到 root 使用者下,執行以下命令:
apt update
apt install postfix postfix-mysql dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-mysql
安裝過程中 postfix 會彈出提示:
這裡我們選擇第二項:Internet Site。
接著會有如下提示:
這裡填入:test.com
配置 mx 解析
在域名提供商增加以下解析:
- MX 記錄:
test.com
指向伺服器IP
- A 記錄:
pop3.test.com
指向伺服器IP
- A 記錄:
smtp.test.com
指向伺服器IP
建立 mysql 資料庫
新建一個資料庫 mailserver,管理賬號為:admin/123456
建立虛擬域表,作為認證域。該表是郵件伺服器用以接收郵件的域名:
-- 建立表
CREATE TABLE `virtual_domains` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入一條記錄
insert into virtual_domains values(1,'test.com')
建立使用者表,用於使用者身份認證。
-- 建立使用者表
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;
-- 插入兩個使用者,以md5加密密碼,實際應用中應該選擇強度更高的演算法,md5目前以及不安全了
insert into virtual_users values(1,1,md5('123456'),'first@test.com');
insert into virtual_users values(2,1,md5('123456'),'second@test.com');
建立別名表.該表作用相當於當 source 收到郵件時,該郵件會自動轉發到 destination 上。
-- 建立表
CREATE TABLE `virtual_aliases` (
`id` int(11) NOT NULL auto_increment,
`domain_id` int(11) NOT NULL,
`source` varchar(100) NOT NULL,
`destination` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入資料,所有發給first的郵件都會自動轉發給second
insert into virtual_aliases values(1,1,'first@test.com','second@test.com')
生成 ssl 證書
生成 ssl 證書可參考這一篇https://www.jianshu.com/p/b47d862bceeb.為 test.com 生成 ssl 證書,假設證書存放地址為:
- 公鑰 /etc/letsencrypt/live/test.com/fullchain.pem;
- 私鑰 /etc/letsencrypt/live/test.com/privkey.pem;
配置 postfix
首選備份 postfix 的預設配置檔案,然後編輯main.cf
cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
vim /etc/postfix/main.cf
註釋下面的配置:
然後加入如下的配置:
# 使用自己的ssl證書
smtpd_tls_cert_file=/etc/letsencrypt/live/test.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/test.com/privkey.pem
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
# 使用dovecot來做身份認證
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
修改 myhostname,myorigin 為如下的值:
myhostname = test.com
myorigin = $myhostname
修改 mydestination 值為 localhost,以啟動 mysql 中的虛擬域。:
mydestination = localhost
在配置檔案的最後加入以下行,確保將郵件投遞給 mysql 表中列出的虛擬域。
virtual_transport = lmtp:unix:private/dovecot-lmtp
最後加入以下三項引數,告知 Postfix 配置虛擬域、使用者和別名
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
接下來建立上面最後加入的三項引數對應的檔案。
建立/etc/postfix/mysql-virtual-mailbox-domains.cf
,內容如下:
user = admin
password = 123456
port = 3306
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
接著重啟 postfix,並測試 postfix 能否找到域,如果成功返回 1:
service postfix restart
postmap -q test.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
建立/etc/postfix/mysql-virtual-mailbox-maps.cf
,內容如下:
user = admin
password = 123456
port = 3306
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'
接著重啟 postfix,並測試其能否找到郵箱地址,成功返回 1:
service postfix restart
postmap -q first@test.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
最後建立/etc/postfix/mysql-virtual-alias-maps.cf
,內容如下:
user = admin
password = 123456
port = 3306
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'
同樣重啟 postfix,驗證能否正確找到別名,並返回:
service postfix restart
postmap -q first@test.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
如果響應使用 587 埠來進行俺的 smtp 通訊,需修改/etc/postfix/master.cf 檔案:
取消以下行的註釋:
配置 dovecot
postfix 配置完畢,現在來配置 dovecot,首先編輯主配置檔案/etc/dovecot/dovecot.conf
:
首先確保下面一行是啟用的:
!include conf.d/*.conf
然後在配置檔案的最後加入如下配置,啟用各協議:
protocols = imap lmtp pop3
修改/etc/dovecot/conf.d/10-mail.conf
,確儲存在以下兩個配置:
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = mail
上面的配置將郵件存放目錄設定在/var/mail 中,因此將該資料夾的所屬人改為 vmail/vmail.命令如下:
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail
chown -R vmail:vmail /var/mail
修改/etc/dovecot/conf.d/10-auth.conf
。首先確保如下兩個配置存在且值正確:
disable_plaintext_auth = yes
auth_mechanisms = plain login
然後修改配置以禁用系統使用者登陸,並開啟 mysql 支援,如下圖所示:
修改/etc/dovecot/dovecot-sql.conf.ext
檔案,將內容改成下面的內容:
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}
修改/etc/dovecot/dovecot-sql.conf.ext
:
首選取消 driver 引數註釋並設定為 mysql
driver = mysql
然後取消 connect 行註釋並設定為如下內容:
connect = host=127.0.0.1 port=3306 dbname=mailserver user=admin password=123456
接著取消 default_pass_scheme 行的註釋並改為 MD5
default_pass_scheme = MD5
接著取消 password_query 行的註釋並設定為以下資訊:
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
最後將/etc/dovecot
的擁有者改為 vmail:dovecot
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
修改/etc/dovecot/conf.d/10-master.conf
:
首先將 imap-login , pop3-login 下第一個的 port 設定為 0,以禁用非 ssl 加密的 imap 和 pop3 協議,如下圖所示:
然後找到service lmtp
將其修改為如下:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
# Create inet listener only if you can't use the above UNIX socket
#inet_listener lmtp {
# Avoid making LMTP visible for the entire internet
#address =
#port =
#}
}
然後找到service auth
將其內容修改為如下:
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
}
user = dovecot
}
最後找到service auth-worker
改為如下內容:
service auth-worker {
# Auth worker process is run as root by default, so that it can access
# /etc/shadow. If this isn't necessary, the user should be changed to
# $default_internal_user.
user = vmail
}
最後要改的就是/etc/dovecot/conf.d/10-ssl.conf
,以開啟 ssl 認證.
首先將 ssl 引數改為 required:
ssl = required
然後設定 ssl 證書路徑就 ok 了,還是用之前的 ssl 證書:
ssl_cert = </etc/letsencrypt/live/test.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/test.com/privkey.pem
到這裡所有的配置都 OK,重啟 postfix,dovecot 後就可以用郵箱客戶端(比如 foxmail)連線了。
service postfix restart
service dovecot restart
結束
配合一個郵件客戶端看似很簡單,實際上還是有很多坑的,看看上面那麼多的配置項就知道了,一定要耐心。
如果無法登陸,可以看看 postfix 和 dovecot 的日誌報錯情況,再去修改。日誌位置在/var/log
注意:
被這個問題困擾了好幾天,未找到解決辦法,最後放棄.
目前很多主機廠商都不支援和其他伺服器的 25 埠通訊,已知的有(谷歌雲,阿里雲),這樣就導致在這些機器上搭建的 postfix 郵件伺服器,無法向其他的外網郵箱傳送郵件,因為無法和其他 smtp 伺服器的 25 埠建立連線。貌似是為了避免有人惡意搭建郵件伺服器向其他的郵件伺服器傳送大量的垃圾郵件,從而導致此伺服器 IP 被反垃圾郵件組織列入 SML。
本部落格原創釋出於:http://tapme.top/blog/detail/2019-04-05