protected function processReceivedMail(PhabricatorMetaMTAReceivedMail $mail, PhabricatorUser $sender)
 {
     $title = $mail->getSubject();
     if (!$title) {
         $title = pht('Email Paste');
     }
     $file = PhabricatorPasteEditor::initializeFileForPaste($sender, $title, $mail->getCleanTextBody());
     $xactions = array();
     $xactions[] = id(new PhabricatorPasteTransaction())->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT)->setNewValue($file->getPHID());
     $xactions[] = id(new PhabricatorPasteTransaction())->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE)->setNewValue($title);
     $xactions[] = id(new PhabricatorPasteTransaction())->setTransactionType(PhabricatorPasteTransaction::TYPE_LANGUAGE)->setNewValue('');
     // auto-detect
     $paste = PhabricatorPaste::initializeNewPaste($sender);
     $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID()));
     $editor = id(new PhabricatorPasteEditor())->setActor($sender)->setContentSource($content_source)->setContinueOnNoEffect(true);
     $xactions = $editor->applyTransactions($paste, $xactions);
     $mail->setRelatedPHID($paste->getPHID());
     $subject_prefix = PhabricatorEnv::getEnvConfig('metamta.paste.subject-prefix');
     $subject = pht('You successfully created a paste.');
     $paste_uri = PhabricatorEnv::getProductionURI($paste->getURI());
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($subject);
     $body->addTextSection(pht('PASTE LINK'), $paste_uri);
     id(new PhabricatorMetaMTAMail())->addTos(array($sender->getPHID()))->setSubject($subject)->setSubjectPrefix($subject_prefix)->setFrom($sender->getPHID())->setRelatedPHID($paste->getPHID())->setBody($body->render())->saveAndSend();
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     // Put all the merged commits info int the mail body if this is a merge
     $merges_caption = '';
     // TODO: Make this limit configurable after T6030
     $limit = 50;
     $commit = $this->getObject();
     try {
         $merges = DiffusionPathChange::newFromConduit(id(new ConduitCall('diffusion.mergedcommitsquery', array('commit' => $commit->getCommitIdentifier(), 'limit' => $limit + 1, 'repository' => $commit->getRepository()->getPHID())))->setUser($this->getViewer())->execute());
         if (count($merges) > $limit) {
             $merges = array_slice($merges, 0, $limit);
             $merges_caption = pht("This commit merges more than %d changes. Only the first " . "%d are shown.\n", $limit, $limit);
         }
         if ($merges) {
             $merge_commits = array();
             foreach ($merges as $merge) {
                 $merge_commits[] = $merge->getAuthorName() . ': ' . $merge->getSummary();
             }
             $body->addTextSection(pht('MERGED COMMITS'), $merges_caption . implode("\n", $merge_commits));
         }
     } catch (ConduitException $ex) {
         // Log the exception into the email body
         $body->addTextSection(pht('MERGED COMMITS'), pht('Error generating merged commits: ') . $ex->getMessage());
     }
 }
 private function assertEmail($expect, $herald_hints)
 {
     $env = PhabricatorEnv::beginScopedEnv();
     $env->overrideEnvConfig('phabricator.production-uri', 'http://test.com/');
     $env->overrideEnvConfig('metamta.herald.show-hints', $herald_hints);
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection('salmon');
     $body->addTextSection('HEADER', "bass\ntrout\n");
     $body->addHeraldSection('/xscript/');
     $this->assertEqual($expect, $body->render());
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     $params = array('commit' => $this->getObject()->getCommitIdentifier(), 'callsign' => $this->getObject()->getRepository()->getCallsign());
     $tags_raw = id(new ConduitCall('diffusion.tagsquery', $params))->setUser($this->getViewer())->execute();
     $tags = DiffusionRepositoryTag::newFromConduit($tags_raw);
     if (!$tags) {
         return;
     }
     $tag_names = mpull($tags, 'getName');
     sort($tag_names);
     $body->addTextSection(pht('TAGS'), implode(', ', $tag_names));
 }
 public function buildApplicationTransactionMailBody(PhabricatorApplicationTransaction $xaction, PhabricatorMetaMTAMailBody $body)
 {
     $params = array('contains' => $this->getObject()->getCommitIdentifier(), 'callsign' => $this->getObject()->getRepository()->getCallsign());
     $branches_raw = id(new ConduitCall('diffusion.branchquery', $params))->setUser($this->getViewer())->execute();
     $branches = DiffusionRepositoryRef::loadAllFromDictionaries($branches_raw);
     if (!$branches) {
         return;
     }
     $branch_names = mpull($branches, 'getShortName');
     sort($branch_names);
     $body->addTextSection(pht('BRANCHES'), implode(', ', $branch_names));
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED;
     // Show the "BRANCH" section only if there's a new diff or the revision
     // is "Accepted".
     if (!$editor->getDiffUpdateTransaction($xactions) && $this->getObject()->getStatus() != $status_accepted) {
         return;
     }
     $branch = $this->getBranchDescription($this->getObject()->getActiveDiff());
     if ($branch === null) {
         return;
     }
     $body->addTextSection(pht('BRANCH'), $branch);
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     $params = array('contains' => $this->getObject()->getCommitIdentifier(), 'callsign' => $this->getObject()->getRepository()->getCallsign());
     try {
         $branches_raw = id(new ConduitCall('diffusion.branchquery', $params))->setUser($this->getViewer())->execute();
         $branches = DiffusionRepositoryRef::loadAllFromDictionaries($branches_raw);
         if (!$branches) {
             return;
         }
         $branch_names = mpull($branches, 'getShortName');
         sort($branch_names);
         $branch_text = implode(', ', $branch_names);
     } catch (Exception $ex) {
         $branch_text = pht('<%s: %s>', get_class($ex), $ex->getMessage());
     }
     $body->addTextSection(pht('BRANCHES'), $branch_text);
 }
 protected function processReceivedMail(PhabricatorMetaMTAReceivedMail $mail, PhabricatorUser $sender)
 {
     $attachment_phids = $mail->getAttachments();
     if (empty($attachment_phids)) {
         throw new PhabricatorMetaMTAReceivedMailProcessingException(MetaMTAReceivedMailStatus::STATUS_UNHANDLED_EXCEPTION, pht('Ignoring email to create files that did not include attachments.'));
     }
     $first_phid = head($attachment_phids);
     $mail->setRelatedPHID($first_phid);
     $attachment_count = count($attachment_phids);
     if ($attachment_count > 1) {
         $subject = pht('You successfully uploaded %d files.', $attachment_count);
     } else {
         $subject = pht('You successfully uploaded a file.');
     }
     $subject_prefix = PhabricatorEnv::getEnvConfig('metamta.files.subject-prefix');
     $file_uris = array();
     foreach ($attachment_phids as $phid) {
         $file_uris[] = PhabricatorEnv::getProductionURI('/file/info/' . $phid . '/');
     }
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($subject);
     $body->addTextSection(pht('FILE LINKS'), implode("\n", $file_uris));
     id(new PhabricatorMetaMTAMail())->addTos(array($sender->getPHID()))->setSubject($subject)->setSubjectPrefix($subject_prefix)->setFrom($sender->getPHID())->setRelatedPHID($first_phid)->setBody($body->render())->saveAndSend();
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     if ($editor->getIsNewObject()) {
         return;
     }
     if ($editor->getIsCloseByCommit()) {
         return;
     }
     $xaction = $editor->getDiffUpdateTransaction($xactions);
     if (!$xaction) {
         return;
     }
     $original = id(new DifferentialDiffQuery())->setViewer($this->getViewer())->withPHIDs(array($xaction->getOldValue()))->executeOne();
     if (!$original) {
         return;
     }
     $revision = $this->getObject();
     $current = $revision->getActiveDiff();
     $old_id = $original->getID();
     $new_id = $current->getID();
     $uri = '/' . $revision->getMonogram() . '?vs=' . $old_id . '&id=' . $new_id;
     $uri = PhabricatorEnv::getProductionURI($uri);
     $body->addTextSection(pht('CHANGES SINCE LAST UPDATE'), $uri);
 }
 private function sendMail(PhabricatorMailTarget $target, PhabricatorRepository $repository, PhabricatorRepositoryPushEvent $event)
 {
     $task_data = $this->getTaskData();
     $viewer = $target->getViewer();
     $locale = PhabricatorEnv::beginScopedLocale($viewer->getTranslation());
     $logs = $event->getLogs();
     list($ref_lines, $ref_list) = $this->renderRefs($logs);
     list($commit_lines, $subject_line) = $this->renderCommits($repository, $logs, idx($task_data, 'info', array()));
     $ref_count = count($ref_lines);
     $commit_count = count($commit_lines);
     $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(array($event->getPusherPHID()))->execute();
     $pusher_name = $handles[$event->getPusherPHID()]->getName();
     $repo_name = $repository->getMonogram();
     if ($commit_count) {
         $overview = pht('%s pushed %d commit(s) to %s.', $pusher_name, $commit_count, $repo_name);
     } else {
         $overview = pht('%s pushed to %s.', $pusher_name, $repo_name);
     }
     $details_uri = PhabricatorEnv::getProductionURI('/diffusion/pushlog/view/' . $event->getID() . '/');
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($overview);
     $body->addLinkSection(pht('DETAILS'), $details_uri);
     if ($commit_lines) {
         $body->addTextSection(pht('COMMITS'), implode("\n", $commit_lines));
     }
     if ($ref_lines) {
         $body->addTextSection(pht('REFERENCES'), implode("\n", $ref_lines));
     }
     $prefix = PhabricatorEnv::getEnvConfig('metamta.diffusion.subject-prefix');
     $parts = array();
     if ($commit_count) {
         $parts[] = pht('%s commit(s)', $commit_count);
     }
     if ($ref_count) {
         $parts[] = implode(', ', $ref_list);
     }
     $parts = implode(', ', $parts);
     if ($subject_line) {
         $subject = pht('(%s) %s', $parts, $subject_line);
     } else {
         $subject = pht('(%s)', $parts);
     }
     $mail = id(new PhabricatorMetaMTAMail())->setRelatedPHID($event->getPHID())->setSubjectPrefix($prefix)->setVarySubjectPrefix(pht('[Push]'))->setSubject($subject)->setFrom($event->getPusherPHID())->setBody($body->render())->setThreadID($event->getPHID(), $is_new = true)->addHeader('Thread-Topic', $subject)->setIsBulk(true);
     $target->sendMail($mail);
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     $repository = $this->getObject()->getRepository();
     if ($repository === null) {
         return;
     }
     $body->addTextSection(pht('REPOSITORY'), $repository->getMonogram() . ' ' . $repository->getName());
 }
 private function appendChangeDetailsForMail(PhabricatorLiskDAO $object, DifferentialDiff $diff, $patch, PhabricatorMetaMTAMailBody $body)
 {
     $section = id(new DifferentialChangeDetailMailView())->setViewer($this->getActor())->setDiff($diff)->setPatch($patch)->buildMailSection();
     $header = pht('CHANGE DETAILS');
     $section_text = "\n" . $section->getPlaintext();
     $style = array('margin: 6px 0 12px 0;');
     $section_html = phutil_tag('div', array('style' => implode(' ', $style)), $section->getHTML());
     $body->addPlaintextSection($header, $section_text, false);
     $body->addHTMLSection($header, $section_html);
 }
 protected function addEmailPreferenceSectionToMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorLiskDAO $object, array $xactions)
 {
     $href = PhabricatorEnv::getProductionURI('/' . $object->getMonogram() . '?settings');
     $label = pht('EMAIL PREFERENCES FOR THIS ROOM');
     $body->addLinkSection($label, $href);
 }
 public function parseCommit(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit)
 {
     $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     if (!$data) {
         // TODO: Permanent failure.
         return;
     }
     $rules = HeraldRule::loadAllByContentTypeWithFullData(HeraldContentTypeConfig::CONTENT_TYPE_COMMIT, $commit->getPHID());
     $adapter = new HeraldCommitAdapter($repository, $commit, $data);
     $engine = new HeraldEngine();
     $effects = $engine->applyRules($rules, $adapter);
     $engine->applyEffects($effects, $adapter, $rules);
     $audit_phids = $adapter->getAuditMap();
     if ($audit_phids) {
         $this->createAudits($commit, $audit_phids, $rules);
     }
     $explicit_auditors = $this->createAuditsFromCommitMessage($commit, $data);
     if ($repository->getDetail('herald-disabled')) {
         // This just means "disable email"; audits are (mostly) idempotent.
         return;
     }
     $this->publishFeedStory($repository, $commit, $data);
     $herald_targets = $adapter->getEmailPHIDs();
     $email_phids = array_unique(array_merge($explicit_auditors, $herald_targets));
     if (!$email_phids) {
         return;
     }
     $xscript = $engine->getTranscript();
     $revision = $adapter->loadDifferentialRevision();
     if ($revision) {
         $name = $revision->getTitle();
     } else {
         $name = $data->getSummary();
     }
     $author_phid = $data->getCommitDetail('authorPHID');
     $reviewer_phid = $data->getCommitDetail('reviewerPHID');
     $phids = array_filter(array($author_phid, $reviewer_phid, $commit->getPHID()));
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $commit_handle = $handles[$commit->getPHID()];
     $commit_name = $commit_handle->getName();
     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();
     $commit_uri = PhabricatorEnv::getProductionURI($commit_handle->getURI());
     $differential = $revision ? PhabricatorEnv::getProductionURI('/D' . $revision->getID()) : 'No revision.';
     $files = $adapter->loadAffectedPaths();
     sort($files);
     $files = implode("\n", $files);
     $xscript_id = $xscript->getID();
     $manage_uri = '/herald/view/commits/';
     $why_uri = '/herald/transcript/' . $xscript_id . '/';
     $reply_handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit($commit);
     $template = new PhabricatorMetaMTAMail();
     $inline_patch_text = $this->buildPatch($template, $repository, $commit);
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($description);
     $body->addTextSection(pht('DETAILS'), $commit_uri);
     $body->addTextSection(pht('DIFFERENTIAL REVISION'), $differential);
     $body->addTextSection(pht('AFFECTED FILES'), $files);
     $body->addReplySection($reply_handler->getReplyHandlerInstructions());
     $body->addHeraldSection($manage_uri, $why_uri);
     $body->addRawSection($inline_patch_text);
     $body = $body->render();
     $prefix = PhabricatorEnv::getEnvConfig('metamta.diffusion.subject-prefix');
     $threading = PhabricatorAuditCommentEditor::getMailThreading($repository, $commit);
     list($thread_id, $thread_topic) = $threading;
     $template->setRelatedPHID($commit->getPHID());
     $template->setSubject("{$commit_name}: {$name}");
     $template->setSubjectPrefix($prefix);
     $template->setVarySubjectPrefix("[Commit]");
     $template->setBody($body);
     $template->setThreadID($thread_id, $is_new = true);
     $template->addHeader('Thread-Topic', $thread_topic);
     $template->setIsBulk(true);
     $template->addHeader('X-Herald-Rules', $xscript->getXHeraldRulesHeader());
     if ($author_phid) {
         $template->setFrom($author_phid);
     }
     $mails = $reply_handler->multiplexMail($template, id(new PhabricatorObjectHandleData($email_phids))->loadHandles(), array());
     foreach ($mails as $mail) {
         $mail->saveAndSend();
     }
 }
