EmailValidator.php 4.22 KB
Newer Older
w  
Qiang Xue committed
1 2
<?php
/**
w  
Qiang Xue committed
3
 * EmailValidator class file.
w  
Qiang Xue committed
4 5
 *
 * @link http://www.yiiframework.com/
w  
Qiang Xue committed
6
 * @copyright Copyright &copy; 2008-2012 Yii Software LLC
w  
Qiang Xue committed
7 8 9
 * @license http://www.yiiframework.com/license/
 */

w  
Qiang Xue committed
10 11
namespace yii\validators;

w  
Qiang Xue committed
12
/**
w  
Qiang Xue committed
13
 * EmailValidator validates that the attribute value is a valid email address.
w  
Qiang Xue committed
14 15
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
w  
Qiang Xue committed
16
 * @since 2.0
w  
Qiang Xue committed
17
 */
w  
Qiang Xue committed
18
class EmailValidator extends Validator
w  
Qiang Xue committed
19 20 21 22 23 24 25 26
{
	/**
	 * @var string the regular expression used to validate the attribute value.
	 * @see http://www.regular-expressions.info/email.html
	 */
	public $pattern = '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/';
	/**
	 * @var string the regular expression used to validate email addresses with the name part.
w  
Qiang Xue committed
27
	 * This property is used only when [[allowName]] is true.
w  
Qiang Xue committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
	 * @see allowName
	 */
	public $fullPattern = '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/';
	/**
	 * @var boolean whether to allow name in the email address (e.g. "Qiang Xue <qiang.xue@gmail.com>"). Defaults to false.
	 * @see fullPattern
	 */
	public $allowName = false;
	/**
	 * @var boolean whether to check the MX record for the email address.
	 * Defaults to false. To enable it, you need to make sure the PHP function 'checkdnsrr'
	 * exists in your PHP installation.
	 */
	public $checkMX = false;
	/**
	 * @var boolean whether to check port 25 for the email address.
	 * Defaults to false.
	 */
	public $checkPort = false;
	/**
	 * @var boolean whether the attribute value can be null or empty. Defaults to true,
	 * meaning that if the attribute is empty, it is considered valid.
	 */
	public $allowEmpty = true;

	/**
	 * Validates the attribute of the object.
	 * If there is any error, the error message is added to the object.
w  
Qiang Xue committed
56
	 * @param \yii\base\Model $object the object being validated
w  
Qiang Xue committed
57 58
	 * @param string $attribute the attribute being validated
	 */
w  
Qiang Xue committed
59
	public function validateAttribute($object, $attribute)
w  
Qiang Xue committed
60 61
	{
		$value = $object->$attribute;
w  
Qiang Xue committed
62
		if ($this->allowEmpty && $this->isEmpty($value)) {
w  
Qiang Xue committed
63
			return;
w  
Qiang Xue committed
64 65
		}
		if (!$this->validateValue($value)) {
Alexander Makarov committed
66
			$message = ($this->message !== null) ? $this->message : \Yii::t('yii', '{attribute} is not a valid email address.');
w  
Qiang Xue committed
67 68 69 70 71 72
			$this->addError($object, $attribute, $message);
		}
	}

	/**
	 * Validates a static value to see if it is a valid email.
w  
Qiang Xue committed
73
	 * Note that this method does not respect [[allowEmpty]] property.
w  
Qiang Xue committed
74 75 76 77 78 79 80 81
	 * This method is provided so that you can call it directly without going through the model validation rule mechanism.
	 * @param mixed $value the value to be validated
	 * @return boolean whether the value is a valid email
	 */
	public function validateValue($value)
	{
		// make sure string length is limited to avoid DOS attacks
		$valid = is_string($value) && strlen($value) <= 254 && (preg_match($this->pattern, $value) || $this->allowName && preg_match($this->fullPattern, $value));
w  
Qiang Xue committed
82
		if ($valid) {
w  
Qiang Xue committed
83
			$domain = rtrim(substr($value, strpos($value, '@') + 1), '>');
w  
Qiang Xue committed
84 85
		}
		if ($valid && $this->checkMX && function_exists('checkdnsrr')) {
w  
Qiang Xue committed
86
			$valid = checkdnsrr($domain, 'MX');
w  
Qiang Xue committed
87 88
		}
		if ($valid && $this->checkPort && function_exists('fsockopen')) {
w  
Qiang Xue committed
89
			$valid = fsockopen($domain, 25) !== false;
w  
Qiang Xue committed
90
		}
w  
Qiang Xue committed
91 92 93 94 95
		return $valid;
	}

	/**
	 * Returns the JavaScript needed for performing client-side validation.
w  
Qiang Xue committed
96
	 * @param \yii\base\Model $object the data object being validated
w  
Qiang Xue committed
97 98 99 100 101
	 * @param string $attribute the name of the attribute to be validated.
	 * @return string the client-side validation script.
	 */
	public function clientValidateAttribute($object, $attribute)
	{
Alexander Makarov committed
102
		$message = ($this->message !== null) ? $this->message : \Yii::t('yii', '{attribute} is not a valid email address.');
w  
Qiang Xue committed
103 104
		$message = strtr($message, array(
			'{attribute}' => $object->getAttributeLabel($attribute),
w  
Qiang Xue committed
105
			'{value}' => $object->$attribute,
w  
Qiang Xue committed
106 107 108
		));

		$condition = "!value.match( {$this->pattern})";
w  
Qiang Xue committed
109
		if ($this->allowName) {
w  
Qiang Xue committed
110
			$condition .= " && !value.match( {$this->fullPattern})";
w  
Qiang Xue committed
111
		}
w  
Qiang Xue committed
112 113 114

		return "
if(" . ($this->allowEmpty ? "$.trim(value)!='' && " : '') . $condition . ") {
w  
Qiang Xue committed
115
	messages.push(" . json_encode($message) . ");
w  
Qiang Xue committed
116 117 118 119
}
";
	}
}