当前位置: 首页 > news >正文

Network 之十四 email 通信架构、Postfix 部署详解

  在之前的博文 Git 之八 详解 Gitlab 本地部署全过程、企业版 PATCH、Gitlab Pages 用到了本地搭建邮件服务器,由于之前对此没有概念,因此,今天专门学习一下(主要是需要配置 Postfix)!

  电子邮件出现在 1960s 晚期,比打开浏览器就要使用的 HTTP 协议早了 20 年左右,是二十世纪人类最伟大的发明之一。这个古老、经典的框架在网络中运行了五十多年,现今仍然是网络中主要的流量类型之一。

通信架构

  如今我们使用电子邮件非常方便,只需要简单在邮件客户端(例如,Outlook、Foxmail)又或者是登录 Web 邮箱,然后写好内容,点击一个发送,邮件就被送出去了。然而,一封邮件从点击发送开开始离开发送者邮箱,经历了一些列的服务,才能最终达到目的用户的邮箱。
在这里插入图片描述

  • MUA(Mail User Agent,邮件用户代理):也称为电子邮件客户端,这些是我们用于发送和接收邮件的应用程序。有两种类型的MUA:

    • 基于客户端:由系统上安装的应用程序访问,例如 Mozilla 的 shundbird,微软的 Outlook 等
    • 基于 Web:使用Web应用程序访问。例如,谷歌 Gmail,雅虎邮件等。
  • MSA(Mail Submmission Agent,邮件提交代理):它是一种计算机程序,用于接收来自MUA的电子邮件并与MTA合作以传递邮件。发送时,您的 MUA 与专用邮件服务器(邮件传输代理 (MTA))进行通信。

    通常是 MTA 的一部分

  • MTA(Mail Transfer Agent,邮件传输代理):也称为邮件服务器、邮件交换器和 MX 主机,MTA 是一种通过将邮件发送到另一个 MTA 来将邮件路由到其最终目的地的软件。这些 MTA 通过 SMTP 相互通信。它有时被称为 SMTP 服务器。

    linux 中的 Postfixsendmail 是常用的 MTA

  • MDA(Mail Ddlivery Agent,邮件投递代理):它是一个计算机软件组件,负责将电子邮件传递到接收者邮件代理。

    1. 在大型邮件服务商哪里,MDA 通常是独立服务器
    2. Postfixsendmail 默认使用的 MDA 是 procmail
  • MRA(Mail Receive Agent,邮件接收代理):负责实现 IMAP 与 POP3协议,与MUA进行交互

    linux 中的 Dovecot 就是一个常用的 MRA

  • MAA(Mail Access Agent):用于将用户连接到系统邮件库,使用POP或IMAP协议接收邮件

  • SMTP(Simple Mail Transfer Potocol,简单邮件传输协议):它是电子邮件传输的互联网标准通信规则。它在端口 25 上运行。它是 TCP/IP 协议应用层的一部分。

  • POP / IMAP(Post Office Protocol 邮局协议 / Internet Message Access Protocol 因特网邮件访问协议):两者都是电子邮件客户端用来从邮件服务器检索电子邮件的应用层因特网标准协议。如果我们使用 POP(目前最新的是第三版,称为 POP3),则整个电子邮件将下载到本地计算机,并且服务器上的副本将被删除。如果使用的协议是 IMAP(目前最新的是第四版),则电子邮件存储在邮件服务器本身中,但用户可以轻松地像在本地计算机中一样操作邮件服务器上的电子邮件。

  • MX 记录: 它是 DNS(域名服务器)区域文件中的一个条目,用于指定用于处理域电子邮件的邮件服务器。它显示相应 SMTP 服务器的 IP 地址。

  • Mailbox: 存储邮件数据。MDA 会将邮件放到不同用户的邮箱中。一般的,有 mbox、Maildir 和 dbmail 等存储格式。mbox 将所有邮件存放到一个文件中,弊端较多。Maildir 则将邮件存为单独的文件。

