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 send()
 {
     $to_phids = $this->getToPHIDs();
     if (!$to_phids) {
         throw new Exception('No "To:" users provided!');
     }
     $cc_phids = $this->getCCPHIDs();
     $attachments = $this->buildAttachments();
     $template = new PhabricatorMetaMTAMail();
     $actor_handle = $this->getActorHandle();
     $reply_handler = $this->getReplyHandler();
     if ($actor_handle) {
         $template->setFrom($actor_handle->getPHID());
     }
     $template->setIsHTML($this->shouldMarkMailAsHTML())->setParentMessageID($this->parentMessageID)->addHeader('Thread-Topic', $this->getThreadTopic());
     $template->setAttachments($attachments);
     $template->setThreadID($this->getThreadID(), $this->isFirstMailAboutRevision());
     if ($this->heraldRulesHeader) {
         $template->addHeader('X-Herald-Rules', $this->heraldRulesHeader);
     }
     $revision = $this->revision;
     if ($revision) {
         if ($revision->getAuthorPHID()) {
             $template->addHeader('X-Differential-Author', '<' . $revision->getAuthorPHID() . '>');
         }
         $reviewer_phids = $revision->getReviewers();
         if ($reviewer_phids) {
             // Add several headers to support e-mail clients which are not able to
             // create rules using regular expressions or wildcards (namely Outlook).
             $template->addPHIDHeaders('X-Differential-Reviewer', $reviewer_phids);
             // Add it also as a list to allow matching of the first reviewer and
             // also for backwards compatibility.
             $template->addHeader('X-Differential-Reviewers', '<' . implode('>, <', $reviewer_phids) . '>');
         }
         if ($cc_phids) {
             $template->addPHIDHeaders('X-Differential-CC', $cc_phids);
             $template->addHeader('X-Differential-CCs', '<' . implode('>, <', $cc_phids) . '>');
             // Determine explicit CCs (those added by humans) and put them in a
             // header so users can differentiate between Herald CCs and human CCs.
             $relation_subscribed = DifferentialRevision::RELATION_SUBSCRIBED;
             $raw = $revision->getRawRelations($relation_subscribed);
             $reason_phids = ipull($raw, 'reasonPHID');
             $reason_handles = id(new PhabricatorObjectHandleData($reason_phids))->loadHandles();
             $explicit_cc = array();
             foreach ($raw as $relation) {
                 if (!$relation['reasonPHID']) {
                     continue;
                 }
                 $type = $reason_handles[$relation['reasonPHID']]->getType();
                 if ($type == PhabricatorPHIDConstants::PHID_TYPE_USER) {
                     $explicit_cc[] = $relation['objectPHID'];
                 }
             }
             if ($explicit_cc) {
                 $template->addPHIDHeaders('X-Differential-Explicit-CC', $explicit_cc);
                 $template->addHeader('X-Differential-Explicit-CCs', '<' . implode('>, <', $explicit_cc) . '>');
             }
         }
     }
     $template->setIsBulk(true);
     $template->setRelatedPHID($this->getRevision()->getPHID());
     $mailtags = $this->getMailTags();
     if ($mailtags) {
         $template->setMailTags($mailtags);
     }
     $phids = array();
     foreach ($to_phids as $phid) {
         $phids[$phid] = true;
     }
     foreach ($cc_phids as $phid) {
         $phids[$phid] = true;
     }
     $phids = array_keys($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $objects = id(new PhabricatorObjectHandleData($phids))->loadObjects();
     $to_handles = array_select_keys($handles, $to_phids);
     $cc_handles = array_select_keys($handles, $cc_phids);
     $this->prepareBody();
     $mails = $reply_handler->multiplexMail($template, $to_handles, $cc_handles);
     $original_translator = PhutilTranslator::getInstance();
     if (!PhabricatorMetaMTAMail::shouldMultiplexAllMail()) {
         $translation = PhabricatorEnv::newObjectFromConfig('translation.provider');
         $translator = id(new PhutilTranslator())->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations());
     }
     try {
         foreach ($mails as $mail) {
             if (PhabricatorMetaMTAMail::shouldMultiplexAllMail()) {
                 $translation = newv($mail->getTranslation($objects), array());
                 $translator = id(new PhutilTranslator())->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations());
                 PhutilTranslator::setInstance($translator);
             }
             $body = $this->buildBody() . "\n" . $reply_handler->getRecipientsSummary($to_handles, $cc_handles);
             $mail->setSubject($this->renderSubject())->setSubjectPrefix($this->getSubjectPrefix())->setVarySubjectPrefix($this->renderVaryPrefix())->setBody($body);
             $event = new PhabricatorEvent(PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL, array('mail' => $mail));
             PhutilEventEngine::dispatchEvent($event);
             $mail = $event->getValue('mail');
             $mail->saveAndSend();
         }
     } catch (Exception $ex) {
         PhutilTranslator::setInstance($original_translator);
         throw $ex;
     }
     PhutilTranslator::setInstance($original_translator);
 }