private function assertEmail($expect, $herald_hints, $reply_hints)
 {
     $env = PhabricatorEnv::beginScopedEnv();
     $env->overrideEnvConfig('phabricator.production-uri', 'http://test.com/');
     $env->overrideEnvConfig('metamta.herald.show-hints', $herald_hints);
     $env->overrideEnvConfig('metamta.reply.show-hints', $reply_hints);
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection('salmon');
     $body->addTextSection('HEADER', "bass\ntrout\n");
     $body->addHeraldSection('/xscript/');
     $body->addReplySection('pike');
     $this->assertEqual($expect, $body->render());
 }
    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();
    }
 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();
     }
 }
 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();
 }
 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();
     }
 }
 protected function buildBody()
 {
     $main_body = $this->renderBody();
     $body = new PhabricatorMetaMTAMailBody();
     $body->addRawSection($main_body);
     $reply_handler = $this->getReplyHandler();
     $body->addReplySection($reply_handler->getReplyHandlerInstructions());
     if ($this->getHeraldTranscriptURI() && $this->isFirstMailToRecipients()) {
         $manage_uri = '/herald/view/differential/';
         $xscript_uri = $this->getHeraldTranscriptURI();
         $body->addHeraldSection($manage_uri, $xscript_uri);
     }
     return $body->render();
 }