SPF

  目前网络中的 Email 通信,还是在使用 SMTP 这个协议。SMTP 的全称为 Simple Mail Transfer Protocol,即「简单邮件传输协议」。正如它的名字所暗示的,SMTP 实际上是一个非常简单(甚至简陋)的传输协议,本身并没有很好的安全措施。根据 SMTP 的规则,发件人的邮箱地址是可以由发信方任意声明的。在 SMTP 协议制定的时候也许还好,但在垃圾和诈骗邮件横行的今天,这显然是极不安全的。

  SPF 全称为 Sender Policy Framework,即发件人策略框架。就是用来防止邮件被伪造的。假设邮件服务器收到了一封邮件,来自主机的 IP 是173.194.72.103,并且声称发件人为 email@example.com。为了确认发件人不是伪造的,邮件服务器会去查询 example.com 的 SPF 记录。如果该域的 SPF 记录设置允许 IP 为173.194.72.103的主机发送邮件,则服务器就认为这封邮件是合法的;如果不允许,则通常会退信,或将其标记为垃圾 / 仿冒邮件。

示例见验证章节

  因为不怀好心的人虽然可以「声称」他的邮件来自example.com,但是他却无权操作 example.com的 DNS 记录;同时他也无法伪造自己的 IP 地址。因此 SPF 是很有效的,当前基本上所有的邮件服务提供商(例如 Gmail、QQ 邮箱等)都会验证它。

除了 SPF,还建议设置 DKIM 和 DMARC

中继转发(Relay)

  邮件从一台 MTA 转发到下一台 MTA,这个操作就成为邮件中继转发。如果所有人都能使用某台 MTA 做中继转发,则这台 MTA 成为 Open Relay。这是很危险的,容易被互联网的邮件流量拖垮,且可能被记录到邮箱服务器黑名单上,坏处多多。需要仔细配置 Relay 规则。

Postfix

  Postfix 是一种电子邮件服务器,它是由任职于 IBM 华生研究中心(T.J. Watson Research Center)的荷兰籍研究员 Wietse Venema 为了改良 sendmail 邮件服务器而产生的。最早在 1990 年代晚期出现,是一个开放源代码的软件。

安装

  在 Postfix 安装过程中,会出现两个配置界面。第一个是邮件服务器的配置类型,选择 “Internet Site” 并按回车键。第二个是邮件服务器的名字(默认就是服务器的名字),根据需要修改然后按回车键确认即可。
在这里插入图片描述
  如果在安装过程中,没有正确选择配置也无所谓,后续可以使用命令 sudo dpkg-reconfigure postfix 来重新进行完整的配置。Postfix 在安装过程中会生成 /etc/postfix/main.cf 配置文件,可以直接编辑该文件来修改配置。

  不出意外,配置会打印出 WARNING: /etc/aliases exists, but does not have a root alias. 这个警告。解决方法就是确保 postmaster 指向 root,root 指向自己的用户名或电子邮件地址。注意修改之后,执行 sudo newaliases 以生效。
在这里插入图片描述

配置

  Postfix 的配置文件主要是 /etc/postfix/main.cf/etc/postfix/master.cf 配置文件。其配置参数有上百个(通过 /etc/postfix/main.cf 来控制),但是大多数参数默认即可正常使用。我们可以手动编辑这个文件,以对 Postfix 进行完整的配置。修改之后,必须 sudo postfix reload 才可以使修改生效。

# 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 2 on
# fresh installs.
compatibility_level = 2

# 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_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination

# 运行 postfix 邮件系统的主机的主机名。缺省地,该值被设定为本地机器名。通常做法是指定完整的主机名,例如下面的 mail.zcs.com(仅仅是个示例)
myhostname = mail.zcs.com
# 指定我们自己的域名(下面仅仅是个示例),即邮箱后缀(@ 后面的域名,例如 163.com)。缺省地,postfix 2.5以后版本将 localdomain 作为 mydomain 的值
# 注意,如果域名没有 SPF(Sender Policy Framework),很大概率邮件被退回 
mydomain = zcs.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
# 参数指定 postfix 接收邮件时收件人的域名,换句话说,也就是 postfix 系统要接收什么样的邮件。
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relayhost =
# 指定你所在的网络的网络地址,postfix 系统根据其值来区别用户是远程的还是本地的,如果是本地网络用户则允许其访问。你可以用标准的A、B、C 类网络地址,也可以用CIDR(无类域间路由)地址来表示
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
# 邮箱大小,0 表示不限制,单位是字节
mailbox_size_limit = 0
recipient_delimiter = +
# 指定 postfix 系统监听的网络接口。缺省地,postfix 监听所有的网络接口。
inet_interfaces = all
inet_protocols = all
# 指明发人所在的域名。如果你的用户的邮件地址为 user@domain.com,则该参数指定@后面的域名。缺省地, postfix 使用本地主机名作为 myorigin
myorigin = $mydomain
# 设置邮件保存目录
# Mailbox 方式:即同一个用户的所有邮件内容存储为单个文件,通常保存在/var/spool/mail/目录下文件名与用户名相同(Postfix默认使用)
# Maildir 方式:使用目录结构来存储用户的邮件内容每一个用户使用一个文件夹,每封邮件都作为一个独立的文件存放。
home_mailbox = Maildir/
  1. 使用 postconf -d 可查看所有默认配置
  2. 需要注意 mydomain,Postfix 本身并不发送邮件,实际的 domain 有发送工具指定。例如 mailutils 命令 mail -r xx@xxx.com xxxxx 中的 -r 参数。

  更简单的是手动执行 sudo dpkg-reconfigure postfix 进行可视化的配置。但是需要注意,这样仅仅是配置了最为基本的参数,配置后基本可以正常发送邮件(多数情况下并不符合我们的实际需求,还是需要手动修改 /etc/postfix/main.cf)。下面是每个配置项的说明:

  1. General type of mail configuration(通用邮件配置类型):这个我们选择 Internet Site,表示直接使用本地 SMTP 服务器发送和接收邮件。
    在这里插入图片描述
  2. System mail name(系统邮件名称):这是用于在仅给出地址的帐户部分时构造有效电子邮件地址的基本域(即邮箱域名,例如,xxx@163.com 中对应的就是 163.com)。 例如,我们服务器的主机名是 mail.example.com,但我们可能希望将系统邮件名称设置为 example.com,以便给定用户名 user1,Postfix 将使用地址 user1@example.com。
    在这里插入图片描述
  3. Root and postmaster mail recipient(root 和邮件管理员接收人):root@ 和 postmaster@ 的邮件需要重定向到一个实际的邮箱账户(收件人)。我这里设置为 root 就表示将 root@ 的邮件转到 root 这个收件人的邮箱中。
    在这里插入图片描述
  4. Other destinations to accept mail for(接受邮件的其他目的地):这定义了此 Postfix 实例将接受的邮件目的地。如果您需要添加此服务器负责接收来自其他域名的邮件,可以在此处添加;默认情况下是可以正常工作的。
    在这里插入图片描述
  5. Force synchronous updates on mail queue?(强制对邮件队列进行同步更新?):由于您可能正在使用日志文件系统,因此请在此处选择 No。
    在这里插入图片描述
  6. Local networks(本地网络):这是您的邮件服务器配置为中继邮件的网络列表。默认应适用于大多数方案。如果您选择修改它,请确保对网络范围有非常严格的限制。
    在这里插入图片描述
  7. Mailbox size limit(邮箱大小限制):这可用于限制邮件的大小。设置成 0 后,就不会限制邮件大小了。
    在这里插入图片描述
  8. Local address extension character(本地地址扩展字符):这是可用于将地址的常规部分与扩展名(用于创建动态别名)分开的字符,默认即可。
    在这里插入图片描述
  9. Internet protocols to use(要使用的 Internet 协议):选择 all
    在这里插入图片描述

Hostname

  Postfix 在与其他的 SMTP 服务器进行通信的时候,会使用 hostname 来表名自己的身份。hostname 可以有两种形式:单名字FQDN(Fully Qualified Domain Name)。如果 SMTP 服务器不是用 FQDN 来表明身份,则有可能会被某些 SMTP 拒收。
在这里插入图片描述

domain

  电子邮件地址格式一般为 用户名@主机地址(域名)。虽然使用 root@192.168.10.10 的形式是可以的,但看起来不太习惯,因此,现在多用域名代替 IP。

邮箱账户

  添加用户的简单方法是在操作系统中添加一个新帐户。例如,在 Ubuntu 服务器上,只需要使用 adduser xxx 创建个系统账户就可了,Postfix 将处理剩下的所有工作。

  但是,如果不想为用户创建系统帐户,那就应该设置一个虚拟域,主要注意的是,虚拟域不能配置到 /etc/postfix/main.cf 中的 mydestination 字段 ,详见 Postfix 官网说明Postfix Virtual Domain Hosting Howto。

