2017-12-28

搭建自己的邮件系统——能用就行

也不知道发生了什么

本来只是想获取一下 he.net ipv6 认证 然后发现要求使用一个具有IPv6的邮箱来收发邮件, 也不知道哪家公司支持, 就打算自己建立一个自己的域名邮箱, 这也是早有打算。那就开干吧。

环境

选用了国外的VPS,自己安装了新的ubuntu 16.04.3,1G内存 25G的空间
预先配置好了docker
系统 : Ubuntu 16.04.3 LTS
内存 :1G
参考文章来源
https://linode.com/docs/email/
https://www.digitalocean.com/community/search?q=mail

构思

docker 上有看到一个很好的项目,虽然web界面不怎么样,但是看它的说明,看挺安全的 poste 这个自己跑过了,然后看到另外一个 mailu 这个一直运行不了 很迷,但是看着挺好看的,官方提供了一个测试页面。

但我决定自己搭建一个 从头开始,以后再考虑使用第三方的,第三方也只是使用他的 webmail 界面,也许可以考虑自己写一个。

现在大部分都是使用 postifx + Dovecot + mysql,然后使用第三方的邮箱客户端进行收取邮件 以后可能会加上web界面,使用 MySQL 是便于管理,如果 用户集 使用系统的用户集我觉得不大合适
postfix 作为 MTA 使用
Dovecot 提供POP3/SMTP/IMAP服务
使用SSL TLS 加密 客户端与邮件服务器的通讯,获取 SSL 证书可查看我站文章 用上Let’s Encrypt的HTTPS证书

域名解析

