[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/people/storage/ -> PhabricatorUserEmail.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1