protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $conpherence = $this->getMailReceiver(); $user = $this->getActor(); if (!$conpherence->getPHID()) { $conpherence->attachParticipants(array())->attachFilePHIDs(array()); } else { $edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST; $file_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($conpherence->getPHID(), $edge_type); $conpherence->attachFilePHIDs($file_phids); $participants = id(new ConpherenceParticipant())->loadAllWhere('conpherencePHID = %s', $conpherence->getPHID()); $participants = mpull($participants, null, 'getParticipantPHID'); $conpherence->attachParticipants($participants); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $editor = id(new ConpherenceEditor())->setActor($user)->setContentSource($content_source)->setParentMessageID($mail->getMessageID()); $body = $mail->getCleanTextBody(); $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $xactions = array(); if ($this->getMailAddedParticipantPHIDs()) { $xactions[] = id(new ConpherenceTransaction())->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS)->setNewValue(array('+' => $this->getMailAddedParticipantPHIDs())); } $xactions = array_merge($xactions, $editor->generateTransactionsFromText($user, $conpherence, $body)); $editor->applyTransactions($conpherence, $xactions); return $conpherence; }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $actor = $this->getActor(); $document = $this->getMailReceiver(); $body_data = $mail->parseBody(); $body = $body_data['body']; $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $xactions = array(); $command = $body_data['command']; switch ($command) { case 'unsubscribe': $xaction = id(new LegalpadTransaction())->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('-' => array($actor->getPHID()))); $xactions[] = $xaction; break; } $xactions[] = id(new LegalpadTransaction())->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment(id(new LegalpadTransactionComment())->setDocumentID($document->getID())->setLineNumber(0)->setLineLength(0)->setContent($body)); $editor = id(new LegalpadDocumentEditor())->setActor($actor)->setContentSource($content_source)->setContinueOnNoEffect(true)->setIsPreview(false); try { $xactions = $editor->applyTransactions($document, $xactions); } catch (PhabricatorApplicationTransactionNoEffectException $ex) { // just do nothing, though unclear why you're sending a blank email return true; } $head_xaction = head($xactions); return $head_xaction->getID(); }
private function dropEmptyMail(PhabricatorMetaMTAReceivedMail $mail) { $body = $mail->getCleanTextBody(); $attachments = $mail->getAttachments(); if (strlen($body) || $attachments) { return; } // Only send an error email if the user is talking to just Phabricator. // We can assume if there is only one "To" address it is a Phabricator // address since this code is running and everything. $is_direct_mail = count($mail->getToAddresses()) == 1 && count($mail->getCCAddresses()) == 0; if ($is_direct_mail) { $status_code = MetaMTAReceivedMailStatus::STATUS_EMPTY; } else { $status_code = MetaMTAReceivedMailStatus::STATUS_EMPTY_IGNORED; } throw new PhabricatorMetaMTAReceivedMailProcessingException($status_code, pht('Your message does not contain any body text or attachments, so ' . 'Phabricator can not do anything useful with it. Make sure comment ' . 'text appears at the top of your message: quoted replies, inline ' . 'text, and signatures are discarded and ignored.')); }
protected final function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $viewer = $this->getActor(); $object = $this->getMailReceiver(); $app_email = $this->getApplicationEmail(); $is_new = !$object->getID(); // If this is a new object which implements the Spaces interface and was // created by sending mail to an ApplicationEmail address, put the object // in the same Space the address is in. if ($is_new) { if ($object instanceof PhabricatorSpacesInterface) { if ($app_email) { $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID($app_email); $object->setSpacePHID($space_phid); } } } $body_data = $mail->parseBody(); $body = $body_data['body']; $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $xactions = $this->didReceiveMail($mail, $body); // If this object is subscribable, subscribe all the users who were // recipients on the message. if ($object instanceof PhabricatorSubscribableInterface) { $subscriber_phids = $mail->loadAllRecipientPHIDs(); if ($subscriber_phids) { $xactions[] = $this->newTransaction()->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('+' => $subscriber_phids)); } } $command_xactions = $this->processMailCommands($mail, $body_data['commands']); foreach ($command_xactions as $xaction) { $xactions[] = $xaction; } if ($this->shouldCreateCommentFromMailBody()) { $comment = $this->newTransaction()->getApplicationTransactionCommentObject()->setContent($body); $xactions[] = $this->newTransaction()->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment($comment); } $target = $object->getApplicationTransactionObject(); $this->newEditor($mail)->setContinueOnNoEffect(true)->applyTransactions($target, $xactions); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $conpherence = $this->getMailReceiver(); $user = $this->getActor(); if (!$conpherence->getPHID()) { $conpherence->attachParticipants(array()); } else { $participants = id(new ConpherenceParticipant())->loadAllWhere('conpherencePHID = %s', $conpherence->getPHID()); $participants = mpull($participants, null, 'getParticipantPHID'); $conpherence->attachParticipants($participants); } $content_source = $mail->newContentSource(); $editor = id(new ConpherenceEditor())->setActor($user)->setContentSource($content_source)->setParentMessageID($mail->getMessageID()); $body = $mail->getCleanTextBody(); $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $xactions = array(); if ($this->getMailAddedParticipantPHIDs()) { $xactions[] = id(new ConpherenceTransaction())->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS)->setNewValue(array('+' => $this->getMailAddedParticipantPHIDs())); } $xactions = array_merge($xactions, $editor->generateTransactionsFromText($user, $conpherence, $body)); $editor->applyTransactions($conpherence, $xactions); return $conpherence; }
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 receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { // NOTE: We'll drop in here on both the "reply to a task" and "create a // new task" workflows! Make sure you test both if you make changes! $task = $this->getMailReceiver(); $is_new_task = !$task->getID(); $user = $this->getActor(); $body = $mail->getCleanTextBody(); $body = trim($body); $xactions = array(); $template = new ManiphestTransaction(); $template->setAuthorPHID($user->getPHID()); if ($is_new_task) { // If this is a new task, create a "User created this task." transaction // and then set the title and description. $xaction = clone $template; $xaction->setTransactionType(ManiphestTransactionType::TYPE_STATUS); $xaction->setNewValue(ManiphestTaskStatus::STATUS_OPEN); $xactions[] = $xaction; $task->setAuthorPHID($user->getPHID()); $task->setTitle(nonempty($mail->getSubject(), 'Untitled Task')); $task->setDescription($body); } else { $lines = explode("\n", trim($body)); $first_line = head($lines); $command = null; $matches = null; if (preg_match('/^!(\\w+)/', $first_line, $matches)) { $lines = array_slice($lines, 1); $body = implode("\n", $lines); $body = trim($body); $command = $matches[1]; } $ttype = ManiphestTransactionType::TYPE_NONE; $new_value = null; switch ($command) { case 'close': $ttype = ManiphestTransactionType::TYPE_STATUS; $new_value = ManiphestTaskStatus::STATUS_CLOSED_RESOLVED; break; case 'claim': $ttype = ManiphestTransactionType::TYPE_OWNER; $new_value = $user->getPHID(); break; case 'unsubscribe': $ttype = ManiphestTransactionType::TYPE_CCS; $ccs = $task->getCCPHIDs(); foreach ($ccs as $k => $phid) { if ($phid == $user->getPHID()) { unset($ccs[$k]); } } $new_value = array_values($ccs); break; } $xaction = clone $template; $xaction->setTransactionType($ttype); $xaction->setNewValue($new_value); $xaction->setComments($body); $xactions[] = $xaction; } // TODO: We should look at CCs on the mail and add them as CCs. $files = $mail->getAttachments(); if ($files) { $file_xaction = clone $template; $file_xaction->setTransactionType(ManiphestTransactionType::TYPE_ATTACH); $phid_type = PhabricatorPHIDConstants::PHID_TYPE_FILE; $new = $task->getAttached(); foreach ($files as $file_phid) { $new[$phid_type][$file_phid] = array(); } $file_xaction->setNewValue($new); $xactions[] = $file_xaction; } $editor = new ManiphestTransactionEditor(); $editor->setParentMessageID($mail->getMessageID()); $editor->applyTransactions($task, $xactions); }
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(); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $this->receivedMail = $mail; $this->handleAction($mail->getCleanTextBody(), $mail->getAttachments()); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { // NOTE: We'll drop in here on both the "reply to a task" and "create a // new task" workflows! Make sure you test both if you make changes! $task = $this->getMailReceiver(); $is_new_task = !$task->getID(); $user = $this->getActor(); $body_data = $mail->parseBody(); $body = $body_data['body']; $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $xactions = array(); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $template = new ManiphestTransaction(); $is_unsub = false; if ($is_new_task) { $task = ManiphestTask::initializeNewTask($user); $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_STATUS)->setNewValue(ManiphestTaskStatus::getDefaultStatus()); $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_TITLE)->setNewValue(nonempty($mail->getSubject(), pht('Untitled Task'))); $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_DESCRIPTION)->setNewValue($body); } else { $command = $body_data['command']; $command_value = $body_data['command_value']; $ttype = PhabricatorTransactions::TYPE_COMMENT; $new_value = null; switch ($command) { case 'close': $ttype = ManiphestTransaction::TYPE_STATUS; $new_value = ManiphestTaskStatus::getDefaultClosedStatus(); break; case 'claim': $ttype = ManiphestTransaction::TYPE_OWNER; $new_value = $user->getPHID(); break; case 'assign': $ttype = ManiphestTransaction::TYPE_OWNER; if ($command_value) { $assign_users = id(new PhabricatorPeopleQuery())->setViewer($user)->withUsernames(array($command_value))->execute(); if ($assign_users) { $assign_user = head($assign_users); $new_value = $assign_user->getPHID(); } } // assign to the user by default if (!$new_value) { $new_value = $user->getPHID(); } break; case 'unsubscribe': $is_unsub = true; $ttype = ManiphestTransaction::TYPE_CCS; $ccs = $task->getCCPHIDs(); foreach ($ccs as $k => $phid) { if ($phid == $user->getPHID()) { unset($ccs[$k]); } } $new_value = array_values($ccs); break; } if ($ttype != PhabricatorTransactions::TYPE_COMMENT) { $xaction = clone $template; $xaction->setTransactionType($ttype); $xaction->setNewValue($new_value); $xactions[] = $xaction; } if (strlen($body)) { $xaction = clone $template; $xaction->setTransactionType(PhabricatorTransactions::TYPE_COMMENT); $xaction->attachComment(id(new ManiphestTransactionComment())->setContent($body)); $xactions[] = $xaction; } } $ccs = $mail->loadCCPHIDs(); $old_ccs = $task->getCCPHIDs(); $new_ccs = array_merge($old_ccs, $ccs); if (!$is_unsub) { $new_ccs[] = $user->getPHID(); } $new_ccs = array_unique($new_ccs); if (array_diff($new_ccs, $old_ccs)) { $cc_xaction = clone $template; $cc_xaction->setTransactionType(ManiphestTransaction::TYPE_CCS); $cc_xaction->setNewValue($new_ccs); $xactions[] = $cc_xaction; } $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK, array('task' => $task, 'mail' => $mail, 'new' => $is_new_task, 'transactions' => $xactions)); $event->setUser($user); PhutilEventEngine::dispatchEvent($event); $task = $event->getValue('task'); $xactions = $event->getValue('transactions'); $editor = id(new ManiphestTransactionEditor())->setActor($user)->setParentMessageID($mail->getMessageID())->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs())->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setContentSource($content_source)->applyTransactions($task, $xactions); $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK, array('task' => $task, 'new' => $is_new_task, 'transactions' => $xactions)); $event->setUser($user); PhutilEventEngine::dispatchEvent($event); }