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 = $request->getStr('email');
176 if (phutil_nonempty_string($email)) {
177 $email = trim($email);
180 if ($new == 'verify') {
181 // The user clicked "Done" from the "an email has been sent" dialog.
182 return id(new AphrontReloadResponse())->setURI($uri);
185 PhabricatorSystemActionEngine
::willTakeAction(
186 array($viewer->getPHID()),
187 new PhabricatorSettingsAddEmailAction(),
190 if ($email === null ||
!strlen($email)) {
191 $e_email = pht('Required');
192 $errors[] = pht('Email is required.');
193 } else if (!PhabricatorUserEmail
::isValidAddress($email)) {
194 $e_email = pht('Invalid');
195 $errors[] = PhabricatorUserEmail
::describeValidAddresses();
196 } else if (!PhabricatorUserEmail
::isAllowedAddress($email)) {
197 $e_email = pht('Disallowed');
198 $errors[] = PhabricatorUserEmail
::describeAllowedAddresses();
200 if ($e_email === true) {
201 $application_email = id(new PhabricatorMetaMTAApplicationEmailQuery())
202 ->setViewer(PhabricatorUser
::getOmnipotentUser())
203 ->withAddresses(array($email))
205 if ($application_email) {
206 $e_email = pht('In Use');
207 $errors[] = $application_email->getInUseMessage();
212 $object = id(new PhabricatorUserEmail())
216 // If an administrator is editing a mailing list, automatically verify
218 if ($viewer->getPHID() != $user->getPHID()) {
219 if ($viewer->getIsAdmin()) {
220 $object->setIsVerified(1);
225 id(new PhabricatorUserEditor())
227 ->addEmail($user, $object);
229 if ($object->getIsVerified()) {
230 // If we autoverified the address, just reload the page.
231 return id(new AphrontReloadResponse())->setURI($uri);
234 $object->sendVerificationEmail($user);
236 $dialog = $this->newDialog()
237 ->addHiddenInput('new', 'verify')
238 ->setTitle(pht('Verification Email Sent'))
239 ->appendChild(phutil_tag('p', array(), pht(
240 'A verification email has been sent. Click the link in the '.
241 'email to verify your address.')))
243 ->addSubmitButton(pht('Done'));
245 return id(new AphrontDialogResponse())->setDialog($dialog);
246 } catch (AphrontDuplicateKeyQueryException
$ex) {
247 $e_email = pht('Duplicate');
248 $errors[] = pht('Another user already has this email.');
254 $errors = id(new PHUIInfoView())
255 ->setErrors($errors);
258 $form = id(new PHUIFormLayoutView())
260 id(new AphrontFormTextControl())
261 ->setLabel(pht('Email'))
264 ->setCaption(PhabricatorUserEmail
::describeAllowedAddresses())
265 ->setError($e_email));
267 $dialog = $this->newDialog()
268 ->addHiddenInput('new', 'true')
269 ->setTitle(pht('New Address'))
270 ->appendChild($errors)
272 ->addSubmitButton(pht('Save'))
273 ->addCancelButton($uri);
275 return id(new AphrontDialogResponse())->setDialog($dialog);
278 private function returnDeleteAddressResponse(
279 AphrontRequest
$request,
282 $user = $this->getUser();
283 $viewer = $this->getViewer();
285 $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
288 $this->getPanelURI());
290 // NOTE: You can only delete your own email addresses, and you can not
291 // delete your primary address.
292 $email = id(new PhabricatorUserEmail())->loadOneWhere(
293 'id = %d AND userPHID = %s AND isPrimary = 0',
298 return new Aphront404Response();
301 if ($request->isFormPost()) {
302 id(new PhabricatorUserEditor())
304 ->removeEmail($user, $email);
306 return id(new AphrontRedirectResponse())->setURI($uri);
309 $address = $email->getAddress();
311 $dialog = id(new AphrontDialogView())
313 ->addHiddenInput('delete', $email_id)
314 ->setTitle(pht("Really delete address '%s'?", $address))
317 'Are you sure you want to delete this address? You will no '.
318 'longer be able to use it to login.'))
321 'Note: Removing an email address from your account will invalidate '.
322 'any outstanding password reset links.'))
323 ->addSubmitButton(pht('Delete'))
324 ->addCancelButton($uri);
326 return id(new AphrontDialogResponse())->setDialog($dialog);
329 private function returnVerifyAddressResponse(
330 AphrontRequest
$request,
333 $user = $this->getUser();
334 $viewer = $this->getViewer();
336 // NOTE: You can only send more email for your unverified addresses.
337 $email = id(new PhabricatorUserEmail())->loadOneWhere(
338 'id = %d AND userPHID = %s AND isVerified = 0',
343 return new Aphront404Response();
346 if ($request->isFormPost()) {
347 $email->sendVerificationEmail($user);
348 return id(new AphrontRedirectResponse())->setURI($uri);
351 $address = $email->getAddress();
353 $dialog = id(new AphrontDialogView())
355 ->addHiddenInput('verify', $email_id)
356 ->setTitle(pht('Send Another Verification Email?'))
357 ->appendChild(phutil_tag('p', array(), pht(
358 'Send another copy of the verification email to %s?',
360 ->addSubmitButton(pht('Send Email'))
361 ->addCancelButton($uri);
363 return id(new AphrontDialogResponse())->setDialog($dialog);
366 private function returnPrimaryAddressResponse(
367 AphrontRequest
$request,
370 $user = $this->getUser();
371 $viewer = $this->getViewer();
373 $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
376 $this->getPanelURI());
378 // NOTE: You can only make your own verified addresses primary.
379 $email = id(new PhabricatorUserEmail())->loadOneWhere(
380 'id = %d AND userPHID = %s AND isVerified = 1 AND isPrimary = 0',
385 return new Aphront404Response();
388 if ($request->isFormPost()) {
389 id(new PhabricatorUserEditor())
391 ->changePrimaryEmail($user, $email);
393 return id(new AphrontRedirectResponse())->setURI($uri);
396 $address = $email->getAddress();
398 $dialog = id(new AphrontDialogView())
400 ->addHiddenInput('primary', $email_id)
401 ->setTitle(pht('Change primary email address?'))
404 'If you change your primary address, %s will send all '.
406 PlatformSymbols
::getPlatformServerName(),
410 'Note: Changing your primary email address will invalidate any '.
411 'outstanding password reset links.'))
412 ->addSubmitButton(pht('Change Primary Address'))
413 ->addCancelButton($uri);
415 return id(new AphrontDialogResponse())->setDialog($dialog);