5

debian下使用Postfix,Dovecot,MySQL,roundcube搭建邮件服务器

 2 years ago
source link: https://www.bobobk.com/675.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

debian下使用Postfix,Dovecot,MySQL,roundcube搭建邮件服务器

2022年6月18日

| 技术

网上有很多使用Postfix搭建邮件服务器的文章,但是没有一个能够顺利搭建的,经过多次摧毁重建终于完成了邮件系统,并且可以顺利收发邮件。本文将介绍在Debian系统中使用Postfix+Dovecot+MySQL+roundcube搭建邮件服务器。

首先介绍基本要求:域名,带公共ip的服务器,服务器能够开放邮件端口,25,110,143,465,587,993,995。如果没开放的话就可以放弃了。当然还有必不可少的linux使用技能。想vi什么的都不知道的话就算了,因为设置非常复杂,我也是经过大量搜索实践才完成。

各个组件的用途:

Postfix: 是一个标准的MTA「Mail Transfer Agent」服务器,它负责通过SMTP协议管理发送到本机的邮件以及由本机发向外界的邮件。在本例中,Postfix会把邮件的本地投递工作「接受到邮件之后将邮件存档到本地磁盘」交给Dovecot的LMTP服务「Local Mail Transfer Protocol service」处理。

Dovecot: 是IMAP/POP服务器用以接收外界发送到本机的邮件。Dovecot的工作内容包括:验证用户身份以确保邮件不会被泄露。在本例中,Dovecot将负责账号密码验证工作,我们会配置Dovecot查询本地的MySQL数据库以确认邮件账号身份。

MySQL: 数据库,用于存储所有的域名与用户信息,其中包括:需要监听的域名信息、用户邮箱地址、登录密码、邮箱别名「alias」等

下面直接介绍在军哥lnmp环境下的邮件服务器搭建过程。

DNS配置

首先是域名,这里以bobobk.com为例,另外也准备一个用于收发邮件的服务器。然后去域名商设置DNS。以cloudflare为例, 这里需要设置mx记录,mail服务器和spf防垃圾txt设置,这里另外设置一个mx的a记录用于记录不经过cdn的解析。 以本域名为例

A     imap      107.148.0.0    DNS only  Auto
A     mx      107.148.0.0    DNS only  Auto
A     pop      107.148.0.0    DNS only  Auto
A     smtp      107.148.0.0    DNS only  Auto
MX     bobobk.com      	mx.bobobk.xyz    DNS only  Auto
TXT     bobobk.com      v=spf1 mx mx:mx.bobobk.com ip4:107.148.0.0 ~all    DNS only  Auto

设置hostname

设置好服务器的hostname和hosts文件 首先是/etc/hostname

mx.bobobk.com

hosts文件,/etc/hosts

localhost mx.bobobk.com bobobk.com

随后更新hostname

hostname -F /etc/hostname

postfix,dovecot的安装

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

在postfix安装时提示类型,选择Internet Site,system mail name直接设置mx.bobobk.com

mysql初始化,用户设置

这里需要两个数据库,一个为postfix,用于用户账号密码验证。一个roundcube,用于邮件网页端登陆发送收取邮件的数据库。

首先是postfix的数据库和创建

CREATE DATABASE postfix;
grant all privileges on postfix.* to  'postfixadmin'@'localhost' IDENTIFIED BY 'postfixadminp';
use postfix;
##域名表
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(106) 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 virtual_domains(id,name) values(1,'bobobk.com');     
insert into virtual_domains(id,name) values(2,'mx.bobobk.com');
# 用户
insert into virtual_users(id,domain_id,password,email) values(1,1,'testpassword','[email protected]');
insert into virtual_users(id,domain_id,password,email) values(2,1,'testpassword','[email protected]');
#别名
insert into virtual_aliases(id,domain_id,source,destination)  values values (1,2,'[email protected]','[email protected]');

顺便查看插入的数据

select * from virtual_domains;  
select * from virtual_users;  
select * from virtual_aliases;

Postfix配置修改

