[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @task restrictions Domain Restrictions 5 * @task email Email About Email 6 */ 7 final class PhabricatorUserEmail extends PhabricatorUserDAO { 8 9 protected $userPHID; 10 protected $address; 11 protected $isVerified; 12 protected $isPrimary; 13 protected $verificationCode; 14 15 const MAX_ADDRESS_LENGTH = 128; 16 17 public function getConfiguration() { 18 return array( 19 self::CONFIG_COLUMN_SCHEMA => array( 20 'address' => 'sort128', 21 'isVerified' => 'bool', 22 'isPrimary' => 'bool', 23 'verificationCode' => 'text64?', 24 ), 25 self::CONFIG_KEY_SCHEMA => array( 26 'address' => array( 27 'columns' => array('address'), 28 'unique' => true, 29 ), 30 'userPHID' => array( 31 'columns' => array('userPHID', 'isPrimary'), 32 ), 33 ), 34 ) + parent::getConfiguration(); 35 } 36 37 public function getVerificationURI() { 38 return '/emailverify/'.$this->getVerificationCode().'/'; 39 } 40 41 public function save() { 42 if (!$this->verificationCode) { 43 $this->setVerificationCode(Filesystem::readRandomCharacters(24)); 44 } 45 return parent::save(); 46 } 47 48 49 /* -( Domain Restrictions )------------------------------------------------ */ 50 51 52 /** 53 * @task restrictions 54 */ 55 public static function isValidAddress($address) { 56 if (strlen($address) > self::MAX_ADDRESS_LENGTH) { 57 return false; 58 } 59 60 // Very roughly validate that this address isn't so mangled that a 61 // reasonable piece of code might completely misparse it. In particular, 62 // the major risks are: 63 // 64 // - `PhutilEmailAddress` needs to be able to extract the domain portion 65 // from it. 66 // - Reasonable mail adapters should be hard-pressed to interpret one 67 // address as several addresses. 68 // 69 // To this end, we're roughly verifying that there's some normal text, an 70 // "@" symbol, and then some more normal text. 71 72 $email_regex = '(^[a-z0-9_+.!-]+@[a-z0-9_+:.-]+\z)i'; 73 if (!preg_match($email_regex, $address)) { 74 return false; 75 } 76 77 return true; 78 } 79 80 81 /** 82 * @task restrictions 83 */ 84 public static function describeValidAddresses() { 85 return pht( 86 "Email addresses should be in the form '[email protected]'. The maximum ". 87 "length of an email address is %d character(s).", 88 new PhutilNumber(self::MAX_ADDRESS_LENGTH)); 89 } 90 91 92 /** 93 * @task restrictions 94 */ 95 public static function isAllowedAddress($address) { 96 if (!self::isValidAddress($address)) { 97 return false; 98 } 99 100 $allowed_domains = PhabricatorEnv::getEnvConfig('auth.email-domains'); 101 if (!$allowed_domains) { 102 return true; 103 } 104 105 $addr_obj = new PhutilEmailAddress($address); 106 107 $domain = $addr_obj->getDomainName(); 108 if (!$domain) { 109 return false; 110 } 111 112 $lower_domain = phutil_utf8_strtolower($domain); 113 foreach ($allowed_domains as $allowed_domain) { 114 $lower_allowed = phutil_utf8_strtolower($allowed_domain); 115 if ($lower_allowed === $lower_domain) { 116 return true; 117 } 118 } 119 120 return false; 121 } 122 123 124 /** 125 * @task restrictions 126 */ 127 public static function describeAllowedAddresses() { 128 $domains = PhabricatorEnv::getEnvConfig('auth.email-domains'); 129 if (!$domains) { 130 return null; 131 } 132 133 if (count($domains) == 1) { 134 return 'Email address must be @'.head($domains); 135 } else { 136 return 'Email address must be at one of: '. 137 implode(', ', $domains); 138 } 139 } 140 141 142 /** 143 * Check if this install requires email verification. 144 * 145 * @return bool True if email addresses must be verified. 146 * 147 * @task restrictions 148 */ 149 public static function isEmailVerificationRequired() { 150 // NOTE: Configuring required email domains implies required verification. 151 return PhabricatorEnv::getEnvConfig('auth.require-email-verification') || 152 PhabricatorEnv::getEnvConfig('auth.email-domains'); 153 } 154 155 156 /* -( Email About Email )-------------------------------------------------- */ 157 158 159 /** 160 * Send a verification email from $user to this address. 161 * 162 * @param PhabricatorUser The user sending the verification. 163 * @return this 164 * @task email 165 */ 166 public function sendVerificationEmail(PhabricatorUser $user) { 167 $username = $user->getUsername(); 168 169 $address = $this->getAddress(); 170 $link = PhabricatorEnv::getProductionURI($this->getVerificationURI()); 171 172 173 $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); 174 175 $signature = null; 176 if (!$is_serious) { 177 $signature = <<<EOSIGNATURE 178 Get Well Soon, 179 Phabricator 180 EOSIGNATURE; 181 } 182 183 $body = <<<EOBODY 184 Hi {$username}, 185 186 Please verify that you own this email address ({$address}) by clicking this 187 link: 188 189 {$link} 190 191 {$signature} 192 EOBODY; 193 194 id(new PhabricatorMetaMTAMail()) 195 ->addRawTos(array($address)) 196 ->setForceDelivery(true) 197 ->setSubject('[Phabricator] Email Verification') 198 ->setBody($body) 199 ->setRelatedPHID($user->getPHID()) 200 ->saveAndSend(); 201 202 return $this; 203 } 204 205 206 /** 207 * Send a notification email from $user to this address, informing the 208 * recipient that this is no longer their account's primary address. 209 * 210 * @param PhabricatorUser The user sending the notification. 211 * @param PhabricatorUserEmail New primary email address. 212 * @return this 213 * @task email 214 */ 215 public function sendOldPrimaryEmail( 216 PhabricatorUser $user, 217 PhabricatorUserEmail $new) { 218 $username = $user->getUsername(); 219 220 $old_address = $this->getAddress(); 221 $new_address = $new->getAddress(); 222 223 $body = <<<EOBODY 224 Hi {$username}, 225 226 This email address ({$old_address}) is no longer your primary email address. 227 Going forward, Phabricator will send all email to your new primary email 228 address ({$new_address}). 229 230 EOBODY; 231 232 id(new PhabricatorMetaMTAMail()) 233 ->addRawTos(array($old_address)) 234 ->setForceDelivery(true) 235 ->setSubject('[Phabricator] Primary Address Changed') 236 ->setBody($body) 237 ->setFrom($user->getPHID()) 238 ->setRelatedPHID($user->getPHID()) 239 ->saveAndSend(); 240 } 241 242 243 /** 244 * Send a notification email from $user to this address, informing the 245 * recipient that this is now their account's new primary email address. 246 * 247 * @param PhabricatorUser The user sending the verification. 248 * @return this 249 * @task email 250 */ 251 public function sendNewPrimaryEmail(PhabricatorUser $user) { 252 $username = $user->getUsername(); 253 254 $new_address = $this->getAddress(); 255 256 $body = <<<EOBODY 257 Hi {$username}, 258 259 This is now your primary email address ({$new_address}). Going forward, 260 Phabricator will send all email here. 261 262 EOBODY; 263 264 id(new PhabricatorMetaMTAMail()) 265 ->addRawTos(array($new_address)) 266 ->setForceDelivery(true) 267 ->setSubject('[Phabricator] Primary Address Changed') 268 ->setBody($body) 269 ->setFrom($user->getPHID()) 270 ->setRelatedPHID($user->getPHID()) 271 ->saveAndSend(); 272 273 return $this; 274 } 275 276 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |