1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-09 16:32:39 +01:00

Add basic email support to Pholio

Summary: These emails aren't yet useful, but thread/multiplex/etc correctly.

Test Plan: Got some Pholio emails.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2097

Differential Revision: https://secure.phabricator.com/D3842
This commit is contained in:
epriestley 2012-11-21 17:39:46 -08:00
parent 029cfcfc19
commit 3ceaad1aa8
5 changed files with 168 additions and 13 deletions

View file

@ -349,8 +349,9 @@ return array(
// class with an implementation of your own. This will allow you to do things
// like have a single public reply handler or change how private reply
// handlers are generated and validated.
//
// This key should be set to a loadable subclass of
// PhabricatorMailReplyHandler (and possibly of ManiphestReplyHandler).
// PhabricatorMailReplyHandler.
'metamta.maniphest.reply-handler' => 'ManiphestReplyHandler',
// If you don't want phabricator to take up an entire domain
@ -367,6 +368,13 @@ return array(
// distinguish between testing and development installs, for example.
'metamta.maniphest.subject-prefix' => '[Maniphest]',
// See 'metamta.pholio.reply-handler-domain'. This does the same thing, but
// affects Pholio.
'metamta.pholio.reply-handler-domain' => null,
// Prefix prepended to mail sent by Pholio.
'metamta.pholio.subject-prefix' => '[Pholio]',
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing,
// but allows email replies via Differential.
'metamta.differential.reply-handler-domain' => null,

View file

@ -1216,6 +1216,7 @@ phutil_register_library_map(array(
'PholioMockQuery' => 'applications/pholio/query/PholioMockQuery.php',
'PholioMockViewController' => 'applications/pholio/controller/PholioMockViewController.php',
'PholioPixelComment' => 'applications/pholio/storage/PholioPixelComment.php',
'PholioReplyHandler' => 'applications/pholio/mail/PholioReplyHandler.php',
'PholioTransaction' => 'applications/pholio/storage/PholioTransaction.php',
'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php',
'PholioTransactionType' => 'applications/pholio/constants/PholioTransactionType.php',
@ -2427,6 +2428,7 @@ phutil_register_library_map(array(
0 => 'PholioDAO',
1 => 'PhabricatorMarkupInterface',
),
'PholioReplyHandler' => 'PhabricatorMailReplyHandler',
'PholioTransaction' =>
array(
0 => 'PholioDAO',

View file

@ -6,7 +6,6 @@
final class ManiphestTransactionEditor extends PhabricatorEditor {
private $parentMessageID;
private $excludePHIDs = array();
private $auxiliaryFields = array();
public function setAuxiliaryFields(array $fields) {
@ -20,15 +19,6 @@ final class ManiphestTransactionEditor extends PhabricatorEditor {
return $this;
}
public function setExcludePHIDs(array $exclude) {
$this->excludePHIDs = $exclude;
return $this;
}
public function getExcludePHIDs() {
return $this->excludePHIDs;
}
public function applyTransactions(ManiphestTask $task, array $transactions) {
assert_instances_of($transactions, 'ManiphestTransaction');
@ -219,7 +209,6 @@ final class ManiphestTransactionEditor extends PhabricatorEditor {
}
private function sendEmail($task, $transactions, $email_to, $email_cc) {
$exclude = $this->getExcludePHIDs();
$email_to = array_filter(array_unique($email_to));
$email_cc = array_filter(array_unique($email_cc));

View file

@ -41,6 +41,8 @@ final class PholioMockEditor extends PhabricatorEditor {
"Call setContentSource() before applyTransactions()!");
}
$is_new = !$mock->getID();
$comments = array();
foreach ($xactions as $xaction) {
if (strlen($xaction->getComment())) {
@ -54,8 +56,12 @@ final class PholioMockEditor extends PhabricatorEditor {
$mentioned_phids = PhabricatorMarkupEngine::extractPHIDsFromMentions(
$comments);
$subscribe_phids = $mentioned_phids;
if ($mentioned_phids) {
// Attempt to subscribe the actor.
$subscribe_phids[] = $actor->getPHID();
if ($subscribe_phids) {
if ($mock->getID()) {
$old_subs = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$mock->getPHID());
@ -111,11 +117,99 @@ final class PholioMockEditor extends PhabricatorEditor {
$mock->saveTransaction();
$this->sendMail($mock, $xactions, $is_new, $mentioned_phids);
PholioIndexer::indexMock($mock);
return $this;
}
private function sendMail(
PholioMock $mock,
array $xactions,
$is_new,
array $mentioned_phids) {
$subscribed_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$mock->getPHID());
$email_to = array(
$mock->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
$email_cc = $subscribed_phids;
$phids = array_merge($email_to, $email_cc);
$handles = id(new PhabricatorObjectHandleData($phids))
->setViewer($this->requireActor())
->loadHandles();
$mock_id = $mock->getID();
$name = $mock->getName();
$original_name = $mock->getOriginalName();
$thread_id = 'pholio-mock-'.$mock->getPHID();
$mail_tags = $this->getMailTags($mock, $xactions);
$body = new PhabricatorMetaMTAMailBody();
$body->addRawSection('lorem ipsum');
$mock_uri = PhabricatorEnv::getProductionURI('/M'.$mock->getID());
$body->addTextSection(pht('MOCK DETAIL'), $mock_uri);
$reply_handler = $this->buildReplyHandler($mock);
$template = id(new PhabricatorMetaMTAMail())
->setSubject("M{$mock_id}: {$name}")
->setSubjectPrefix($this->getMailSubjectPrefix())
->setVarySubjectPrefix('[edit/create?]')
->setFrom($this->requireActor()->getPHID())
->addHeader('Thread-Topic', "M{$mock_id}: {$original_name}")
->setThreadID($thread_id, $is_new)
->setRelatedPHID($mock->getPHID())
->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs())
->setIsBulk(true)
->setMailTags($mail_tags)
->setBody($body->render());
// TODO
// ->setParentMessageID(...)
$mails = $reply_handler->multiplexMail(
$template,
array_select_keys($handles, $email_to),
array_select_keys($handles, $email_cc));
foreach ($mails as $mail) {
$mail->saveAndSend();
}
$template->addTos($email_to);
$template->addCCs($email_cc);
return $template;
}
private function getMailTags(PholioMock $mock, array $xactions) {
assert_instances_of($xactions, 'PholioTransaction');
$tags = array();
return $tags;
}
public function buildReplyHandler(PholioMock $mock) {
$handler_object = new PholioReplyHandler();
$handler_object->setMailReceiver($mock);
return $handler_object;
}
private function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix');
}
private function applyTransaction(
PholioMock $mock,
PholioTransaction $xaction) {
@ -155,6 +249,9 @@ final class PholioMockEditor extends PhabricatorEditor {
break;
case PholioTransactionType::TYPE_NAME:
$mock->setName($xaction->getNewValue());
if ($mock->getOriginalName() === null) {
$mock->setOriginalName($xaction->getNewValue());
}
break;
case PholioTransactionType::TYPE_DESCRIPTION:
$mock->setDescription($xaction->getNewValue());

View file

@ -0,0 +1,59 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @group pholio
*/
final class PholioReplyHandler extends PhabricatorMailReplyHandler {
public function validateMailReceiver($mail_receiver) {
if (!($mail_receiver instanceof PholioMock)) {
throw new Exception("Mail receiver is not a PholioMock!");
}
}
public function getPrivateReplyHandlerEmailAddress(
PhabricatorObjectHandle $handle) {
return $this->getDefaultPrivateReplyHandlerEmailAddress($handle, 'M');
}
public function getPublicReplyHandlerEmailAddress() {
return $this->getDefaultPublicReplyHandlerEmailAddress('M');
}
public function getReplyHandlerDomain() {
return PhabricatorEnv::getEnvConfig(
'metamta.pholio.reply-handler-domain');
}
public function getReplyHandlerInstructions() {
if ($this->supportsReplies()) {
// TODO: Implement.
return null;
return "Reply to comment.";
} else {
return null;
}
}
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) {
// TODO: Implement this.
return null;
}
}