【问题标题】:Zend Validate Email Address and Deep MX CheckingZend 验证电子邮件地址和深度 MX 检查
【发布时间】:2012-04-07 03:24:58
【问题描述】:

我已经开始使用Zend_Validate_EmailAddress 并将mxdeep 选项设置为true。我认为当涉及到 IP 地址在保留 IP 范围内的 MX 记录时,我得到了一些误报。

一个很好的例子是MX records for harn.ufl.edu。由于 128.0.0.0/16 范围内的 IP 地址,它似乎失败了。但是,它确实有一个使用 8.6.245.30 的记录,它不在保留范围内。

另一个例子是MX record for martinhealth.org。它的 MX 记录域使用 198.136.38.2。

这是一个技术上不正确但实际上有效的情况吗?

【问题讨论】:

  • 你在 Windows 上使用它吗? 在 Windows 环境中,MX 检查仅在使用 PHP 5.3 或更高版本时可用。 PHP 5.3 以下的 MX 检查即使在选项中激活也不会使用。
  • 您在Zend_Validate_EmailAddress 中似乎遇到了错误。 128. 范围内的唯一保留 IP 地址来自 128.0.0.0 - 128.0.255.255。 harn 的邮件服务器不在此范围内,但 Zend_Validate_Email 似乎错误地计算了子网掩码导致误报的内容。我会看看能不能找到更多。
  • 如果你很快就到了,我设置了这个chat来讨论这个问题,我相信我看到了ZF的问题所在。
  • @drew010 - 我也发现了问题,并重写了验证器的部分。我将发布我的解决方案,并欢迎对我所采取的方法提出任何批评。

标签: php email zend-framework dns mx-record


【解决方案1】:

正如我帖子中的 cmets 所暗示的,Zend_Validate_EmailAddress::_isReserved 中有一个错误。它不仅有问题,而且很难理解逻辑流程。这是一个private 函数,所以我将其更改为protected,这样我就可以在我的子类中覆盖它。 $_invalidIp 数组中还有一些不正确的范围。

对于我的逻辑检查,我决定比较 IP 地址的最简单(最清晰?)的方法是将它们转换为它们的十进制整数等值。

这是我的子类:

class My_Validate_EmailAddressDeep extends Zend_Validate_EmailAddress
{
    /**
     * @var array
     */
    protected $_messageTemplates = array(
        self::INVALID            => "Invalid type given. String expected",
        self::INVALID_FORMAT     => "'%value%' is not a valid email address in the basic [user]@[hostname] format",
        self::INVALID_HOSTNAME   => "The '%hostname%' part of '%value%' is not a valid hostname",
        self::INVALID_MX_RECORD  => "'%hostname%' does not appear to be configured to accept email",
        self::INVALID_SEGMENT    => "'%hostname%' does not appear to be configured to accept external email",
        self::DOT_ATOM           => null,
        self::QUOTED_STRING      => null,
        self::INVALID_LOCAL_PART => "The '%localPart%' part of '%value%' is not valid",
        self::LENGTH_EXCEEDED    => "'%value%' is longer than the allowed length for an email address",
    );

    /**
     * Internal options array
     * @var array
     */
    protected $_options = array(
        'allow' => Zend_Validate_Hostname::ALLOW_DNS,
        'deep' => true,
        'domain' => true,
        'hostname' => null,
        'mx' => true,
    );

    /**
     * @see http://en.wikipedia.org/wiki/Reserved_IP_addresses#Reserved_IPv4_addresses
     * @var array [first octet] => [[CIDR] => [[range start], [range end]]]
     */
    protected $_reservedIps = array(
        '0' => array('0.0.0.0/8' => array('0.0.0.0', '0.255.255.255',),),
        '10' => array('10.0.0.0/8' => array('10.0.0.0', '10.255.255.255',),),
        '127' => array('127.0.0.0/8' => array('127.0.0.0', '127.255.255.255',),),
        '169' => array('169.254.0.0/16' => array('169.254.0.0', '169.254.255.255',),),
        '172' => array('172.16.0.0/12' => array('172.16.0.0', '172.31.255.255',),),
        '192' => array(
            '192.0.2.0/24' => array('192.0.2.0', '192.0.2.255',),
            '192.88.99.0/24' => array('192.88.99.0', '192.88.99.255',),
            '192.168.0.0/16' => array('192.168.0.0', '192.168.255.255',),
        ),
        '198' => array(
            '198.18.0.0/15' => array('198.18.0.0', '198.19.255.255',),
            '198.51.100.0/24' => array('198.51.100.0', '198.51.100.255',),
        ),
        '203' => array('203.0.113.0/24' => array('203.0.113.0', '203.0.113.255',),),
        '224' => array('224.0.0.0/4' => array('224.0.0.0', '239.255.255.255',),),
        '240' => array('240.0.0.0/4' => array('240.0.0.0', '255.255.255.255',),),
    );

    /**
     * Returns if the given host is reserved
     *
     * @param string $host
     * @return boolean
     */
    protected function _isReserved($host)
    {
        if (!preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) {
            $host = gethostbyname($host);
        }

        $octets = explode('.', $host);
        if (224 <= (int) $octets[0]) {
            // IP Addresses beginning with 224 or greater are all reserved, short-circuit range checks
            return true;
        } elseif (array_key_exists($octets[0], $this->_reservedIps)) {
            // for integer comparisons
            $intIp = $this->_ipToInt($host);

            // loop over reserved IP addresses
            foreach ($this->_reservedIps as $ranges) {
                foreach ($ranges as $range) {
                    if (($this->_ipToInt($range[0]) <= $intIp)
                            && ($this->_ipToInt($range[1]) >= $intIp)) {
                        // the IP address falls in a reserved range
                        return true;
                    }
                }
            }

            // the IP address did not fall in a reserved range
            return false;
        } else {
            return false;
        }
    }

    /**
     * Convert a dot-decimal IP address to it's decimal integer equivalent
     *
     * @param string $ip
     * @return integer
     */
    protected function _ipToInt($ip)
    {
        $octets = explode('.', $ip);
        foreach ($octets as $key => $octet) {
            $octets[$key] = str_pad(decbin($octet), 8, '0', STR_PAD_LEFT);
        }
        $bin = implode('', $octets);
        return bindec($bin);
    }
}

【讨论】:

猜你喜欢
  • 2010-12-12
  • 2016-06-26
  • 2012-04-08
  • 2014-06-12
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
相关资源
最近更新 更多