Example #15
0
 protected function buildMailBody(PhabricatorLiskDAO $object, array $xactions)
 {
     $body = new PhabricatorMetaMTAMailBody();
     $headers = array();
     $comments = array();
     $inline_comments = array();
     foreach ($xactions as $xaction) {
         if ($xaction->shouldHide()) {
             continue;
         }
         $comment = $xaction->getComment();
         switch ($xaction->getTransactionType()) {
             case PholioTransactionType::TYPE_INLINE:
                 if ($comment && strlen($comment->getContent())) {
                     $inline_comments[] = $comment;
                 }
                 break;
             case PhabricatorTransactions::TYPE_COMMENT:
                 if ($comment && strlen($comment->getContent())) {
                     $comments[] = $comment->getContent();
                 }
                 // fallthrough
             // fallthrough
             default:
                 $headers[] = id(clone $xaction)->setRenderingTarget('text')->getTitle();
                 break;
         }
     }
     $body->addRawSection(implode("\n", $headers));
     foreach ($comments as $comment) {
         $body->addRawSection($comment);
     }
     if ($inline_comments) {
         $body->addRawSection(pht('INLINE COMMENTS'));
         foreach ($inline_comments as $comment) {
             $text = pht('Image %d: %s', $comment->getImageID(), $comment->getContent());
             $body->addRawSection($text);
         }
     }
     $body->addTextSection(pht('MOCK DETAIL'), PhabricatorEnv::getProductionURI('/M' . $object->getID()));
     return $body;
 }
 protected function buildMailBody(PhabricatorLiskDAO $object, array $xactions)
 {
     $body = new PhabricatorMetaMTAMailBody();
     $body->setViewer($this->requireActor());
     $this->addHeadersAndCommentsToMailBody($body, $xactions);
     $type_inline = DifferentialTransaction::TYPE_INLINE;
     $inlines = array();
     foreach ($xactions as $xaction) {
         if ($xaction->getTransactionType() == $type_inline) {
             $inlines[] = $xaction;
         }
     }
     if ($inlines) {
         $body->addTextSection(pht('INLINE COMMENTS'), $this->renderInlineCommentsForMail($object, $inlines));
     }
     $changed_uri = $this->getChangedPriorToCommitURI();
     if ($changed_uri) {
         $body->addLinkSection(pht('CHANGED PRIOR TO COMMIT'), $changed_uri);
     }
     $this->addCustomFieldsToMailBody($body, $object, $xactions);
     $body->addLinkSection(pht('REVISION DETAIL'), PhabricatorEnv::getProductionURI('/D' . $object->getID()));
     $update_xaction = null;
     foreach ($xactions as $xaction) {
         switch ($xaction->getTransactionType()) {
             case DifferentialTransaction::TYPE_UPDATE:
                 $update_xaction = $xaction;
                 break;
         }
     }
     if ($update_xaction) {
         $diff = $this->requireDiff($update_xaction->getNewValue(), true);
         $body->addTextSection(pht('AFFECTED FILES'), $this->renderAffectedFilesForMail($diff));
         $config_key_inline = 'metamta.differential.inline-patches';
         $config_inline = PhabricatorEnv::getEnvConfig($config_key_inline);
         $config_key_attach = 'metamta.differential.attach-patches';
         $config_attach = PhabricatorEnv::getEnvConfig($config_key_attach);
         if ($config_inline || $config_attach) {
             $patch_section = $this->renderPatchForMail($diff);
             $lines = count(phutil_split_lines($patch_section->getPlaintext()));
             if ($config_inline && $lines <= $config_inline) {
                 $body->addTextSection(pht('CHANGE DETAILS'), $patch_section);
             }
             if ($config_attach) {
                 $name = pht('D%s.%s.patch', $object->getID(), $diff->getID());
                 $mime_type = 'text/x-patch; charset=utf-8';
                 $body->addAttachment(new PhabricatorMetaMTAAttachment($patch_section->getPlaintext(), $name, $mime_type));
             }
         }
     }
     return $body;
 }
 protected function processReceivedMail(PhabricatorMetaMTAReceivedMail $mail, PhabricatorUser $sender)
 {
     $attachments = $mail->getAttachments();
     $files = array();
     $errors = array();
     if ($attachments) {
         $files = id(new PhabricatorFileQuery())->setViewer($sender)->withPHIDs($attachments)->execute();
         foreach ($files as $index => $file) {
             if ($file->getMimeType() != 'text/plain') {
                 $errors[] = pht('Could not parse file %s; only files with mimetype text/plain ' . 'can be parsed via email.', $file->getName());
                 unset($files[$index]);
             }
         }
     }
     $diffs = array();
     foreach ($files as $file) {
         $call = new ConduitCall('differential.createrawdiff', array('diff' => $file->loadFileData()));
         $call->setUser($sender);
         try {
             $result = $call->execute();
             $diffs[$file->getName()] = $result['uri'];
         } catch (Exception $e) {
             $errors[] = pht('Could not parse attachment %s; only attachments (and mail bodies) ' . 'generated via "diff" commands can be parsed.', $file->getName());
         }
     }
     $body = $mail->getCleanTextBody();
     if ($body) {
         $call = new ConduitCall('differential.createrawdiff', array('diff' => $body));
         $call->setUser($sender);
         try {
             $result = $call->execute();
             $diffs[pht('Mail Body')] = $result['uri'];
         } catch (Exception $e) {
             $errors[] = pht('Could not parse mail body; only mail bodies (and attachments) ' . 'generated via "diff" commands can be parsed.');
         }
     }
     $subject_prefix = PhabricatorEnv::getEnvConfig('metamta.differential.subject-prefix');
     if (count($diffs)) {
         $subject = pht('You successfully created %d diff(s).', count($diffs));
     } else {
         $subject = pht('Diff creation failed; see body for %s error(s).', new PhutilNumber(count($errors)));
     }
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($subject);
     if (count($diffs)) {
         $text_body = '';
         $html_body = array();
         $body_label = pht('%s DIFF LINK(S)', new PhutilNumber(count($diffs)));
         foreach ($diffs as $filename => $diff_uri) {
             $text_body .= $filename . ': ' . $diff_uri . "\n";
             $html_body[] = phutil_tag('a', array('href' => $diff_uri), $filename);
             $html_body[] = phutil_tag('br');
         }
         $body->addTextSection($body_label, $text_body);
         $body->addHTMLSection($body_label, $html_body);
     }
     if (count($errors)) {
         $body_section = new PhabricatorMetaMTAMailSection();
         $body_label = pht('%s ERROR(S)', new PhutilNumber(count($errors)));
         foreach ($errors as $error) {
             $body_section->addFragment($error);
         }
         $body->addTextSection($body_label, $body_section);
     }
     id(new PhabricatorMetaMTAMail())->addTos(array($sender->getPHID()))->setSubject($subject)->setSubjectPrefix($subject_prefix)->setFrom($sender->getPHID())->setBody($body->render())->saveAndSend();
 }
    private function buildErrorMailBody($error, PhabricatorMetaMTAReceivedMail $mail)
    {
        $original_body = $mail->getRawTextBody();
        $main_body = <<<EOBODY
Your request failed because an error was encoutered while processing it:

  ERROR: {$error}

  -- Original Body -------------------------------------------------------------

  {$original_body}

EOBODY;
        $body = new PhabricatorMetaMTAMailBody();
        $body->addRawSection($main_body);
        $body->addReplySection($this->getReplyHandlerInstructions());
        return $body->render();
    }
 private function applyHeraldRules(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit)
 {
     $commit->attachRepository($repository);
     // Don't take any actions on an importing repository. Principally, this
     // avoids generating thousands of audits or emails when you import an
     // established repository on an existing install.
     if ($repository->isImporting()) {
         return;
     }
     if ($repository->getDetail('herald-disabled')) {
         return;
     }
     $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     if (!$data) {
         throw new PhabricatorWorkerPermanentFailureException(pht('Unable to load commit data. The data for this task is invalid ' . 'or no longer exists.'));
     }
     $adapter = id(new HeraldCommitAdapter())->setCommit($commit);
     $rules = id(new HeraldRuleQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withContentTypes(array($adapter->getAdapterContentType()))->withDisabled(false)->needConditionsAndActions(true)->needAppliedToPHIDs(array($adapter->getPHID()))->needValidateAuthors(true)->execute();
     $engine = new HeraldEngine();
     $effects = $engine->applyRules($rules, $adapter);
     $engine->applyEffects($effects, $adapter, $rules);
     $xscript = $engine->getTranscript();
     $audit_phids = $adapter->getAuditMap();
     $cc_phids = $adapter->getAddCCMap();
     if ($audit_phids || $cc_phids) {
         $this->createAudits($commit, $audit_phids, $cc_phids, $rules);
     }
     HarbormasterBuildable::applyBuildPlans($commit->getPHID(), $repository->getPHID(), $adapter->getBuildPlans());
     $explicit_auditors = $this->createAuditsFromCommitMessage($commit, $data);
     $this->publishFeedStory($repository, $commit, $data);
     $herald_targets = $adapter->getEmailPHIDs();
     $email_phids = array_unique(array_merge($explicit_auditors, array_keys($cc_phids), $herald_targets));
     if (!$email_phids) {
         return;
     }
     $revision = $adapter->loadDifferentialRevision();
     if ($revision) {
         $name = $revision->getTitle();
     } else {
         $name = $data->getSummary();
     }
     $author_phid = $data->getCommitDetail('authorPHID');
     $reviewer_phid = $data->getCommitDetail('reviewerPHID');
     $phids = array_filter(array($author_phid, $reviewer_phid, $commit->getPHID()));
     $handles = id(new PhabricatorHandleQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPHIDs($phids)->execute();
     $commit_handle = $handles[$commit->getPHID()];
     $commit_name = $commit_handle->getName();
     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();
     $commit_uri = PhabricatorEnv::getProductionURI($commit_handle->getURI());
     $differential = $revision ? PhabricatorEnv::getProductionURI('/D' . $revision->getID()) : 'No revision.';
     $limit = self::MAX_FILES_SHOWN_IN_EMAIL;
     $files = $adapter->loadAffectedPaths();
     sort($files);
     if (count($files) > $limit) {
         array_splice($files, $limit);
         $files[] = '(This commit affected more than ' . $limit . ' files. ' . 'Only ' . $limit . ' are shown here and additional ones are truncated.)';
     }
     $files = implode("\n", $files);
     $xscript_id = $xscript->getID();
     $why_uri = '/herald/transcript/' . $xscript_id . '/';
     $reply_handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit($commit);
     $template = new PhabricatorMetaMTAMail();
     $inline_patch_text = $this->buildPatch($template, $repository, $commit);
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($description);
     $body->addTextSection(pht('DETAILS'), $commit_uri);
     // TODO: This should be integrated properly once we move to
     // ApplicationTransactions.
     $field_list = PhabricatorCustomField::getObjectFields($commit, PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS);
     $field_list->setViewer(PhabricatorUser::getOmnipotentUser())->readFieldsFromStorage($commit);
     foreach ($field_list->getFields() as $field) {
         try {
             $field->buildApplicationTransactionMailBody(new DifferentialTransaction(), $body);
         } catch (Exception $ex) {
             // Log the exception and continue.
             phlog($ex);
         }
     }
     $body->addTextSection(pht('DIFFERENTIAL REVISION'), $differential);
     $body->addTextSection(pht('AFFECTED FILES'), $files);
     $body->addReplySection($reply_handler->getReplyHandlerInstructions());
     $body->addHeraldSection($why_uri);
     $body->addRawSection($inline_patch_text);
     $body = $body->render();
     $prefix = PhabricatorEnv::getEnvConfig('metamta.diffusion.subject-prefix');
     $threading = PhabricatorAuditCommentEditor::getMailThreading($repository, $commit);
     list($thread_id, $thread_topic) = $threading;
     $template->setRelatedPHID($commit->getPHID());
     $template->setSubject("{$commit_name}: {$name}");
     $template->setSubjectPrefix($prefix);
     $template->setVarySubjectPrefix('[Commit]');
     $template->setBody($body);
     $template->setThreadID($thread_id, $is_new = true);
     $template->addHeader('Thread-Topic', $thread_topic);
     $template->setIsBulk(true);
     $template->addHeader('X-Herald-Rules', $xscript->getXHeraldRulesHeader());
     if ($author_phid) {
         $template->setFrom($author_phid);
     }
     // TODO: We should verify that each recipient can actually see the
     // commit before sending them email (T603).
     $mails = $reply_handler->multiplexMail($template, id(new PhabricatorHandleQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPHIDs($email_phids)->execute(), array());
     foreach ($mails as $mail) {
         $mail->saveAndSend();
     }
 }
 private function inlinePatch(PhabricatorMetaMTAMailBody $body, PhabricatorRepositoryCommit $commit)
 {
     if (!$this->getRawPatch()) {
         return;
     }
     $inline_key = 'metamta.diffusion.inline-patches';
     $inline_patches = PhabricatorEnv::getEnvConfig($inline_key);
     if (!$inline_patches) {
         return;
     }
     $repository = $commit->getRepository();
     $raw_patch = $this->getRawPatch();
     $result = null;
     $len = substr_count($raw_patch, "\n");
     if ($len <= $inline_patches) {
         // We send email as utf8, so we need to convert the text to utf8 if
         // we can.
         $encoding = $repository->getDetail('encoding', 'UTF-8');
         if ($encoding) {
             $raw_patch = phutil_utf8_convert($raw_patch, 'UTF-8', $encoding);
         }
         $result = phutil_utf8ize($raw_patch);
     }
     if ($result) {
         $result = "PATCH\n\n{$result}\n";
     }
     $body->addRawSection($result);
 }
 private function newMailMessage(PhabricatorUser $viewer, array $events)
 {
     $events = msort($events, 'getEpoch');
     $next_event = head($events);
     $body = new PhabricatorMetaMTAMailBody();
     foreach ($events as $event) {
         $body->addTextSection(null, pht('%s is starting in %s minute(s), at %s.', $event->getEvent()->getName(), $event->getDisplayMinutes(), $event->getDisplayTime()));
         $body->addLinkSection(pht('EVENT DETAIL'), PhabricatorEnv::getProductionURI($event->getEvent()->getURI()));
     }
     $next_event = head($events)->getEvent();
     $subject = $next_event->getName();
     if (count($events) > 1) {
         $more = pht('(+%s more...)', new PhutilNumber(count($events) - 1));
         $subject = "{$subject} {$more}";
     }
     $calendar_phid = id(new PhabricatorCalendarApplication())->getPHID();
     return id(new PhabricatorMetaMTAMail())->setSubject($subject)->addTos(array($viewer->getPHID()))->setSensitiveContent(false)->setFrom($calendar_phid)->setIsBulk(true)->setSubjectPrefix(pht('[Calendar]'))->setVarySubjectPrefix(pht('[Reminder]'))->setThreadID($next_event->getPHID(), false)->setRelatedPHID($next_event->getPHID())->setBody($body->render())->setHTMLBody($body->renderHTML());
 }
Example #22
0
 public function send()
 {
     $email_to = array_filter(array_unique($this->to));
     $question = $this->getQuestion();
     $target = $this->getTarget();
     $uri = PhabricatorEnv::getURI('/Q' . $question->getID());
     $thread_id = $this->getThreadID();
     $handles = id(new PhabricatorObjectHandleData($email_to))->loadHandles();
     $reply_handler = new PonderReplyHandler();
     $reply_handler->setMailReceiver($question);
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($this->renderBody());
     $body->addTextSection(pht('QUESTION DETAIL'), $uri);
     $template = id(new PhabricatorMetaMTAMail())->setSubject($this->getThreadTopic())->setSubjectPrefix($this->getSubjectPrefix())->setVarySubjectPrefix($this->renderVaryPrefix())->setFrom($target->getAuthorPHID())->setParentMessageID($this->parentMessageID)->addHeader('Thread-Topic', $this->getThreadTopic())->setThreadID($this->getThreadID(), false)->setRelatedPHID($question->getPHID())->setIsBulk(true)->setBody($body->render());
     $mails = $reply_handler->multiplexMail($template, array_select_keys($handles, $email_to), array());
     foreach ($mails as $mail) {
         $mail->saveAndSend();
     }
 }
 private function sendWaitingForApprovalEmail(PhabricatorUser $user)
 {
     $title = '[Phabricator] ' . pht('New User "%s" Awaiting Approval', $user->getUsername());
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection(pht('Newly registered user "%s" is awaiting account approval by an ' . 'administrator.', $user->getUsername()));
     $body->addLinkSection(pht('APPROVAL QUEUE'), PhabricatorEnv::getProductionURI('/people/query/approval/'));
     $body->addLinkSection(pht('DISABLE APPROVAL QUEUE'), PhabricatorEnv::getProductionURI('/config/edit/auth.require-approval/'));
     $admins = id(new PhabricatorPeopleQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withIsAdmin(true)->execute();
     if (!$admins) {
         return;
     }
     $mail = id(new PhabricatorMetaMTAMail())->addTos(mpull($admins, 'getPHID'))->setSubject($title)->setBody($body->render())->saveAndSend();
 }
 private function sendEmail($task, $transactions, $email_to, $email_cc)
 {
     $email_to = array_filter(array_unique($email_to));
     $email_cc = array_filter(array_unique($email_cc));
     $phids = array();
     foreach ($transactions as $transaction) {
         foreach ($transaction->extractPHIDs() as $phid) {
             $phids[$phid] = true;
         }
     }
     foreach ($email_to as $phid) {
         $phids[$phid] = true;
     }
     foreach ($email_cc as $phid) {
         $phids[$phid] = true;
     }
     $phids = array_keys($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $view = new ManiphestTransactionDetailView();
     $view->setTransactionGroup($transactions);
     $view->setHandles($handles);
     $view->setAuxiliaryFields($this->auxiliaryFields);
     list($action, $main_body) = $view->renderForEmail($with_date = false);
     $is_create = $this->isCreate($transactions);
     $task_uri = PhabricatorEnv::getURI('/T' . $task->getID());
     $reply_handler = $this->buildReplyHandler($task);
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($main_body);
     if ($is_create) {
         $body->addTextSection(pht('TASK DESCRIPTION'), $task->getDescription());
     }
     $body->addTextSection(pht('TASK DETAIL'), $task_uri);
     $body->addReplySection($reply_handler->getReplyHandlerInstructions());
     $thread_id = 'maniphest-task-' . $task->getPHID();
     $task_id = $task->getID();
     $title = $task->getTitle();
     $mailtags = $this->getMailTags($transactions);
     $template = id(new PhabricatorMetaMTAMail())->setSubject("T{$task_id}: {$title}")->setSubjectPrefix($this->getSubjectPrefix())->setVarySubjectPrefix("[{$action}]")->setFrom($transaction->getAuthorPHID())->setParentMessageID($this->parentMessageID)->addHeader('Thread-Topic', "T{$task_id}: " . $task->getOriginalTitle())->setThreadID($thread_id, $is_create)->setRelatedPHID($task->getPHID())->setIsBulk(true)->setMailTags($mailtags)->setBody($body->render());
     $mails = $reply_handler->multiplexMail($template, array_select_keys($handles, $email_to), array_select_keys($handles, $email_cc));
     foreach ($mails as $mail) {
         $mail->saveAndSend();
     }
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     if (!$editor->getIsNewObject()) {
         return;
     }
     $summary = $this->getValue();
     if (!strlen(trim($summary))) {
         return;
     }
     $body->addRemarkupSection(pht('REVISION SUMMARY'), $summary);
 }
 private function renderMailBody(PhabricatorAuditComment $comment, $cname, PhabricatorObjectHandle $handle, PhabricatorMailReplyHandler $reply_handler, array $inline_comments)
 {
     assert_instances_of($inline_comments, 'PhabricatorInlineCommentInterface');
     $commit = $this->commit;
     $user = $this->user;
     $name = $user->getUsername();
     $verb = PhabricatorAuditActionConstants::getActionPastTenseVerb($comment->getAction());
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection("{$name} {$verb} commit {$cname}.");
     $body->addRawSection($comment->getContent());
     if ($inline_comments) {
         $block = array();
         $path_map = id(new DiffusionPathQuery())->withPathIDs(mpull($inline_comments, 'getPathID'))->execute();
         $path_map = ipull($path_map, 'path', 'id');
         foreach ($inline_comments as $inline) {
             $path = idx($path_map, $inline->getPathID());
             if ($path === null) {
                 continue;
             }
             $start = $inline->getLineNumber();
             $len = $inline->getLineLength();
             if ($len) {
                 $range = $start . '-' . ($start + $len);
             } else {
                 $range = $start;
             }
             $content = $inline->getContent();
             $block[] = "{$path}:{$range} {$content}";
         }
         $body->addTextSection(pht('INLINE COMMENTS'), implode("\n", $block));
     }
     $body->addTextSection(pht('COMMIT'), PhabricatorEnv::getProductionURI($handle->getURI()));
     $body->addReplySection($reply_handler->getReplyHandlerInstructions());
     return $body->render();
 }
 /**
  * @task mail
  */
 protected function buildMailBody(PhabricatorLiskDAO $object, array $xactions)
 {
     $headers = array();
     $comments = array();
     foreach ($xactions as $xaction) {
         if ($xaction->shouldHideForMail($xactions)) {
             continue;
         }
         $header = $xaction->getTitleForMail();
         if ($header !== null) {
             $headers[] = $header;
         }
         $comment = $xaction->getBodyForMail();
         if ($comment !== null) {
             $comments[] = $comment;
         }
     }
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection(implode("\n", $headers));
     foreach ($comments as $comment) {
         $body->addRawSection($comment);
     }
     if ($object instanceof PhabricatorCustomFieldInterface) {
         $field_list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_TRANSACTIONMAIL);
         $field_list->setViewer($this->getActor());
         $field_list->readFieldsFromStorage($object);
         foreach ($field_list->getFields() as $field) {
             $field->updateTransactionMailBody($body, $this, $xactions);
         }
     }
     return $body;
 }
 /**
  * @task mail
  */
 protected function addHeadersAndCommentsToMailBody(PhabricatorMetaMTAMailBody $body, array $xactions)
 {
     $headers = array();
     $comments = array();
     foreach ($xactions as $xaction) {
         if ($xaction->shouldHideForMail($xactions)) {
             continue;
         }
         $header = $xaction->getTitleForMail();
         if ($header !== null) {
             $headers[] = $header;
         }
         $comment = $xaction->getBodyForMail();
         if ($comment !== null) {
             $comments[] = $comment;
         }
     }
     $body->addRawSection(implode("\n", $headers));
     foreach ($comments as $comment) {
         $body->addRemarkupSection($comment);
     }
 }
 public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions)
 {
     if (!$editor->getIsNewObject()) {
         return;
     }
     $test_plan = $this->getValue();
     if (!strlen(trim($test_plan))) {
         return;
     }
     $body->addTextSection(pht('TEST PLAN'), $test_plan);
 }
 /**
  * @task mail
  */
 protected function addHeadersAndCommentsToMailBody(PhabricatorMetaMTAMailBody $body, array $xactions, $object_label = null, $object_href = null)
 {
     $headers = array();
     $headers_html = array();
     $comments = array();
     $details = array();
     foreach ($xactions as $xaction) {
         if ($xaction->shouldHideForMail($xactions)) {
             continue;
         }
         $header = $xaction->getTitleForMail();
         if ($header !== null) {
             $headers[] = $header;
         }
         $header_html = $xaction->getTitleForHTMLMail();
         if ($header_html !== null) {
             $headers_html[] = $header_html;
         }
         $comment = $xaction->getBodyForMail();
         if ($comment !== null) {
             $comments[] = $comment;
         }
         if ($xaction->hasChangeDetailsForMail()) {
             $details[] = $xaction;
         }
     }
     $headers_text = implode("\n", $headers);
     $body->addRawPlaintextSection($headers_text);
     $headers_html = phutil_implode_html(phutil_tag('br'), $headers_html);
     $header_button = null;
     if ($object_label !== null) {
         $button_style = array('text-decoration: none;', 'padding: 4px 8px;', 'margin: 0 8px 8px;', 'float: right;', 'color: #464C5C;', 'font-weight: bold;', 'border-radius: 3px;', 'background-color: #F7F7F9;', 'background-image: linear-gradient(to bottom,#fff,#f1f0f1);', 'display: inline-block;', 'border: 1px solid rgba(71,87,120,.2);');
         $header_button = phutil_tag('a', array('style' => implode(' ', $button_style), 'href' => $object_href), $object_label);
     }
     $xactions_style = array();
     $header_action = phutil_tag('td', array(), $header_button);
     $header_action = phutil_tag('td', array('style' => implode(' ', $xactions_style)), array($headers_html, "\n"));
     $headers_html = phutil_tag('table', array(), phutil_tag('tr', array(), array($header_action, $header_button)));
     $body->addRawHTMLSection($headers_html);
     foreach ($comments as $comment) {
         $body->addRemarkupSection(null, $comment);
     }
     foreach ($details as $xaction) {
         $details = $xaction->renderChangeDetailsForMail($body->getViewer());
         if ($details !== null) {
             $label = $this->getMailDiffSectionHeader($xaction);
             $body->addHTMLSection($label, $details);
         }
     }
 }