自建 SMTP 邮件发送服务

搭建自己的 SMTP 邮件发送服务器
序言
SMTP 可以直接购买云厂商的服务,比如 :

Amazon SES SMTP
阿里云邮件推送
也可以自己搭建邮件服务器 —— 发送不限量,综合成本低。

下面,我们一步一步的演示如何自建邮件服务器。

服务器选购
自托管的 SMTP 服务器需要开放了 25、456、587 端口的公网 IP。

常用的公有云默认都封禁了这些端口,发工单可能可以开通,但终归很麻烦。

我建议从那些开放了这些端口并支持设置反向域名的主机商中选购。

在这里,我推荐下 Contabo 。

Contabo 是总部位于德国慕尼黑的主机提供商,成立于 2003 年,价格极具竞争力。

购买币种选择欧元,价格会更便宜 (8GB 内存 4 CPU 的服务器约 529 元人民币每年,买一年免初装费)。

下单时备注 prefer AMD, 选用 AMD CPU 的服务器,性能更佳。

后文,我将以 Contabo 的 VPS 为例,演示如何搭建自己的邮件服务器。

Ubuntu 系统配置
这里操作系统选用 Ubuntu 22.04

如果 ssh 上服务器显示 Welcome to TinyCore 13!(如下图),表示这时候系统还没装完,请断开 ssh,等待几分钟再次登录。

出现 Welcome to Ubuntu 22.04.1 LTS 就是初始化完成,可以继续下面的步骤了。

[可选] 初始化开发环境
这一步是可选的。

为了方便,我把 ubuntu 软件的安装、系统配置放到了 github.com/user-tax-dev/docker_dev_build/tree/main/ubuntu。

运行以下指令可一键安装。

