邮件服务器搭建教程(只收不发)

Administrator 3 2025-05-31

第零步:确认 DNS A 记录

请确保您已经为 mail.xxx.com 设置了正确的 A 记录:

  • 类型 (Type): A

  • 名称 (Name): mail

  • 内容 (Content): 89.183.126.152

  • 类型 (Type): A

  • 名称 (Name): *

  • 内容 (Content): 89.183.126.152

  • 类型 (Type): A

  • 名称 (Name): @

  • 内容 (Content): 89.183.126.152

  • 类型 (Type): mx

  • 名称 (Name): xxx.com

  • 内容 (Content): 89.183.126.152

第一步:服务器基础环境准备

登录到您重装好的服务器,执行以下操作。

  1. 更新系统软件包:

    apt update

    apt upgrade -y

2.安装 Python 和相关工具:

apt install python3 python3-pip python3-venv -y


第二步:安装并运行 MailHog

MailHog 将作为我们独立的邮件接收服务。

  1. 下载 MailHog:

    # 切换到 Home 目录

    cd ~

    # 从 GitHub 下载 MailHog 的二进制文件

    wget https://github.com/mailhog/MailHog/releases/download/v1.0.1/MailHog_linux_amd64

  2. 赋予执行权限:

    chmod +x MailHog_linux_amd64

3.让 MailHog 在后台运行:

nohup ./MailHog_linux_amd64 > mailhog.log 2>&1 &


第三步:配置网络和防火墙

这是连接外部世界和 MailHog 的关键。

  1. 配置 VPS 提供商的防火墙 (最重要)登录到您的 VPS 提供商的管理后台网页,找到这台服务器的网络安全组(Security Group),并添加入站规则(Inbound Rules)来放行以下三个端口的 TCP 流量:

    • 25 (SMTP,接收邮件用)

    • 8025 (MailHog 的网页界面和 API)

    • 2099 (我们自己的 Python API)

  2. 在服务器内部设置端口转发 由于 MailHog 监听 1025 端口,我们需要将标准的邮件端口 25 转发过去。

    iptables -t nat -A PREROUTING -p tcp --dport 25 -j REDIRECT --to-port 1025

第四步:部署 Python API 服务

这个服务将作为我们读取邮件的接口。

  1. 创建项目目录和虚拟环境:

    Bash

    mkdir -p /opt/mail_api
    cd /opt/mail_api
    python3 -m venv venv
    
  2. 激活虚拟环境并安装依赖包:

    Bash

    source venv/bin/activate
    # 注意:这次我们一次性把所有需要的包装好
    pip install Flask Gunicorn requests
    
  3. 创建 API 脚本:

    Bash

    nano mail_reader.py
    

    将下面的全部代码粘贴进去,然后按 Ctrl+X, Y, Enter 保存退出。

    Python

    # -*- coding: utf-8 -*-
    from flask import Flask, request, Response
    import requests
    import re
    
    app = Flask(__name__)
    
    MAILHOG_API = "http://localhost:8025/api/v2/messages"
    VALID_TOKEN = "2088"
    
    @app.route("/Mail")
    def get_mail():
        token = request.args.get("token")
        # 这现在是我们要精确查找的目标邮箱地址
        mail_address_to_find = request.args.get("mail")
    
        if token != VALID_TOKEN:
            return "❌ 无效的 token!", 401
        if not mail_address_to_find:
            return "❌ 参数错误:请提供需要查找的 mail 地址。", 400
    
        try:
            # 获取最新的50封邮件,增加找到目标邮件的概率
            response = requests.get(MAILHOG_API, params={'limit': 50})
            response.raise_for_status()
            data = response.json()
            
            messages = data.get('items', [])
            if not messages:
                return "❌ MailHog 中没有任何邮件。", 404
    
            subject_expected_1 = "Verify your email address"
            subject_expected_2 = "验证您的电子邮件地址。"
    
            # 遍历所有近期邮件,寻找收件人匹配的那一封
            for msg in messages:
                headers = msg.get('Content', {}).get('Headers', {})
                
                # 提取收件人地址
                # To 字段是一个列表,我们取第一个。可能包含 "Name <email@addr>" 格式
                to_header_list = headers.get('To', [])
                if not to_header_list:
                    continue
                
                recipient_in_mailhog = to_header_list[0]
    
                # 检查收件人地址是否匹配
                if mail_address_to_find not in recipient_in_mailhog:
                    continue # 如果收件人不匹配,跳过这封邮件
    
                # --- 收件人匹配成功后,才开始检查主题 ---
                subject = headers.get('Subject', [""])[0]
                if subject_expected_1.lower() not in subject.lower() and subject_expected_2 not in subject:
                    continue # 如果主题不匹配,也跳过
    
                # --- 收件人和主题都匹配成功,才开始提取验证码 ---
                body = msg.get('Content', {}).get('Body', "")
                match = re.search(r"\b(\d{6})\b", body)
    
                if match:
                    # 找到了!删除邮件并返回内容
                    #msg_id = msg.get('ID')
                    #if msg_id:
                        #try:
                            #requests.delete(f"http://localhost:8025/api/v1/messages/{msg_id}")
                        #except requests.RequestException:
                            #pass
                    
                    return Response(body, mimetype="text/html; charset=utf-8")
    
            # 如果循环结束了还没找到,说明没有符合所有条件的邮件
            return f"❌ 未找到发送给 <{mail_address_to_find}> 且主题为“{subject_expected_1}”或“{subject_expected_2}”并包含验证码的邮件。", 404
    
        except requests.RequestException as e:
            return f"❌ 请求 MailHog API 出错:{e}", 500
        except Exception as e:
            return f"❌ 处理邮件时发生未知错误:{e}", 500
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=2099)
    


第五步:启动服务并进行最终测试




启动您的 Python API 服务: 确保您还在 /opt/mail_api 目录下,并且虚拟环境 (venv) 已激活。

Bash

gunicorn --workers 2 --bind 0.0.0.0:2099 mail_reader:app

保持这个终端窗口在前台运行,以便观察日志。

  • 发送测试邮件: 从您的个人邮箱,发送一封测试邮件到 test@mail.xxx.com

    • 主题: Verify your email address

    • 内容: 包含一个6位数字,例如 Your code is 987654

  • 调用 API: 等待半分钟,然后在您的本地电脑上,打开终端并执行 curl 命令(注意使用您的新域名和真实IP):

    Bash

    curl "http://89.128.116.153:2099/Mail?token=2088&mail=test@mail.xxx.com"