配置 BIND 可见文章 权威DNS(造轮子……

给自己的域名添加 以下解析项

@       IN      MX      10      mail.example.com.
mail    IN      A       0.0.0.0
mail    IN      AAAA    ::1
pop     IN      CNAME   mail.example.com.
pop3    IN      CNAME   mail.example.com.
smtp    IN      CNAME   mail.example.com.
imap    IN      CNAME   mail.example.com.

在网络不是很大型的情况下,可以多种服务部署到同一台服务器上上,并做CNAME解析,如果服务使用人数众多,则建议将每个服务单独放在一台服务器上,并做好DNS解析.

建议服务器的IP做好反向解析,减少发信被拒的情况

安装所需软件包

sudo apt install postfix postfix-mysql \
dovecot-core dovecot-imapd dovecot-pop3d \
dovecot-lmtpd dovecot-mysql mysql-server

根据提示 输入mysql root 的密码 ,以及选择postfix 的环境和 服务器名称

配置

Mysql

登录MySQL 服务器 增加新数据库以及新用户

mysql -u root -p 
#增加新数据库
create database mailserver;
#新增mailuser 并授权 其 mailserver 权限
GRANT SELECT ON mailserver.* TO 'mailuser'@'127.0.0.1' IDENTIFIED BY 'mailuserpass';

刷新权限表 FLUSH PRIVILEGES;

创建 邮箱虚拟名称表

CREATE TABLE `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建 邮箱表

CREATE TABLE `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `password` varchar(1024) NOT NULL,
  `email` varchar(100) 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;

创建 别名列表

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;

添加邮箱虚拟名称

INSERT INTO `mailserver`.`virtual_domains`
  (`id` ,`name`)
VALUES
  ('1', 'example.com'),
  ('2', 'hostname.example.com'),
  ('3', 'hostname'),
  ('4', 'localhost.example.com');

新增用户

INSERT INTO `mailserver`.`virtual_users`
  (`id`, `domain_id`, `password` , `email`)
VALUES
  ('1', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email1@example.com'),
  ('2', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email2@example.com');

password 请根据实际修改

添加用户别名

INSERT INTO `mailserver`.`virtual_aliases`
  (`id`, `domain_id`, `source`, `destination`)
VALUES
  ('1', '1', 'alias@example.com', 'email1@example.com');

查询一下是否添加成功

SELECT * FROM mailserver.virtual_domains;
SELECT * FROM mailserver.virtual_users;
SELECT * FROM mailserver.virtual_aliases;

添加数据请根据实际情况

POSTFIX

  • 备份默认配置
cp /etc/postfix/main.cf /etc/postfix/main.cf.backup

详细配置可见 postfix 上的叙述,我这里只添加

virtual_transport = lmtp:unix:private/dovecot-lmtp 用来告诉postfix 将本域邮件处理交给 Dovecot's LMTP

  • 安全
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
  • 用户验证
    虚拟用户的查询方式以及查询的配置
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

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,
        mysql:/etc/postfix/mysql-virtual-email2email.cf

三个文件的配置 写在下面

如果您使用了不同的用户名, 密码, 数据库名称, 数据库字段名,甚至数据库不在本地服务器上,请根据实际情况修改.

/etc/postfix/mysql-virtual-mailbox-domains.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

/etc/postfix/mysql-virtual-mailbox-maps.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

/etc/postfix/mysql-virtual-alias-maps.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

/etc/postfix/mysql-virtual-email2email.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT email FROM virtual_users WHERE email='%s'

修改完成后
sudo service postfix restart
重启postfix,然后执行测试

postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
postmap -q email1@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf

如没报错 语句不可用 及类似的则可认为配置正确

smtp      inet  n       -       -       y       -       smtpd
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

sudo service postfix restart
重启 postfix,这样postfix 就配置完成了

Dovecot

  • 备份原有配置

sudo cp -a /etc/dovecot /etc/dovecot.backup

  • 启用协议
    修改文件##### /etc/dovecot/dovecot.conf增加
protocols = imap pop3 lmtp 

以启用 imap pop3 lmtp 协议

  • 建立邮件存储文件夹
    修改 /etc/dovecot/conf.d/10-mail.conf
maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = mail

maildir 为存储位置 %d表示域名, %n 表示邮箱全名, %u 表示用户名,可根据需要修改

ls -ld /var/mail 

新建用户 并修改 /var/mail所有者

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

建立文件夹

mkdir -p /var/mail/vhosts/example.com
chown -R mail /var/mail/
  • 用户身份验证
  • /etc/dovecot/conf.d/10-auth.conf
#停止使用明文验证
disable_plaintext_auth = yes
#修改登录验证机制
auth_mechanisms = plain login

停止使用系统账户登录 !include auth-system.conf.ext 前加入 # 注释掉语句
去掉 #!include auth-sql.conf.ext 前的 # 以启用 MySQL 验证身份
验证身份文件
/etc/dovecot/conf.d/auth-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
}

sql身份验证配置,修改以下文件的行段
/etc/dovecot/dovecot-sql.conf.ext

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailuserpass
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
  • 连接配置
    由于我们还未配置安全证书,所以暂不开放与安全有关的端口
    去掉以下行段的注释并根据需要修改
inet_listener imap {
    port = 143
  }

inet_listener pop3 {
    port = 110
  }

unix_listener lmtp {
    mode = 0666
  }

unix_listener auth-userdb {
    mode = 0666 
  }

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

  unix_listener auth-userdb {
    mode = 0600
    user = vmail
  }
  user = dovecot
}

service auth-worker {
  user = vmail
}

这里 有整份文档的全部内容

重启 sudo service dovecot restart

这样就配置完成了,来修 bug 吧~

测试以及修复奇怪的bug

没加密的情况下 outlook 一直连接不上Orz, 然后查了好久 在 /etc/dovecot/dovecot.conf 里加上

disable_plaintext_auth = no
ssl_disable = no

这时候,能接受邮件,但是不一定发得出去,得看服务器提供商的设置,是否开放了25端口,大部分已经不开放了……垃圾邮件这么多,谁也不想毁了自己的名誉。我当时发了一个工单,很快就给开通了。

如何确保你和服务器之间的连接是安全可靠的呢?见文章 搭建自己的邮件系统——SSL安全

-- EOF --

comments

如果无法加载 请将 disqus.com | disquscdn.com 加入代理