bash <(curl -s https://raw.githubusercontent.com/user-tax-dev/docker_dev_build/main/ubuntu/boot.sh)
中国用户请改用下面的指令,会自动设置语言、时区等。

CN=1 bash <(curl -s https://ghproxy.com/https://raw.githubusercontent.com/user-tax-dev/docker_dev_build/main/ubuntu/boot.sh)
Contabo 启用 IPV6
启用 IPV6 ,这样 SMTP 也可以发送 IPV6 地址的邮件了。

编辑 /etc/sysctl.conf

修改或加入下面几行

net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
然后运行 sysctl -p /etc/sysctl.conf 启用配置

接下来参考 contabo 教程 : 将 IPv6 连接添加到您的服务器

在管理后台找到你的 IPV6 地址,如下图:

然后编辑运行下面的命令

ip addr add YOUR_IPV6_ADDRESS dev eth0
ip route add default via fe80::1 dev eth0
配置成功后,可使用 curl 6.ipw.cn 查看自己外网的 ipv6 地址。

以上操作只是临时启用 ipv6,重启之后会失效。

想永久启用 ipv6,编辑 /etc/netplan/01-netcfg.yaml, 加上如下图所示几行 ( Contabo 默认系统的配置文件已经有这些行,取消注释即可 )

克隆配置仓库 ops
git clone https://github.com/user-tax/ops.git
生成域名 免费 SSL 证书
发送邮件需要 SSL 证书加密和签名。

我们使用 acme.sh 来生成证书。

acme.sh 是开源的自动化证书签发工具,

进入配置仓库 ops ,运行 ./ssl.sh,会在上一级目录创建 conf 文件夹。

目录结构如下图:

从 acme.sh dnsapi 中找到你的 DNS 服务商,编辑 conf/conf.sh 。

然后运行 ./ssl.sh 123.com,就可以为你的域名生成 123.com 以及*.123.com 证书。

首次运行会自动安装acme.sh,并添加自动续期的定时任务。crontab -l 就可以看到,有如下这么一行。

52 0 * * * “/mnt/www/.acme.sh”/acme.sh --cron --home “/mnt/www/.acme.sh” > /dev/null
生成的证书的路径类似 /mnt/www/.acme.sh/123.com_ecc。

证书续期会调用 conf/reload/123.com.sh 脚本,编辑这个脚本,可以添加诸如 nginx -s reload 的指令来刷新相关应用的证书缓存。

用 chasquid 搭建 SMTP 服务器
chasquid 是 Go 语言编写的开源 SMTP 服务器。

作为 Postfix、Sendmail 这些古老的邮件服务器程序的替代品,chasquid 更加简单易上手,也更容易二次开发。

运行 chasquid 配置仓库中的 ./chasquid/init.sh 123.com 会全自动一键安装(替换 123.com 为你的发信域名)。

配置邮件签名 DKIM
DKIM 用于发送邮件的签名,避免信件被当成垃圾邮件。

命令成功运行后,会提示你去设置 DKIM 记录(如下图)。

到你的 DNS 添加 TXT 记录即可(如下图)。

查看服务状态 & 日志
systemctl status chasquid 查看服务状态。

正常运行时状态如下图

grep chasquid /var/log/syslog 或者 journalctl -xeu chasquid 可以查看出错日志。

反向域名配置
反向域名是让 IP 地址可以解析为对应的域名。

设置反向域名,能避免邮件被识别为垃圾邮件。

当邮件接收后,接收服务器将对发送服务器的 IP 地址进行反向域名解析,以确认发送服务器是否具有有效的反向域名。

如果发送服务器没有反向域名或者反向域名与发送服务器的 IP 地址不匹配,接收服务器可能会将该邮件识别为垃圾邮件或拒绝接收。

访问 https://my.contabo.com/rdns,配置如下图

设置完反向域名后,记得配置此域名 ipv4 和 ipv6 的正向解析到该服务器。

编辑 chasquid.conf 的 hostname
修改 conf/chasquid/chasquid.conf 为反向域名的值。

接着运行 systemctl restart chasquid 重启服务。

备份 conf 到 git 仓库

比如我备份 conf 文件夹到自己的 github 流程如下

首先创建私有仓库

进入 conf 目录,然后提交到仓库

git init
git add .
git commit -m “init”
git branch -M main
git remote add origin git@github.com:user-tax-key/conf.git
git push -u origin main
添加发件用户
运行

chasquid-util user-add i@user.tax
可以添加发件用户

效验密码是否设置正确
chasquid-util authenticate i@user.tax --password=xxxxxxx

添加完成用户 , chasquid/domains/user.tax/users 会有更新,记得提交到仓库。

DNS 添加 SPF 记录
SPF ( Sender Policy Framework ) 是一种邮件验证技术,用于防范电子邮件欺诈。

它通过检查发件人的 IP 地址与其所声称的域名的 DNS 记录是否匹配来验证邮件发送者的身份,从而防止欺诈者发送伪造的电子邮件。

添加 SPF 记录,能尽可能避免邮件被识别为垃圾邮件。

如果你的域名服务器不支持 SPF 类型,添加 TXT 类型记录即可。

比如,user.tax 的 SPF 如下

v=spf1 a mx include:_spf.user.tax include:_spf.google.com ~all

_spf.user.tax 的 SPF

v=spf1 a:smtp.user.tax ~all

注意,我这里有 include:_spf.google.com, 这是因为后续我将在谷歌邮箱配置用 i@user.tax 做发信地址。

DNS 配置 DMARC
DMARC 是(Domain-based Message Authentication, Reporting & Conformance)的缩写。

它用于获取 SPF 退信的情况(可能是配置错误导致,也可能是别人在冒充你发送垃圾邮件)。

添加 TXT 记录 _dmarc,

内容如下

v=DMARC1; p=quarantine; fo=1; ruf=mailto:ruf@user.tax; rua=mailto:rua@user.tax

各个参数含义如下

p (Policy)
表示如何处理未通过 SPF (Sender Policy Framework) 或 DKIM (DomainKeys Identified Mail) 验证的邮件。p 参数可以设置为以下三个值之一:

none:不采取任何行动,仅将验证结果通过邮件报告机制反馈给发件人。
quarantine:将未通过验证的邮件放入垃圾邮件文件夹,但不会直接拒绝邮件。
reject:直接拒绝未通过验证的邮件。
fo (Failure Options)
指定报告机制返回的信息量。它可以设置为以下值之一 :

0:报告所有邮件的验证结果
1:仅报告未通过验证的邮件
d:仅报告域名验证失败
s:仅报告 SPF 验证失败
l:仅报告 DKIM 验证失败
rua & ruf
rua(Reporting URI for Aggregate reports):接收聚合报告的邮件地址
ruf(Reporting URI for Forensic reports):接收详细报告的邮件地址
添加 MX 记录转发来信到谷歌邮箱
因为没找到免费的支持万能地址 (Catch-All,能接收任何发送到此域名的邮件,不限制前缀)的企业邮箱,所以我用 chasquid 把所有的邮件都转发到 我的 Gmail 信箱。

如果你有自己付费的企业邮箱,请不要修改 MX,并跳过这一步。

编辑 conf/chasquid/domains/user.tax/aliases, 设置转发邮箱

  • 表示所有邮件,i 是上面创建的发信用户邮箱前缀。想转发邮件,每个用户都需要添加一行。

然后添加 MX 记录即可 (我这里直接指向反向域名的地址,如下图第一行) 。

配置完成后,可以用其他邮箱发件到 i@user.tax 和 any123@user.tax 看看是否能在 Gmail 收到信件。

如果不能收到,请检查 chasquid 的日志 ( journalctl -n 10 --no-pager --no-hostname -u chasquid -f 或者grep chasquid /var/log/syslog)。

用谷歌邮箱发送 i@user.tax 的邮件
谷歌邮箱收件之后,自然希望回信也用 i@user.tax 而不是 i.user.tax@gmail.com 。

访问 https://mail.google.com/mail/u/1/#settings/accounts ,点击 『添加其他电子邮件地址』。

接着,输入被转发到的邮箱收到的验证码即可。

最后,可以将其设置为默认发信地址(同时选择以相同地址回复)。

如此,我们就完成了 SMTP 发信服务器的搭建以及同时用谷歌邮箱收发邮件。

发送测试邮件,检查配置是否成功
进入 ops/chasquid

运行 direnv allow 安装依赖 (前文一键初始化过程中已经安装 direnv 并且在 shell 添加了 hook)

然后运行

user=i@user.tax pass=xxxx to=iuser.link@gmail.com ./sendmail.coffee
参数含义如下

user: SMTP 的用户名
pass: SMTP 的密码
to: 收件人
就可以发送测试邮件了。

建议用 Gmail 收测试邮件,方便查看各项配置是否成功。

TLS 标准加密
如下图,有这个小锁,表示 SSL 证书已经成功启用。

然后点击『显示原始邮件』

DKIM
如下图,Gmail 原始邮件页面显示 DKIM,即为 DKIM 配置成功。

检查原始邮件头部的 Received,还可以看到发信地址是 IPV6,这表示 IPV6 也配置成功了。

https://zhuanlan.zhihu.com/p/612674402?utm_id=0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(C)一些题12

1&#xff0e;若指针 p 已正确定义&#xff0c;要使 p 指向两个连续的整型动态存储单元&#xff0c;不正确的语是 A ) p 2*( int *) malloc ( sizeof ( int )); B ) p ( int *) malloc (2* sizeof ( int )); C ) p ( int *) malloc (4*2); D ) p ( int ") calloc (2…

飞天使-docker知识点2-dockerfile构建镜像

文章目录 dockerfile 简介dockerfile 构建实例1dockerfile 直接构建nginx 本地镜像docke tag dockerfile 简介 DockerFile 可以说是一种可以被 Docker 程序解释的脚本&#xff0c;DockerFile 是由一条条的命令组成的&#xff0c;每条命令对应 linux 下面的一条命令&#xff0c…

SimCLR损失函数详解

图片来源&#xff1a;Self-Supervised Learning 超详细解读 (二)&#xff1a;SimCLR系列 文章目录 1. 数据增强2. 获得图片表征3. 正样本和负样本构建4. 计算相似度5. 计算图片之间相似的概率6. 损失函数为什么需要大规模的batchsize&#xff1f; 1. 数据增强 有一批batchsize…

LeetCode-旋转链表问题

1.旋转链表 题目描述&#xff1a; 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 思路&#xff1a; 这里向右移动k个位置&#xff0c;相当于从链表的倒数第k个节点处断开&#xff0c;之后再将断开的两个子链表按照相反顺序…

centos日常运维随记

# 需要生成随机字符及数字 rootAAA:~# echo $RANDOM | md5sum |cut -c 3-29 e7e8942a791146531f613c7c757 # echo $RANDOM 产生随机数据 # md5sum 随机数生成md5值 # cut -c 3-29 :md5产生的是32的md5数&#xff0c;使用cut -c 对这个数进行 第3位到第29位的截取# 在现有的…

【数据结构和算法】--队列

目录 队列的概念及结构队列的实现初始化入队出队其他一些队列函数 小结队列相关题目 队列的概念及结构 队列是只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 的原则。 入队列&#xf…

持续集成交付CICD:通过API方式上传Nexus制品

目录 一、实验 1.通过API方式上传Nexus制品 二、问题 1.如何通过API方式上传PNG图片 2.如何通过API方式上传tar.gz 与 ZIP文件 3.如何通过API方式上传Jar file文件 4.如何通过API方式上传制品&#xff08;maven类型的制品&#xff09;文件 5.如何下载制品 一、实验 1.通…

提升开发效率的免费API好物

日出日落&#xff1a;支持国内3400个城市以及国际4万个城市&#xff0c;获取指定城市/地点每日日出时间、日落时间&#xff1b;同时也支持全球任意经纬度查询&#xff0c;接口会返回该经纬度最近的日出日落信息。月出月落和月相&#xff1a;支持国内3400个城市以及国际4万个城市…

各地加速“双碳”落地,数字能源供应商怎么选?

作者 | 曾响铃 文 | 响铃说 随着我国力争2030年前实现“碳达峰”、2060年前实现“碳中和”的“双碳”目标提出&#xff0c;为各地区、各行业的低碳转型和绿色可持续发展制定“倒计时”时间表&#xff0c;一场围绕“数字能源”、“智慧能源”、“新能源”等关键词的创新探索进…

【教程】Ipa Guard为iOS应用提供免费加密混淆方案

概述&#xff1a;使用ios加固工具对ios代码保护&#xff0c;保护ios项目中的核心代码&#xff0c; #ipagurd年终大促百厂联动暖冬特惠&#xff0c;超多软控件立享惊喜优惠>> ​ 简介 iOS加固保护是直接针对ios ipa二进制文件的保护技术&#xff0c;可以对iOS APP中的可…

Leetcode—113.路径总和II【中等】

2023每日刷题&#xff08;五十七&#xff09; Leetcode—113.路径总和II 实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* …

使用 Taro 开发鸿蒙原生应用 —— 当 Taro 遇到纯血鸿蒙 | 京东云技术团队

纯血鸿蒙即将到来 在今年 8 月的「2023年华为开发者大会&#xff08;HDC.Together&#xff09;」上&#xff0c;华为正式官宣「鸿蒙Next」&#xff0c;这个更新的版本将移除所有的 AOSP 代码&#xff0c;彻底与 Android 切割&#xff0c;使其成为一个完全自主研发的操作系统&a…

数据挖掘目标(Kaggle Titanic 生存测试)

import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns1.数据导入 In [2]: train_data pd.read_csv(r../老师文件/train.csv) test_data pd.read_csv(r../老师文件/test.csv) labels pd.read_csv(r../老师文件/label.csv)[Su…

SqlServer中,数字-null的问题

一、业务描述 叫货单&#xff0c;已知叫货金额&#xff0c;填写本次付款金额&#xff0c;计算待付款金额 二、问题 在计算待付款金额时&#xff0c;偶尔会出现待付款金额为空的情况&#xff0c;百思不得其解 三、解决 仔细检查&#xff0c;发现了猫腻。 简单的说&#xff…

阿里云SMC迁移RedHat/CentOS 5 内核升级

阿里云SMC迁移RedHat/CentOS 5 内核升级 1. 起因 服务器需要迁移上阿里云,有几台服务器用的是Redhat 5.x,在使用SMC进行迁移时出现以下报错. [2023-12-13 09:50:55] [Error] Check System Info Failed, codeS16_111, msgGet OS Info Failed: [error] grub is too old for C…

33、变种卷积 - 分组卷积

这一节再了解一个卷积的变种,叫作分组卷积,这部分了解即可。 1、 什么是分组卷积 网上有很多关于分组卷积的资料。我整理了下,其实分组卷积是将卷积在channel 维度分组来计算,以达到将一个大卷积分成多个小卷积的目的。 为了清晰,我将卷积操作简化为一次最简单的乘累加运…

冒泡排序(函数)

冒泡排序&#xff0c;将一个列表中的两个元素进行比较&#xff0c;并将最小的元素交换到顶部。两个元素中较小的会冒到顶部&#xff0c;而较大的会沉到底部&#xff0c;该过程将被重复执行&#xff0c;直到所有元素都被排序。 输入格式: 输入在第1行中给出N&#xff08;1<N…

十大shell脚本任务(二)备份和恢复脚本

日志文件分析器&#xff1a; 目标&#xff1a;编写一个脚本&#xff0c;自动分析服务器日志文件&#xff0c;提取关键错误信息&#xff0c;并发送通知。价值&#xff1a;实时监控系统状态&#xff0c;及时响应问题。连接&#xff1a;十大shell脚本任务&#xff08;一&#xff0…

路径总和(递归)

112. 路径总和 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &a…