0

0

使用 PHP 获取域名的所有 MX 记录及其对应的 PTR 记录

DDD

DDD

发布时间:2025-10-04 09:56:24

|

388人浏览过

|

来源于php中文网

原创

使用 PHP 获取域名的所有 MX 记录及其对应的 PTR 记录

本文详细介绍了如何使用 PHP 获取指定域名的所有邮件交换 (MX) 记录,并进一步查询这些 MX 记录所对应 IP 地址的反向 DNS (PTR) 记录。通过利用 getmxrr()、gethostbynamel() 和 dns_get_record() 等 PHP 函数,我们将构建一个健壮的解决方案,以确保邮件服务器的合法性验证,从而有效避免邮件被标记为垃圾邮件。

理解 MX 与 PTR 记录在邮件系统中的作用

在电子邮件通信中,域名系统 (dns) 扮演着至关重要的角色。其中,邮件交换记录 (mx record) 和指针记录 (ptr record,即反向 dns 记录) 是确保邮件正常投递和防止垃圾邮件的关键。

  • MX 记录 (Mail Exchange Record):它指定了负责接收特定域名电子邮件的邮件服务器。当您向某个域名发送邮件时,发件服务器会查询该域名的 MX 记录,以确定将邮件发送到哪个邮件服务器。
  • PTR 记录 (Pointer Record):也称为反向 DNS (Reverse DNS, rDNS) 记录,它提供从 IP 地址到主机名的映射。与我们通常通过主机名查找 IP 地址的正向 DNS 查询相反,PTR 记录允许通过 IP 地址查找其对应的主机名。

为什么 PTR 记录对邮件服务器至关重要? 许多邮件服务器在接收传入邮件时,会执行反向 DNS 查找,以验证发件服务器的合法性。它们会检查发件 IP 地址的 PTR 记录是否与发件主机名匹配。如果发件服务器缺少 PTR 记录,或者 PTR 记录解析出的主机名与邮件头中的主机名不一致,接收方邮件服务器很可能会将该邮件标记为垃圾邮件,甚至直接拒绝,这可能导致发件 IP 地址被列入黑名单 (RBL)。因此,拥有正确配置的 PTR 记录是确保邮件送达率和维护邮件服务器声誉的关键。

PHP 中的 DNS 查询函数

PHP 提供了一系列内置函数来执行 DNS 查询:

  • getmxrr(string $hostname, array &$mxhosts, array &$weight = null): 用于获取指定域名的所有 MX 记录。它将 MX 主机名存储在 $mxhosts 数组中,可选地将对应的权重存储在 $weight 数组中。
  • gethostbyname(string $hostname): 用于获取指定主机名的 IP 地址。需要注意的是,此函数只返回主机名对应的第一个 IP 地址。
  • gethostbynamel(string $hostname): 用于获取指定主机名对应的所有 IP 地址。这是在需要获取完整 IP 列表时更推荐的函数。
  • dns_get_record(string $hostname, int $type = DNS_ANY, array &$authns = null, array &$addtl = null, bool $raw = false): 一个功能强大的通用 DNS 查询函数。通过指定 $type 参数,可以查询不同类型的 DNS 记录,例如 DNS_PTR 用于查询 PTR 记录。

逐步获取 MX 记录及其 PTR 记录

以下是使用 PHP 获取指定域名的 MX 记录并进一步查询其对应 PTR 记录的详细步骤和代码示例。

1. 获取域名的 MX 记录

首先,使用 getmxrr() 函数获取目标域名的所有 MX 记录。为了更好地处理邮件服务器的优先级,通常会将这些记录按权重进行排序。

<?php

$domain = "example.com"; // 替换为您要查询的域名

$mx_records = [];
$mx_weight = [];

// 获取域名的 MX 记录
if (getmxrr($domain, $mx_records, $mx_weight)) {
    echo "<h2>域名: {$domain} 的 MX 记录及其 PTR 记录:</h2>";

    // 将 MX 记录按权重排序
    $mxs_weighted = [];
    for ($i = 0; $i < count($mx_records); $i++) {
        $mxs_weighted[$mx_records[$i]] = $mx_weight[$i];
    }
    asort($mxs_weighted); // 按权重升序排序

    $sorted_mx_hosts = array_keys($mxs_weighted); // 获取排序后的 MX 主机名列表

    // ... 后续步骤将在此处继续
} else {
    echo "无法获取域名 {$domain} 的 MX 记录。<br>";
}

?>

2. 解析 MX 主机名对应的所有 IP 地址

对于每个获取到的 MX 主机名,我们需要获取其对应的所有 IP 地址。这里是关键点:必须使用 gethostbynamel(),而不是 gethostbyname(),因为一个主机名可能解析到多个 IP 地址。

立即学习PHP免费学习笔记(深入)”;

吐槽大师
吐槽大师

吐槽大师(Roast Master) - 终极 AI 吐槽生成器,适用于 Instagram,Facebook,Twitter,Threads 和 Linkedin

下载
<?php
// 承接上一步的代码...

foreach ($sorted_mx_hosts as $mx_host) {
    echo "<h3>MX 主机: {$mx_host}</h3>";

    // 获取 MX 主机名对应的所有 IP 地址
    $ip_addresses = gethostbynamel($mx_host);

    if ($ip_addresses) {
        // ... 后续步骤将在此处继续处理每个 IP 地址
    } else {
        echo "<p style='color: orange;'>  无法解析 MX 主机 {$mx_host} 的 IP 地址。</p>";
    }
}

// ...
?>

3. 构建 PTR 查询字符串

PTR 记录的查询方式比较特殊。您不能直接查询 IP 地址的 PTR 记录,而是需要将 IP 地址的八位字节反转,并追加 .IN-ADDR.ARPA 后缀。例如,IP 地址 192.0.2.1 对应的 PTR 查询字符串是 1.2.0.192.IN-ADDR.ARPA。

<?php
// 承接上一步的代码...

foreach ($ip_addresses as $ip_addr) {
    echo "<p>  IP 地址: {$ip_addr}</p>";

    // 构建反向 DNS 查询字符串
    $ip_parts = explode('.', $ip_addr);
    $reverse_ip_parts = array_reverse($ip_parts);
    $reverse_dns_query = implode('.', $reverse_ip_parts) . ".IN-ADDR.ARPA";

    // ... 后续步骤将在此处查询 PTR 记录
}

// ...
?>

4. 查询 PTR 记录并提取结果

最后,使用 dns_get_record() 函数并指定 DNS_PTR 类型来查询构建好的反向 DNS 字符串。该函数会返回一个包含 PTR 记录信息的数组,其中 target 字段即为反向解析得到的主机名。

<?php
// 承接上一步的代码...

    // 查询 PTR 记录
    $ptr_records = dns_get_record($reverse_dns_query, DNS_PTR);

    if ($ptr_records) {
        $ptr_targets = array_column($ptr_records, 'target'); // 提取所有 PTR 目标主机名
        echo "<p style='color: green;'>    PTR 记录: " . implode(', ', $ptr_targets) . "</p>";
    } else {
        echo "<p style='color: red;'>    未找到 PTR 记录或查询失败。</p>";
    }
}

// ...
?>

完整实现代码示例

将上述所有步骤整合,即可得到一个完整的 PHP 脚本来查询域名的 MX 记录及其对应的 PTR 记录。

<?php

$domain = "google.com"; // 替换为您要查询的域名,例如 "example.com"

$mx_records = [];
$mx_weight = [];

echo "<!DOCTYPE html>
<html lang='zh-CN'>
<head>
    <meta charset='UTF-8'>
    <title>MX 和 PTR 记录查询</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; margin: 20px; }
        h2, h3 { color: #333; }
        p { margin: 5px 0; }
        strong { color: #0056b3; }
        .success { color: green; font-weight: bold; }
        .error { color: red; font-weight: bold; }
        .warning { color: orange; }
        pre { background-color: #f4f4f4; padding: 10px; border: 1px solid #ddd; overflow-x: auto; }
    </style>
</head>
<body>";

echo "<h2>查询域名: <strong>{$domain}</strong> 的 MX 记录及其 PTR 记录</h2>";

// 1. 获取域名的 MX 记录
if (getmxrr($domain, $mx_records, $mx_weight)) {
    // 将 MX 记录按权重排序
    $mxs_weighted = [];
    for ($i = 0; $i < count($mx_records); $i++) {
        $mxs_weighted[$mx_records[$i]] = $mx_weight[$i];
    }
    asort($mxs_weighted); // 按权重升序排序

    $sorted_mx_hosts = array_keys($mxs_weighted); // 获取排序后的 MX 主机名列表

    if (empty($sorted_mx_hosts)) {
        echo "<p class='warning'>域名 {$domain} 未找到 MX 记录。</p>";
    } else {
        foreach ($sorted_mx_hosts as $mx_host) {
            echo "<h3>MX 主机: <strong>{$mx_host}</strong> (权重: {$mxs_weighted[$mx_host]})</h3>";

            // 2. 解析 MX 主机名对应的所有 IP 地址
            $ip_addresses = gethostbynamel($mx_host);

            if ($ip_addresses) {
                foreach ($ip_addresses as $ip_addr) {
                    echo "<p>  IP 地址: {$ip_addr}</p>";

                    // 3. 构建反向 DNS 查询字符串
                    $ip_parts = explode('.', $ip_addr);
                    // 检查 IP 地址是否为有效的 IPv4 格式
                    if (count($ip_parts) === 4 && filter_var($ip_addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        $reverse_ip_parts = array_reverse($ip_parts);
                        $reverse_dns_query = implode('.', $reverse_ip_parts) . ".IN-ADDR.ARPA";

                        // 4. 查询 PTR 记录
                        $ptr_records = dns_get_record($reverse_dns_query, DNS_PTR);

                        if ($ptr_records) {
                            $ptr_targets = array_column($ptr_records, 'target'); // 提取所有 PTR 目标主机名
                            echo "<p class='success'>    PTR 记录: " . htmlspecialchars(implode(', ', $ptr_targets)) . "</p>";
                        } else {
                            echo "<p class='error'>    未找到 PTR 记录或查询失败。</p>";
                        }
                    } else {
                        echo "<p class='warning'>    IP 地址 {$ip_addr} 格式无效或非 IPv4,跳过 PTR 查询。</p>";
                    }
                }
            } else {
                echo "<p class='warning'>  无法解析 MX 主机 {$mx_host} 的 IP 地址。</p>";
            }
        }
    }
} else {
    echo "<p class='error'>无法获取域名 {$domain} 的 MX 记录。</p>";
}

echo "</body></html>";

?>

注意事项

  1. gethostbynamel() 的重要性:切勿使用 gethostbyname(),因为它只能返回一个 IP 地址。如果 MX 主机名配置了多个 IP 地址(例如用于负载均衡或冗余),gethostbyname() 将会遗漏其他 IP,导致无法查询到所有相关的 PTR 记录。
  2. 反向 DNS 格式:PTR 记录的查询需要将 IPv4 地址的四段反转,并加上 .IN-ADDR.ARPA 后缀。对于 IPv6 地址,反向解析区域是 .IP6.ARPA,其格式更为复杂,本教程主要关注 IPv4。
  3. 错误处理:DNS 查询可能会因网络问题、域名不存在或记录缺失而失败。在实际应用中,应加入更健壮的错误检查和异常处理机制。例如,检查 getmxrr() 和 gethostbynamel() 的返回值是否为 false 或空数组。
  4. 性能考虑:对大量域名或具有大量 MX 记录的域名进行批量查询时,可能会消耗较多的时间和系统资源。在生产环境中,可以考虑引入缓存机制或异步处理。
  5. DNS 缓存:PHP 的 DNS 查询函数通常会利用操作系统或 PHP 自身的 DNS 缓存。这意味着重复查询相同记录可能不会每次都发起新的网络请求。
  6. 结果解读:即使找到了 PTR 记录,也需要检查其 target 值是否与预期的主机名匹配,以确保邮件服务器的配置是正确的。

总结

通过本文的指导,您应该已经掌握了使用 PHP 获取域名 MX 记录及其对应 PTR 记录的方法。理解并正确实现这一过程对于管理邮件服务器、确保邮件送达率以及维护良好的发件人声誉至关重要。遵循这些步骤和注意事项,将有助于您构建更可靠的邮件服务监控或诊断工具

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1031

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号