用户别名

  用户别名功能是一项简单实用的邮件账户伪装技术,可以用来设置多个虚拟信箱的账户以接受发送的邮件,从而保证自身的邮件地址不被泄露,还可以用来接收自己的多个信箱中的邮件。

  实现发不发是通过编辑 aliases 邮件别名服务的配置文件 /etc/aliases。里面定义了大量的用户别名,这些用户别名大多数是Linux 系统本地的系统账户,而在冒号(:)间隔符后面的 root 账户则是实际用来接收这些账户邮件的人。用户别名可以是 Linux 系统内的本地用户,也可以是完全虚构的用户名字。

验证

  Postfix 本身自带了 sendmail 命令,我们可以直接使用该命令来发送邮件。我比较习惯 mailutils,因此,sudo apt install mailutils 安装,然后执行 echo "Content of email" | mail -r dell@zcs.com -s "Email from Postfix" xxx@163.com,查看自己的邮箱
在这里插入图片描述
  需要注意,sendmail 发送时使用的是 /etc/postfix/main.cf 中配置的 domain,而 mailutils 如果没有 -r 参数指定,默认使用 /etc/hostname 中的内容作为 domain。domain 如果是个合法的域名就会被大多数邮箱服务商检查 SPF,而导致退信!

日志

  Postfix 本身将日志存放于 /var/log 目录下,我们可以通过查看日志文件来查找问题。日志文件是 /var/log/mail.log,从邮件日志看到 status=sent,确认邮件发送成功;错误记录文件是 /var/log/mail.err
在这里插入图片描述
  然而,在某次调试时,我手贱删除了其中的 /var/log/mail.log 文件,导致无法再次生成 Log,即使是手动创建了 /var/log/mail.log 文件依旧不行,后来想是不是权限问题,于是有了下面的解决方法:
在这里插入图片描述

参考

  1. https://zhuanlan.zhihu.com/p/28816035
  2. https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-on-ubuntu-20-04
  3. https://blog.csdn.net/qq_43561410/article/details/100009775
  4. https://fedingo.com/postfix-mail-server-configuration-in-linux-step-by-step/
  5. https://www.serverwatch.com/guides/adding-users-and-aliases-for-postfix/
  6. https://ubuntu.com/server/docs/mail-postfix
  7. https://juejin.cn/post/6844903465764782087

相关文章:

  • Tableau8——数据操作
  • python基础知识笔记
  • 基于FPGA的PID控制器设计
  • 程序设计与c语言笔记(一)
  • 【.Net实用方法总结】 整理并总结.NET 中的 System.IO.Pipelines(管道)
  • 深度学习10——卷积神经网络
  • Mybatis 实现原理
  • matplotlib入门
  • JavaScript设计模式——建造者模式
  • Roson的Qt之旅 #124 QNetworkConfigurationManager网络配置管理
  • 天池Python练习02-位运算
  • 国内主机整车EEA架构汇总
  • Java刷题面试系列习题(十三)
  • linux驱动35:工作队列
  • 句向量模型之SimCSE——Pytorch
  • JS 中的深拷贝与浅拷贝
  • download使用浅析
  • httpie使用详解
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JS实现简单的MVC模式开发小游戏
  • leetcode讲解--894. All Possible Full Binary Trees
  • PAT A1092
  • php的插入排序,通过双层for循环
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • 从零开始的无人驾驶 1
  • 关于springcloud Gateway中的限流
  • 力扣(LeetCode)965
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 前端之React实战:创建跨平台的项目架构
  • 算法-图和图算法
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 鱼骨图 - 如何绘制?
  • 最简单的无缝轮播
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • ###STL(标准模板库)
  • #预处理和函数的对比以及条件编译
  • (2)MFC+openGL单文档框架glFrame
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (差分)胡桃爱原石
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (七)c52学习之旅-中断
  • (四)Controller接口控制器详解(三)
  • (算法)N皇后问题
  • (转)ABI是什么
  • (转载)hibernate缓存
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET Standard 的管理策略
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .net 提取注释生成API文档 帮助文档