ubuntu自建企业邮箱(ipv6+postfix+dovecot+mysql)

国内免费邮箱限制多,最近部署odoo要用到邮箱的bounce,和catchall功能,国内免费邮箱都不支持,于是准备自己架设一个邮件服务器记录一下。

前置条件

有公网IP/服务器25端口能通信(如无此条件,放弃)

本来想搞个☁️服务器做邮件服务器,但国内都是封了25端口,所以放弃。家里有条中国移动的宽带有IPV6,而且25端口也能通信(伟大的中国移动)中国电信就不行。

首先域名解析设置:


1.安装nginx 本站教程

2.安装acme.sh 方便搞到ssl证书。

curl https://get.acme.sh | sh -s email=xnb.mail@gmail.com

国内把证书服务器换成 letsencrypt

acme.sh --set-default-ca --server letsencrypt

 

申请证书

#进入nginx配置文件目录
cd /etc/nginx/conf.d
mv default.conf xnb.xyz.conf
vi xnb.xyz.conf
#将server_name改成 xnb.xyz
nginx -s reload
acme.sh --issue -d xnb.xyz

将证书布署到相应目录以便使用,我喜欢在/etc/nginx/cert下每个域名一个目录。

cd /etc/nginx
mkdir cert
mkdir -p /etc/nginx/cert/xnb.xyz

acme.sh --install-cert -d xnb.xyz --key-file /etc/nginx/cert/xnb.xyz/key.pem --fullchain-file /etc/nginx/cert/xnb.xyz/cert.pem --reloadcmd "service nginx force-reload"

方正先放在这里,等一会使用。记住这个路径

3.安装mysql数据库

新建一个数据库 mailserver,管理账号为:mail/Mail202$

创建虚拟域表,作为认证域。该表是邮件服务器用以接收邮件的域名:

 

-- 建立表
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,'xnb.xyz');

创建用户表,用于用户身份认证。

-- 创建用户表
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'),'a@xnb.xyz');
insert into virtual_users values(2,1,md5('123456'),'b@xnb.xyz');

创建别名表.该表作用相当于当 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,'a@xnb.xyz','b@xnb.xyz');

4.安装postfix及相关软件

apt update
apt install postfix postfix-mysql dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-mysql

正常会出现向导配置,如果没有。运行  sudo dpkg-reconfigure postfix 会出现向导。

 

有几张图忘截了,一般按默认值,和你需要选择。

接下来配置main.cf

cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
vim /etc/postfix/main.cf

参考我的修改

 

# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 3.6 on
# fresh installs.
compatibility_level = 3.6


#
## TLS parameters
#smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
#smtpd_tls_security_level=may
#
#smtp_tls_CApath=/etc/ssl/certs
#smtp_tls_security_level=may
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# 使用自己的ssl证书
smtpd_tls_cert_file=/etc/nginx/cert/xnb.xyz/fullchain.pem
smtpd_tls_key_file=/etc/nginx/cert/xnb.xyz/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


smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
#修改 myhostname为如下的值:
myhostname = xnb.xyz
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
#myorigin = /etc/mailname
#修改 myorigin 为如下的值:
myorigin = $myhostname
#mydestination = $myhostname, ithb.vip, ali-cd2, localhost.localdomain, localhost
mydestination = localhost
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
#确保将邮件投递给 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


创建main.cf里面最后加入的三项参数对应的文件。

创建/etc/postfix/mysql-virtual-mailbox-domains.cf,内容如下:

#数据库用户,密码,数据库名 按你的配置
user = mail
password = passowd
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 xnb.xyz mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

创建/etc/postfix/mysql-virtual-mailbox-maps.cf,内容如下:

user = mail
password = password
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 a@xnb.xyz mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

最后创建/etc/postfix/mysql-virtual-alias-maps.cf,内容如下:

user = mail
password = password
port = 3306
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

同样重启 postfix,验证能否正确找到别名,并返回:

service postfix restart
postmap -q b@xnb.xyz mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf 

修改/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" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd
#smtp      inet  n       -       y       -       1       postscreen
#smtpd     pass  -       -       y       -       -       smtpd
#dnsblog   unix  -       -       y       -       0       dnsblog
#tlsproxy  unix  -       -       y       -       0       tlsproxy
# Choose one: enable submission for loopback clients only, or for any client.
#127.0.0.1:submission 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_tls_auth_only=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=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
# Choose one: enable smtps for loopback clients only, or for any client.
#127.0.0.1:smtps inet n  -       y       -       -       smtpd
#smtps     inet  n       -       y       -       -       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=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
#628       inet  n       -       y       -       -       qmqpd
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
#qmgr     unix  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent.  See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
#
# Specify in cyrus.conf:
#   lmtp    cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Specify in main.cf one or more of the following:
#  mailbox_transport = lmtp:inet:localhost
#  virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus     unix  -       n       n       -       -       pipe
#  flags=DRX user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix  -       n       n       -       -       pipe
#  flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}

 

5.配置 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 支持,如下图所示:

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

修改/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
}

 

 

我的文件参考:

# Authentication for SQL users. Included from 10-auth.conf.
#
# <doc/wiki/AuthDatabase.SQL.txt>

passdb {
  driver = sql

  # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
  args = /etc/dovecot/dovecot-sql.conf.ext
}

# "prefetch" user database means that the passdb already provided the
# needed information and there's no need to do a separate userdb lookup.
# <doc/wiki/UserDatabase.Prefetch.txt>
#userdb {
#  driver = prefetch
#}

userdb {
  driver = sql
#  args = /etc/dovecot/dovecot-sql.conf.ext
  args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

# If you don't have any user-specific settings, you can avoid the user_query
# by using userdb static instead of userdb sql, for example:
# <doc/wiki/UserDatabase.Static.txt>
#userdb {
  #driver = static
  #args = uid=vmail gid=vmail home=/var/vmail/%u
#}

修改/etc/dovecot/dovecot-sql.conf.ext: 在大约33行加入:


driver = mysql
connect = host=127.0.0.1 port=3306 dbname=mailserver user=mail password=password

#换成你的数据库用户和密码

接着取消 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:

首先将 启用pop3s和imaps收信,如下图所示:

然后找到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 auth-userdb {
    mode = 0600
    user = vmail
    #group =
  }

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

  # Auth process is run as this user.
  #user = $default_internal_user
}

参考如图

 

最后找到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 了,就是之前用acme.sh部署的证书路:

# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
# dropping root privileges, so keep the key file unreadable by anyone but
# root. Included doc/mkcert.sh can be used to easily generate self-signed
# certificate, just make sure to update the domains in dovecot-openssl.cnf
ssl_cert = </etc/nginx/cert/xnb.xyz/cert.pem
ssl_key = </etc/nginx/cert/xnb.xyz/key.pem

如图

到这里所有的配置都 OK,重启 postfix,dovecot 后就可以用邮箱客户端(比如 foxmail)连接了。

service postfix restart
service dovecot restart

结束
配合一个邮件客户端看似很简单,实际上还是有很多坑的,看看上面那么多的配置项就知道了,一定要耐心。

如果无法登陆,可以看看 postfix 和 dovecot 的日志报错情况,再去修改。日志位置在/var/log

 

版权声明:
作者:xiaoniba
链接:https://blog.xiaoniba.com/2024/02/07/ubuntu%e8%87%aa%e5%bb%ba%e4%bc%81%e4%b8%9a%e9%82%ae%e7%ae%b1%ef%bc%88ipv6postfixdovecotmysql/
来源:小泥吧的博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>