public function willSendMail(PhabricatorMetaMTAMail $mail) { $viewer = $this->getViewer(); $mail->addPHIDHeaders('X-Phabricator-To', $this->rawToPHIDs); $mail->addPHIDHeaders('X-Phabricator-Cc', $this->rawCCPHIDs); $to_handles = $viewer->loadHandles($this->rawToPHIDs); $cc_handles = $viewer->loadHandles($this->rawCCPHIDs); $body = $mail->getBody(); $body .= "\n"; $body .= $this->getRecipientsSummary($to_handles, $cc_handles); $mail->setBody($body); $html_body = $mail->getHTMLBody(); if (strlen($html_body)) { $html_body .= hsprintf('%s', $this->getRecipientsSummaryHTML($to_handles, $cc_handles)); } $mail->setHTMLBody($html_body); $reply_to = $this->getReplyTo(); if ($reply_to) { $mail->setReplyTo($reply_to); } $to = array_keys($this->getToMap()); if ($to) { $mail->addTos($to); } $cc = array_keys($this->getCCMap()); if ($cc) { $mail->addCCs($cc); } return $mail; }
public function testRecipients() { $user = $this->generateNewTestUser(); $phid = $user->getPHID(); $mailer = new PhabricatorMailImplementationTestAdapter(); $mail = new PhabricatorMetaMTAMail(); $mail->addTos(array($phid)); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"To" is a recipient.')); // Test that the "No Self Mail" and "No Mail" preferences work correctly. $mail->setFrom($phid); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" does not exclude recipients by default.')); $user = $this->writeSetting($user, PhabricatorEmailSelfActionsSetting::SETTINGKEY, true); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('"From" excludes recipients with no-self-mail set.')); $user = $this->writeSetting($user, PhabricatorEmailSelfActionsSetting::SETTINGKEY, null); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" does not exclude recipients by default.')); $user = $this->writeSetting($user, PhabricatorEmailNotificationsSetting::SETTINGKEY, true); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('"From" excludes recipients with no-mail set.')); $mail->setForceDelivery(true); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" includes no-mail recipients when forced.')); $mail->setForceDelivery(false); $user = $this->writeSetting($user, PhabricatorEmailNotificationsSetting::SETTINGKEY, null); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" does not exclude recipients by default.')); // Test that explicit exclusion works correctly. $mail->setExcludeMailRecipientPHIDs(array($phid)); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('Explicit exclude excludes recipients.')); $mail->setExcludeMailRecipientPHIDs(array()); // Test that mail tag preferences exclude recipients. $user = $this->writeSetting($user, PhabricatorEmailTagsSetting::SETTINGKEY, array('test-tag' => false)); $mail->setMailTags(array('test-tag')); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('Tag preference excludes recipients.')); $user = $this->writeSetting($user, PhabricatorEmailTagsSetting::SETTINGKEY, null); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), 'Recipients restored after tag preference removed.'); }
public function processRequest() { $request = $this->getRequest(); if ($request->isFormPost()) { $mail = new PhabricatorMetaMTAMail(); $mail->addTos($request->getArr('to')); $mail->addCCs($request->getArr('cc')); $mail->setSubject($request->getStr('subject')); $mail->setBody($request->getStr('body')); $files = $request->getArr('files'); if ($files) { foreach ($files as $phid) { $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $phid); $mail->addAttachment(new PhabricatorMetaMTAAttachment($file->loadFileData(), $file->getName(), $file->getMimeType())); } } $mail->setFrom($request->getUser()->getPHID()); $mail->setSimulatedFailureCount($request->getInt('failures')); $mail->setIsHTML($request->getInt('html')); $mail->setIsBulk($request->getInt('bulk')); $mail->setMailTags($request->getStrList('mailtags')); $mail->save(); if ($request->getInt('immediately')) { $mail->sendNow(); } return id(new AphrontRedirectResponse())->setURI($this->getApplicationURI('/view/' . $mail->getID() . '/')); } $failure_caption = "Enter a number to simulate that many consecutive send failures before " . "really attempting to deliver via the underlying MTA."; $doclink_href = PhabricatorEnv::getDoclink('article/Configuring_Outbound_Email.html'); $doclink = phutil_render_tag('a', array('href' => $doclink_href, 'target' => '_blank'), 'Configuring Outbound Email'); $instructions = '<p class="aphront-form-instructions">This form will send a normal ' . 'email using the settings you have configured for Phabricator. For more ' . 'information, see ' . $doclink . '.</p>'; $adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter'); $warning = null; if ($adapter == 'PhabricatorMailImplementationTestAdapter') { $warning = new AphrontErrorView(); $warning->setTitle('Email is Disabled'); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->appendChild('<p>This installation of Phabricator is currently set to use ' . '<tt>PhabricatorMailImplementationTestAdapter</tt> to deliver ' . 'outbound email. This completely disables outbound email! All ' . 'outbound email will be thrown in a deep, dark hole until you ' . 'configure a real adapter.</p>'); } $panel_id = celerity_generate_unique_node_id(); $phdlink_href = PhabricatorEnv::getDoclink('article/Managing_Daemons_with_phd.html'); $phdlink = phutil_render_tag('a', array('href' => $phdlink_href, 'target' => '_blank'), '"phd start"'); $form = new AphrontFormView(); $form->setUser($request->getUser()); $form->appendChild($instructions)->appendChild(id(new AphrontFormStaticControl())->setLabel('Adapter')->setValue($adapter))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('To')->setName('to')->setDatasource('/typeahead/common/mailable/'))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('CC')->setName('cc')->setDatasource('/typeahead/common/mailable/'))->appendChild(id(new AphrontFormTextControl())->setLabel('Subject')->setName('subject'))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Body')->setName('body'))->appendChild(id(new AphrontFormTextControl())->setLabel('Mail Tags')->setName('mailtags')->setCaption('Example: <tt>differential-cc, differential-comment</tt>'))->appendChild(id(new AphrontFormDragAndDropUploadControl())->setLabel('Attach Files')->setName('files')->setDragAndDropTarget($panel_id)->setActivatedClass('aphront-panel-view-drag-and-drop'))->appendChild(id(new AphrontFormTextControl())->setLabel('Simulate Failures')->setName('failures')->setCaption($failure_caption))->appendChild(id(new AphrontFormCheckboxControl())->setLabel('HTML')->addCheckbox('html', '1', 'Send as HTML email.'))->appendChild(id(new AphrontFormCheckboxControl())->setLabel('Bulk')->addCheckbox('bulk', '1', 'Send with bulk email headers.'))->appendChild(id(new AphrontFormCheckboxControl())->setLabel('Send Now')->addCheckbox('immediately', '1', 'Send immediately. (Do not enqueue for daemons.)', PhabricatorEnv::getEnvConfig('metamta.send-immediately'))->setCaption('Daemons can be started with ' . $phdlink . '.'))->appendChild(id(new AphrontFormSubmitControl())->setValue('Send Mail')); $panel = new AphrontPanelView(); $panel->setHeader('Send Email'); $panel->appendChild($form); $panel->setID($panel_id); $panel->setWidth(AphrontPanelView::WIDTH_FORM); $nav = $this->buildSideNavView(); $nav->selectFilter('send'); $nav->appendChild(array($warning, $panel)); return $this->buildApplicationPage($nav, array('title' => 'Send Test')); }
public function testRecipients() { $user = $this->generateNewTestUser(); $phid = $user->getPHID(); $prefs = $user->loadPreferences(); $mailer = new PhabricatorMailImplementationTestAdapter(); $mail = new PhabricatorMetaMTAMail(); $mail->addTos(array($phid)); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"To" is a recipient.')); // Test that the "No Self Mail" and "No Mail" preferences work correctly. $mail->setFrom($phid); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" does not exclude recipients by default.')); $prefs->setPreference(PhabricatorUserPreferences::PREFERENCE_NO_SELF_MAIL, true); $prefs->save(); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('"From" excludes recipients with no-self-mail set.')); $prefs->unsetPreference(PhabricatorUserPreferences::PREFERENCE_NO_SELF_MAIL); $prefs->save(); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" does not exclude recipients by default.')); $prefs->setPreference(PhabricatorUserPreferences::PREFERENCE_NO_MAIL, true); $prefs->save(); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('"From" excludes recipients with no-mail set.')); $mail->setForceDelivery(true); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" includes no-mail recipients when forced.')); $mail->setForceDelivery(false); $prefs->unsetPreference(PhabricatorUserPreferences::PREFERENCE_NO_MAIL); $prefs->save(); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), pht('"From" does not exclude recipients by default.')); // Test that explicit exclusion works correctly. $mail->setExcludeMailRecipientPHIDs(array($phid)); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('Explicit exclude excludes recipients.')); $mail->setExcludeMailRecipientPHIDs(array()); // Test that mail tag preferences exclude recipients. $prefs->setPreference(PhabricatorUserPreferences::PREFERENCE_MAILTAGS, array('test-tag' => false)); $prefs->save(); $mail->setMailTags(array('test-tag')); $this->assertFalse(in_array($phid, $mail->buildRecipientList()), pht('Tag preference excludes recipients.')); $prefs->unsetPreference(PhabricatorUserPreferences::PREFERENCE_MAILTAGS); $prefs->save(); $this->assertTrue(in_array($phid, $mail->buildRecipientList()), 'Recipients restored after tag preference removed.'); }
public function processRequest() { $request = $this->getRequest(); if ($request->isFormPost()) { $mail = new PhabricatorMetaMTAMail(); $mail->addTos($request->getArr('to')); $mail->addCCs($request->getArr('cc')); $mail->setSubject($request->getStr('subject')); $mail->setBody($request->getStr('body')); $mail->setFrom($request->getUser()->getPHID()); $mail->setSimulatedFailureCount($request->getInt('failures')); $mail->setIsHTML($request->getInt('html')); $mail->save(); if ($request->getInt('immediately')) { $mail->sendNow(); } return id(new AphrontRedirectResponse())->setURI('/mail/view/' . $mail->getID() . '/'); } $failure_caption = "Enter a number to simulate that many consecutive send failures before " . "really attempting to deliver via the underlying MTA."; $doclink_href = PhabricatorEnv::getDoclink('article/Configuring_Outbound_Email.html'); $doclink = phutil_render_tag('a', array('href' => $doclink_href, 'target' => '_blank'), 'Configuring Outbound Email'); $instructions = '<p class="aphront-form-instructions">This form will send a normal ' . 'email using the settings you have configured for Phabricator. For more ' . 'information, see ' . $doclink . '.</p>'; $adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter'); $warning = null; if ($adapter == 'PhabricatorMailImplementationTestAdapter') { $warning = new AphrontErrorView(); $warning->setTitle('Email is Disabled'); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->appendChild('<p>This installation of Phabricator is currently set to use ' . '<tt>PhabricatorMailImplementationTestAdapter</tt> to deliver ' . 'outbound email. This completely disables outbound email! All ' . 'outbound email will be thrown in a deep, dark hole until you ' . 'configure a real adapter.</p>'); } $form = new AphrontFormView(); $form->setUser($request->getUser()); $form->setAction('/mail/send/'); $form->appendChild($instructions)->appendChild(id(new AphrontFormStaticControl())->setLabel('Configured Adapter')->setValue($adapter))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('To')->setName('to')->setDatasource('/typeahead/common/mailable/'))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('CC')->setName('cc')->setDatasource('/typeahead/common/mailable/'))->appendChild(id(new AphrontFormTextControl())->setLabel('Subject')->setName('subject'))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Body')->setName('body'))->appendChild(id(new AphrontFormTextControl())->setLabel('Simulate Failures')->setName('failures')->setCaption($failure_caption))->appendChild(id(new AphrontFormCheckboxControl())->setLabel('HTML')->addCheckbox('html', '1', 'Send as HTML email.'))->appendChild(id(new AphrontFormCheckboxControl())->setLabel('Send Now')->addCheckbox('immediately', '1', 'Send immediately, not via MetaMTA background script.'))->appendChild(id(new AphrontFormSubmitControl())->setValue('Send Mail')); $panel = new AphrontPanelView(); $panel->setHeader('Send Email'); $panel->appendChild($form); $panel->setWidth(AphrontPanelView::WIDTH_WIDE); return $this->buildStandardPageResponse(array($warning, $panel), array('title' => 'Send Mail')); }
public function parseCommit(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit) { if ($repository->getDetail('herald-disabled')) { return; } $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID()); $rules = HeraldRule::loadAllByContentTypeWithFullData(HeraldContentTypeConfig::CONTENT_TYPE_COMMIT); $adapter = new HeraldCommitAdapter($repository, $commit, $data); $engine = new HeraldEngine(); $effects = $engine->applyRules($rules, $adapter); $engine->applyEffects($effects, $adapter); $email_phids = $adapter->getEmailPHIDs(); if (!$email_phids) { return; } $xscript = $engine->getTranscript(); $commit_name = $adapter->getHeraldName(); $revision = $adapter->loadDifferentialRevision(); $name = null; if ($revision) { $name = ' ' . $revision->getTitle(); } $author_phid = $data->getCommitDetail('authorPHID'); $reviewer_phid = $data->getCommitDetail('reviewerPHID'); $phids = array_filter(array($author_phid, $reviewer_phid)); $handles = array(); if ($phids) { $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); } if ($author_phid) { $author_name = $handles[$author_phid]->getName(); } else { $author_name = $data->getAuthorName(); } if ($reviewer_phid) { $reviewer_name = $handles[$reviewer_phid]->getName(); } else { $reviewer_name = null; } $who = implode(', ', array_filter(array($author_name, $reviewer_name))); $description = $data->getCommitMessage(); $details = PhabricatorEnv::getProductionURI('/' . $commit_name); $differential = $revision ? PhabricatorEnv::getProductionURI('/D' . $revision->getID()) : 'No revision.'; $files = $adapter->loadAffectedPaths(); sort($files); $files = implode("\n ", $files); $xscript_id = $xscript->getID(); $manage_uri = PhabricatorEnv::getProductionURI('/herald/view/commits/'); $why_uri = PhabricatorEnv::getProductionURI('/herald/transcript/' . $xscript_id . '/'); $body = <<<EOBODY DESCRIPTION {$description} DETAILS {$details} DIFFERENTIAL REVISION {$differential} AFFECTED FILES {$files} MANAGE HERALD COMMIT RULES {$manage_uri} WHY DID I GET THIS EMAIL? {$why_uri} EOBODY; $subject = "[Herald/Commit] {$commit_name} ({$who}){$name}"; $mailer = new PhabricatorMetaMTAMail(); $mailer->setRelatedPHID($commit->getPHID()); $mailer->addTos($email_phids); $mailer->setSubject($subject); $mailer->setBody($body); $mailer->addHeader('X-Herald-Rules', $xscript->getXHeraldRulesHeader()); if ($author_phid) { $mailer->setFrom($author_phid); } $mailer->saveAndSend(); }
public function processRequest() { $request = $this->getRequest(); if (!PhabricatorEnv::getEnvConfig('auth.password-auth-enabled')) { return new Aphront400Response(); } $e_email = true; $e_captcha = true; $errors = array(); if ($request->isFormPost()) { $e_email = null; $e_captcha = 'Again'; $captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request); if (!$captcha_ok) { $errors[] = "Captcha response is incorrect, try again."; $e_captcha = 'Invalid'; } $email = $request->getStr('email'); if (!strlen($email)) { $errors[] = "You must provide an email address."; $e_email = 'Required'; } if (!$errors) { // NOTE: Don't validate the email unless the captcha is good; this makes // it expensive to fish for valid email addresses while giving the user // a better error if they goof their email. $target_user = id(new PhabricatorUser())->loadOneWhere('email = %s', $email); if (!$target_user) { $errors[] = "There is no account associated with that email address."; $e_email = "Invalid"; } if (!$errors) { $uri = $target_user->getEmailLoginURI(); $body = <<<EOBODY Condolences on forgetting your password. You can use this link to reset it: {$uri} After you set a new password, consider writing it down on a sticky note and attaching it to your monitor so you don't forget again! Choosing a very short, easy-to-remember password like "cat" or "1234" might also help. Best Wishes, Phabricator EOBODY; $mail = new PhabricatorMetaMTAMail(); $mail->setSubject('[Phabricator] Password Reset'); $mail->setFrom($target_user->getPHID()); $mail->addTos(array($target_user->getPHID())); $mail->setBody($body); $mail->saveAndSend(); $view = new AphrontRequestFailureView(); $view->setHeader('Check Your Email'); $view->appendChild('<p>An email has been sent with a link you can use to login.</p>'); return $this->buildStandardPageResponse($view, array('title' => 'Email Sent')); } } } $email_auth = new AphrontFormView(); $email_auth->setAction('/login/email/')->setUser($request->getUser())->appendChild(id(new AphrontFormTextControl())->setLabel('Email')->setName('email')->setValue($request->getStr('email'))->setError($e_email))->appendChild(id(new AphrontFormRecaptchaControl())->setLabel('Captcha')->setError($e_captcha))->appendChild(id(new AphrontFormSubmitControl())->setValue('Send Email')); $error_view = null; if ($errors) { $error_view = new AphrontErrorView(); $error_view->setTitle('Login Error'); $error_view->setErrors($errors); } $panel = new AphrontPanelView(); $panel->setWidth(AphrontPanelView::WIDTH_FORM); $panel->appendChild('<h1>Forgot Password / Email Login</h1>'); $panel->appendChild($email_auth); return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Create New Account')); }