3 final class PhabricatorEmailAddressesSettingsPanel
4 extends PhabricatorSettingsPanel
{
6 public function getPanelKey() {
10 public function getPanelName() {
11 return pht('Email Addresses');
14 public function getPanelMenuIcon() {
18 public function getPanelGroupKey() {
19 return PhabricatorSettingsEmailPanelGroup
::PANELGROUPKEY
;
22 public function isEditableByAdministrators() {
23 if ($this->getUser()->getIsMailingList()) {
30 public function processRequest(AphrontRequest
$request) {
31 $user = $this->getUser();
32 $editable = PhabricatorEnv
::getEnvConfig('account.editable');
34 $uri = new PhutilURI($request->getPath());
37 $new = $request->getStr('new');
39 return $this->returnNewAddressResponse($request, $uri, $new);
42 $delete = $request->getInt('delete');
44 return $this->returnDeleteAddressResponse($request, $uri, $delete);
48 $verify = $request->getInt('verify');
50 return $this->returnVerifyAddressResponse($request, $uri, $verify);
53 $primary = $request->getInt('primary');
55 return $this->returnPrimaryAddressResponse($request, $uri, $primary);
58 $emails = id(new PhabricatorUserEmail())->loadAllWhere(
59 'userPHID = %s ORDER BY address',
64 foreach ($emails as $email) {
66 $button_verify = javelin_tag(
69 'class' => 'button small button-grey',
70 'href' => $uri->alter('verify', $email->getID()),
71 'sigil' => 'workflow',
75 $button_make_primary = javelin_tag(
78 'class' => 'button small button-grey',
79 'href' => $uri->alter('primary', $email->getID()),
80 'sigil' => 'workflow',
84 $button_remove = javelin_tag(
87 'class' => 'button small button-grey',
88 'href' => $uri->alter('delete', $email->getID()),
89 'sigil' => 'workflow',
93 $button_primary = phutil_tag(
96 'class' => 'button small disabled',
100 if (!$email->getIsVerified()) {
101 $action = $button_verify;
102 } else if ($email->getIsPrimary()) {
103 $action = $button_primary;
105 $action = $button_make_primary;
108 if ($email->getIsPrimary()) {
109 $remove = $button_primary;
110 $rowc[] = 'highlighted';
112 $remove = $button_remove;
117 $email->getAddress(),
123 $table = new AphrontTableView($rows);
130 $table->setColumnClasses(
136 $table->setRowClasses($rowc);
137 $table->setColumnVisibility(
146 $buttons[] = id(new PHUIButtonView())
149 ->setText(pht('Add New Address'))
150 ->setHref($uri->alter('new', 'true'))
151 ->addSigil('workflow')
152 ->setColor(PHUIButtonView
::GREY
);
155 return $this->newBox(pht('Email Addresses'), $table, $buttons);
158 private function returnNewAddressResponse(
159 AphrontRequest
$request,
163 $user = $this->getUser();
164 $viewer = $this->getViewer();
166 $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
169 $this->getPanelURI());
174 if ($request->isDialogFormPost()) {
175 $email = trim($request->getStr('email'));
177 if ($new == 'verify') {
178 // The user clicked "Done" from the "an email has been sent" dialog.
179 return id(new AphrontReloadResponse())->setURI($uri);
182 PhabricatorSystemActionEngine
::willTakeAction(
183 array($viewer->getPHID()),
184 new PhabricatorSettingsAddEmailAction(),
187 if (!strlen($email)) {
188 $e_email = pht('Required');
189 $errors[] = pht('Email is required.');
190 } else if (!PhabricatorUserEmail
::isValidAddress($email)) {
191 $e_email = pht('Invalid');
192 $errors[] = PhabricatorUserEmail
::describeValidAddresses();
193 } else if (!PhabricatorUserEmail
::isAllowedAddress($email)) {
194 $e_email = pht('Disallowed');
195 $errors[] = PhabricatorUserEmail
::describeAllowedAddresses();
197 if ($e_email === true) {
198 $application_email = id(new PhabricatorMetaMTAApplicationEmailQuery())
199 ->setViewer(PhabricatorUser
::getOmnipotentUser())
200 ->withAddresses(array($email))
202 if ($application_email) {
203 $e_email = pht('In Use');
204 $errors[] = $application_email->getInUseMessage();
209 $object = id(new PhabricatorUserEmail())
213 // If an administrator is editing a mailing list, automatically verify
215 if ($viewer->getPHID() != $user->getPHID()) {
216 if ($viewer->getIsAdmin()) {
217 $object->setIsVerified(1);
222 id(new PhabricatorUserEditor())
224 ->addEmail($user, $object);
226 if ($object->getIsVerified()) {
227 // If we autoverified the address, just reload the page.
228 return id(new AphrontReloadResponse())->setURI($uri);
231 $object->sendVerificationEmail($user);
233 $dialog = $this->newDialog()
234 ->addHiddenInput('new', 'verify')
235 ->setTitle(pht('Verification Email Sent'))
236 ->appendChild(phutil_tag('p', array(), pht(
237 'A verification email has been sent. Click the link in the '.
238 'email to verify your address.')))
240 ->addSubmitButton(pht('Done'));
242 return id(new AphrontDialogResponse())->setDialog($dialog);
243 } catch (AphrontDuplicateKeyQueryException
$ex) {
244 $e_email = pht('Duplicate');
245 $errors[] = pht('Another user already has this email.');
251 $errors = id(new PHUIInfoView())
252 ->setErrors($errors);
255 $form = id(new PHUIFormLayoutView())
257 id(new AphrontFormTextControl())
258 ->setLabel(pht('Email'))
261 ->setCaption(PhabricatorUserEmail
::describeAllowedAddresses())
262 ->setError($e_email));
264 $dialog = $this->newDialog()
265 ->addHiddenInput('new', 'true')
266 ->setTitle(pht('New Address'))
267 ->appendChild($errors)
269 ->addSubmitButton(pht('Save'))
270 ->addCancelButton($uri);
272 return id(new AphrontDialogResponse())->setDialog($dialog);
275 private function returnDeleteAddressResponse(
276 AphrontRequest
$request,
279 $user = $this->getUser();
280 $viewer = $this->getViewer();
282 $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
285 $this->getPanelURI());
287 // NOTE: You can only delete your own email addresses, and you can not
288 // delete your primary address.
289 $email = id(new PhabricatorUserEmail())->loadOneWhere(
290 'id = %d AND userPHID = %s AND isPrimary = 0',
295 return new Aphront404Response();
298 if ($request->isFormPost()) {
299 id(new PhabricatorUserEditor())
301 ->removeEmail($user, $email);
303 return id(new AphrontRedirectResponse())->setURI($uri);
306 $address = $email->getAddress();
308 $dialog = id(new AphrontDialogView())
310 ->addHiddenInput('delete', $email_id)
311 ->setTitle(pht("Really delete address '%s'?", $address))
314 'Are you sure you want to delete this address? You will no '.
315 'longer be able to use it to login.'))
318 'Note: Removing an email address from your account will invalidate '.
319 'any outstanding password reset links.'))
320 ->addSubmitButton(pht('Delete'))
321 ->addCancelButton($uri);
323 return id(new AphrontDialogResponse())->setDialog($dialog);
326 private function returnVerifyAddressResponse(
327 AphrontRequest
$request,
330 $user = $this->getUser();
331 $viewer = $this->getViewer();
333 // NOTE: You can only send more email for your unverified addresses.
334 $email = id(new PhabricatorUserEmail())->loadOneWhere(
335 'id = %d AND userPHID = %s AND isVerified = 0',
340 return new Aphront404Response();
343 if ($request->isFormPost()) {
344 $email->sendVerificationEmail($user);
345 return id(new AphrontRedirectResponse())->setURI($uri);
348 $address = $email->getAddress();
350 $dialog = id(new AphrontDialogView())
352 ->addHiddenInput('verify', $email_id)
353 ->setTitle(pht('Send Another Verification Email?'))
354 ->appendChild(phutil_tag('p', array(), pht(
355 'Send another copy of the verification email to %s?',
357 ->addSubmitButton(pht('Send Email'))
358 ->addCancelButton($uri);
360 return id(new AphrontDialogResponse())->setDialog($dialog);
363 private function returnPrimaryAddressResponse(
364 AphrontRequest
$request,
367 $user = $this->getUser();
368 $viewer = $this->getViewer();
370 $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
373 $this->getPanelURI());
375 // NOTE: You can only make your own verified addresses primary.
376 $email = id(new PhabricatorUserEmail())->loadOneWhere(
377 'id = %d AND userPHID = %s AND isVerified = 1 AND isPrimary = 0',
382 return new Aphront404Response();
385 if ($request->isFormPost()) {
386 id(new PhabricatorUserEditor())
388 ->changePrimaryEmail($user, $email);
390 return id(new AphrontRedirectResponse())->setURI($uri);
393 $address = $email->getAddress();
395 $dialog = id(new AphrontDialogView())
397 ->addHiddenInput('primary', $email_id)
398 ->setTitle(pht('Change primary email address?'))
401 'If you change your primary address, Phabricator will send all '.
406 'Note: Changing your primary email address will invalidate any '.
407 'outstanding password reset links.'))
408 ->addSubmitButton(pht('Change Primary Address'))
409 ->addCancelButton($uri);
411 return id(new AphrontDialogResponse())->setDialog($dialog);