接下来进行postfix的配置修改 首先是/etc/postfix/main.cf文件,直接替换就好,记得修改bobobk.com成你的域名

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
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 2 on
# fresh installs.
compatibility_level = 2

# TLS parameters
smtpd_tls_cert_file=/usr/local/nginx/conf/ssl/mx.bobobk.com/fullchain.cer
smtpd_tls_key_file=/usr/local/nginx/conf/ssl/mx.bobobk.com/mx.bobobk.com.key
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtp_sasl_auth_enable = yes
smtpd_sasl_auth_enable = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
# Authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

#
smtpd_helo_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_recipient,
        reject_unknown_recipient_domain,
        reject_unlisted_recipient,
        reject_unauth_destination
smtpd_sender_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_sender,
        reject_unknown_sender_domain
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = mx.bobobk.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydomain = bobobk.com
myorigin = $mydomain
mydestination = localhost
#mydestination = $myhostname, mx.bobobk.com, debian.debian, localhost.debian, 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

# Handing off local delivery to Dovecot's LMTP, and telling it where to store mail
virtual_transport = lmtp:unix:private/dovecot-lmtp

# Virtual domains, users, and aliases
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-users.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias.cf,

# Even more Restrictions and MTA params
disable_vrfy_command = yes
strict_rfc821_envelopes = yes
#smtpd_etrn_restrictions = reject
#smtpd_reject_unlisted_sender = yes
#smtpd_reject_unlisted_recipient = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtp_always_send_ehlo = yes
#smtpd_hard_error_limit = 1
smtpd_timeout = 30s
smtp_helo_timeout = 15s
smtp_rcpt_timeout = 15s
smtpd_recipient_limit = 40
minimal_backoff_time = 180s
maximal_backoff_time = 3h

# Reply Rejection Codes
invalid_hostname_reject_code = 550
non_fqdn_reject_code = 550
unknown_address_reject_code = 550
unknown_client_reject_code = 550
unknown_hostname_reject_code = 550
unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550

然后是/etc/postfix/mysql-virtual-domains.cf 文件

user = postfixadmin
password = postfixadminp
hosts = 127.0.0.1
dbname = postfix
query = SELECT 1 FROM virtual_domains WHERE name='%s'

/etc/postfix/mysql-virtual-users.cf 文件

user = postfixadmin
password = postfixadminp
hosts = 127.0.0.1
dbname = postfix
query = SELECT 1 FROM virtual_users WHERE email='%s'

/etc/postfix/mysql-virtual-alias.cf 文件

user = postfixadmin
password = postfixadminp
hosts = 127.0.0.1
dbname = postfix
query = SELECT destination FROM virtual_aliases WHERE source='%s'

接着是/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
submission inet n       -       y       -       -       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_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject  #$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
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
#  -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 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
#
# ====================================================================
# 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=DRhu 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
#  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=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
  ${nexthop} ${user}

postfix测试

重启postfix

systemctl restart postfix

开始测试前面设置的mysql数据

postmap -q bobobk.com mysql:/etc/postfix/mysql-virtual-domains.cf
1
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-users.cf
1
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-alias.cf
[email protected]

前两条返回1,后面返回对应的域名,说明测试成功。

dovecot设置

首先是/etc/dovecot/dovecot.conf文件下面三项需要修改

!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap pop3 lmtp

postmaster_address = postmaster at bobobk.com

然后是/etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:/home/mail/%d/%n/
mail_privileged_group = 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

再来是/etc/dovecot/conf.d/auth-sql.conf.ext

passdb {
  driver = sql

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

userdb {
  driver = static
  args = uid=vmail gid=vmail home=/home/mail/%d/%n
}

文件/etc/dovecot/dovecot-sql.conf.ext

driver = mysql
default_pass_scheme = PLAIN
password_query = \
   SELECT email as user, password FROM virtual_users WHERE email='%u';
connect = host=127.0.0.1 dbname=postfix user=postfixadmin password=postfixadminp


文件/etc/dovecot/conf.d/10-master.conf

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service lmtp {

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

service imap {
}

service pop3 {
}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
  unix_listener auth-userdb {
    mode = 0666
    user = vmail
    #group = 
  }
  user = dovecot
}

service auth-worker {
  user = vmail
}

service dict {
  unix_listener dict {
  }
}

文件/etc/dovecot/conf.d/10-ssl.conf

ssl = yes
ssl_cert = </usr/local/nginx/conf/ssl/mx.bobobk.com/fullchain.cer
ssl_key = </usr/local/nginx/conf/ssl/mx.bobobk.com/mx.bobobk.com.key
chown -R vmail:dovecot /etc/dovecot

重启dovecot

systemctl restart dovecot

roundcube的安装配置

首先是确保第一步dns设置到了本ip,然后将roungcube下载到对应站点文件夹,比如mail.bobobk.com的话就是

## lnmp vhost add添加邮件域名后再运行
cd /home/wwwroot/mail.bobobk.com
wget https://github.com/roundcube/roundcubemail/archive/refs/heads/master.zip
unzip master.zip
mv roun*/* .
rmdir -rf roundcube*
chown -R www:www /home/wwwroot/mail.bobobk.com

接下来进行roundcube的安装 浏览器进入 mail.bobobk.com 一步一步进行安装,需要注意php需要的环境

cURL:  OK
FileInfo:  OK
Exif:  OK
Iconv:  OK
LDAP:  OK
GD:  OK
Imagick:  OK
Zip:  OK

就是FileInfo,Exif,LDAP,Imagick需要安装,目前lnmp1.9的话可以通过addon.sh添加,1.8貌似添加不上,所以要以最新的lnmp脚本安装,如果宝塔的话没测试不知道。 安装好后可以将删除installer文件夹。

主要进行端口的测试,开放端口,我使用了ufw,注意不要把自己关在了外面。

apt install ufw -y
ufw allow 22
ufw allow 80
ufw allow 443
ufw allow 110
ufw allow 143
ufw allow 993
ufw allow 995

安装端口测试软件net-tools,telnet,mailutils

apt install net-tools -y
apt install telnet -y
apt install mailutils -y

端口开放检测

netstat -nlp|grep -v unix
tcp        0      0 0.0.0.0:143             0.0.0.0:*               LISTEN      25043/dovecot       
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      20750/nginx: worker 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      20750/nginx: worker 
tcp        0      0 0.0.0.0:465             0.0.0.0:*               LISTEN      11857/master        
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      5790/sshd           
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      11857/master        
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      20750/nginx: worker 
tcp        0      0 0.0.0.0:993             0.0.0.0:*               LISTEN      25043/dovecot       
tcp        0      0 0.0.0.0:995             0.0.0.0:*               LISTEN      25043/dovecot       
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      31374/mysqld        
tcp        0      0 0.0.0.0:587             0.0.0.0:*               LISTEN      11857/master        
tcp        0      0 0.0.0.0:110             0.0.0.0:*               LISTEN      25043/dovecot   

可以看到postfix监听的25,465,587端口,dovecot监听的110,143,993,995是开放的,不过前面ufw防火墙没有开放postfix的端口,是为了防止邮件被滥用。

dovecot登陆检测

使用110端口测试,使用前面数据库的明文密码,user和pass为账号和密码

telnet 127.0.0.1 110
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
+OK Dovecot ready.
user [email protected]
+OK
pass testpassword
+OK Logged in.
quit
+OK Logging out.
Connection closed by foreign host.

检测接收邮件

那么就可以接下来进行邮件收取的操作了,直接进入roundcude进行验证,前面设置的邮件密码是 [email protected],密码是testpassword,然后向google邮箱发个邮件试试,结果发现已经成功。

my new server test mail
rom
Stored with zero-access encryption
tech<[email protected]>
Star message
Inbox
PM 12:14
To
[email protected]
this is the email from bobobk.com

本文将在debian上搭建邮件服务器成功后的配置过程和文件进行简单说明,因为各配置的意义实在很多,有需求的可以多看看我参考的资料,各资料均有问题,请搭配本文使用0-0

最佳 其次 也好


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK