Laravel 的邮件 SPF 检查器(避免的邮件进入垃圾邮箱)

Laravel

Laravel 「Mail SPF Checker」 是一个包,用来检查你是否可以通过给定的邮件服务器,并以给定的邮件地址名义来发送一份电子邮件:

当以一个域名的名义发送电子邮件但不使用该域的合法邮件服务器时,它可能会变得棘手......大多数情况下,你的邮件最终会进入垃圾邮件文件夹下。而这个包 「Mail SPF Checker」 可以通过为你要发送的域配置正确的 SPF 记录来解决此问题。

此包提供了一个检查器,你可以在你的程序中使用该检查器来确保你拥有一个正确的 SPF 记录:

$mailSpfChecker->canISendAs("hello@dietse.dev"); // bool

// 如果你不能正确地发送邮件,则会输出需要的 SPF 记录:

if (! $mailSpfChecker->canISendAs("hello@dietse.dev")) {
    // 生成一个名为 「diets.dev」 的 txt 记录
    // 记录格式为  v=spf1 ip4:#.#.#.# -all
    echo $mailSpfChecker->howCanISendAs("hello@dietse.be");
}

Laravel

Laravel 「Mail SPF Checker」 是一个包,用来检查你是否可以通过给定的邮件服务器,并以给定的邮件地址名称来发送一封电子邮件:

当以一个域名的名称发送电子邮件但不使用该域的合法邮件服务器时,它可能会变得棘手...大多数情况下,你的邮件最终会进入垃圾邮件文件夹下。而这个包 「Mail SPF Checker」 可以通过为你要发送的域配置正确的 SPF 记录来解决此问题。

此包提供了一个检查器,你可以在你的程序中使用该检查器来确保你拥有一个正确的 SPF 记录:

$mailSpfChecker->canISendAs("hello@dietse.dev"); // bool

// 如果你不能正确地发送邮件,则会输出需要的 SPF 记录:

if (! $mailSpfChecker->canISendAs("hello@dietse.dev")) {
    // 生成一个名为 「diets.dev」 的 txt 记录
    // 记录格式为  v=spf1 ip4:#.#.#.# -all
    echo $mailSpfChecker->howCanISendAs("hello@dietse.be");
}

你还可以使用给定的邮件server:

$mailSpfChecker
    ->using('SMTP.mandrill.com')
    ->canISendAs("hello@dietse.dev");

你可以通过查看 giHub 上的 Mail SFP Checker 开始使用此程序包。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://laravel-news.com/mailspfchecker

译文地址:https://learnku.com/laravel/t/71383

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 2
// 根据位数推测子网掩码
function byPrefixLengthCalcSubnetMask(string $ip): array|bool
    {
        $length = 32;
        if (mb_strpos($ip, "/")) {
            $ip_arr = explode("/", $ip);
            if (count($ip_arr) > 1) {
                if (is_numeric($ip_arr[1])) {
                    $length = $ip_arr[1];
                    $ip = $ip_arr[0];
                }
            }
        }
        $ip_arr = explode(".", $ip);
        foreach ($ip_arr as $ip_value) {
            if (!is_numeric($ip_value)) {
                return false;
            }
            if ((int)$ip_value > 255) {
                return false;
            }
        }
        // 求一个最大位数减去当前位数的差的结果(N) 然后以这个结果的值的1的N - 1次方 左移
        $mask = -1 << (32 - $length);
        // 子网掩码四位
        $partNum = 4;
        $bitsOfPart = 8;
        $maskPart = [];
        // 最大值 255
        $selector = 0x000000ff;
        for ($i = 0; $i < $partNum; $i++) {
            // 当前子网掩码下标 从后往前
            $pos = 4 - 1 - $i;
            // 公式 右移
            $maskPart[$pos] = ($mask >> ($i * $bitsOfPart)) & $selector;
        }

        $ip_range = [];
        for ($i = 0; $i < count($maskPart); $i++) {
            // 将子网掩码和求值ip进行二进制转换
            $subnetMask = decbin($maskPart[$i]);
            $ip_s = decbin($ip_arr[$i]);
            // 位运算得到起始地址
            $ip_range[] = bindec($subnetMask & $ip_s);
        }
        $range_end = [];
        // 根据子网掩码进行查询
        $ip_end = 255 - $maskPart[count($maskPart) - 1];
        for ($i = 0; $i < count($ip_range); $i++) {
            if ($i === count($ip_range) - 1) {
                // 得出最后的广播地址
                $range_end[] = $ip_range[$i] + $ip_end;
                continue;
            }
            if (empty($ip_range[$i])) {
                if (empty($maskPart[$i])) {
                    $range_end[] = 255;
                    continue;
                }
                if ($ip_range[$i] === 0) {
                    $range_end[] = 0;
                    continue;
                }
                $range_end[] = $maskPart[$i];
                continue;
            }
            $range_end[] = $ip_range[$i];
        }
        return [
            $ip_range,
            $range_end
        ];
    }
    // 检测是否在ip范围内
    function validateRangeIP($client_ip, $start_ip, $end_ip): bool
    {
        $client_ip_arr = explode(".", $client_ip);
        $start_ip_str = implode(".", $start_ip);
        $end_ip_str = implode(".", $end_ip);

        if ($start_ip_str === $end_ip_str && $client_ip === $start_ip_str) {
            return true;
        }

        for ($i = 0; $i < 2; $i++) {
            if ($client_ip_arr[$i] != $start_ip[$i]) {
                return false;
            }
        }
        if ($start_ip[2] != $end_ip[2]) {
            if (!($client_ip_arr[2] > $start_ip[2] && $client_ip_arr[2] < $end_ip[2])) {
                return false;
            }
        }
        if (!($client_ip_arr[3] > $start_ip[3] && $client_ip_arr[3] < $end_ip[3])) {
            return false;
        }
        return true;
    }
1年前 评论

我自己实现过一个spf检测的

// 读取spf记录
function getSpfDNS($host, $type): array
    {
        $dns = dns_get_record($host, DNS_TXT);
        $start_spf = [];
        foreach ($dns as $k => $v) {
            if (!isset($v['host'])) {
                continue;
            }
            if ($v['host'] !== $host) {
                continue;
            }
            if (!isset($v['txt']) || !isset($v['ttl'])) {
                continue;
            }
            $ttl = $v['ttl'];

            $v_arr = explode(" ", $v['txt']);
            $v_arr = array_values(array_filter($v_arr));
            if (count($v_arr) < 3) {
                continue;
            }
            $spf_type = $v_arr[0];
            $spf_type_arr = explode("=", $spf_type);
            if (count($spf_type_arr) < 2) {
                continue;
            }
            $spf_type = $spf_type_arr[1];
            if ($spf_type !== "spf1") {
                continue;
            }
            $start_spf['type'] = $spf_type;
            unset($v_arr[0]);
            $v_arr = array_values($v_arr);
//            $role = $v_arr[count($v_arr) - 1];
            unset($v_arr[count($v_arr) - 1]);
            $v_arr = array_values($v_arr);
            foreach ($v_arr as $handle) {
                $spf_value_arr = explode(":", $handle);
                if ($spf_value_arr[0] === "include") {
                    $start_spfs = getSpfDNS($spf_value_arr[1], $type);
                    foreach ($start_spfs as $spfs_k => $spfs) {
                        if (empty($start_spf[$spfs_k])) {
                            $start_spf[$spfs_k] = null;
                        }
                        if (is_array($spfs)) {
                            if (empty($start_spf[$spfs_k])) {
                                $start_spf[$spfs_k] = [];
                            }
                            foreach ($spfs as $spf_children) {
                                $start_spf[$spfs_k][] = $spf_children;
                            }
                        } elseif ($spfs_k != "type") {
                            $start_spf[$spfs_k] = $spfs;
                        }
                    }
                } else {
                    if ($spf_value_arr[0] === $type) {
                        if (empty($start_spf[$spf_value_arr[0]])) {
                            $start_spf[$spf_value_arr[0]] = [];
                        }
                        if (empty($start_spf["ttl"])) {
                            $start_spf["ttl"] = [];
                        }
                        if ($spf_value_arr[0] === "ip6") {
                            $ip6_data = $spf_value_arr;
                            unset($ip6_data[0]);
                            $ip6_data = array_values($ip6_data);
                            $spf_value_arr[1] = implode(":", $ip6_data);
                        }
                        $start_spf[$spf_value_arr[0]][] = $spf_value_arr[1];
                        $start_spf["ttl"][] = $ttl;
                    }
                }
            }
            return $start_spf;
        }
        return [];
1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!