1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 09:18:48 +02:00

Conpherence - reply handler integration

Summary: Added a reply handler. A few problems -- first, I can't seem to get this to actually send me email so I haven't been able to reply (which I would have done by generating a reply, then copying the raw email into scripts/mail_handler.php). Second, the subject is often terrible on these emails -- unless the conpherence is named its something gross like "E4:" Third, on create I am noticing an error on array_combine() which I think is related to the need to write array_combine_not_broken or what have you I saw go by... (PhabricatorTransactionEditor does array_combine(xaction->getOldValue(), xaction->getOldValue()) and complains that the arrays are empty)

Test Plan: noted that /mail/ said mails were being sent

Reviewers: epriestley

Reviewed By: epriestley

CC: chad, aran, Korvin

Maniphest Tasks: T2399

Differential Revision: https://secure.phabricator.com/D4656
This commit is contained in:
Bob Trahan 2013-01-25 16:03:54 -08:00
parent e344f57df1
commit 4d22c9104f
9 changed files with 151 additions and 16 deletions

View file

@ -195,6 +195,7 @@ phutil_register_library_map(array(
'ConduitCallTestCase' => 'applications/conduit/call/__tests__/ConduitCallTestCase.php', 'ConduitCallTestCase' => 'applications/conduit/call/__tests__/ConduitCallTestCase.php',
'ConduitException' => 'applications/conduit/protocol/ConduitException.php', 'ConduitException' => 'applications/conduit/protocol/ConduitException.php',
'ConduitSSHWorkflow' => 'applications/conduit/ssh/ConduitSSHWorkflow.php', 'ConduitSSHWorkflow' => 'applications/conduit/ssh/ConduitSSHWorkflow.php',
'ConpherenceConfigOptions' => 'applications/conpherence/config/ConpherenceConfigOptions.php',
'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php', 'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php',
'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php', 'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php',
'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php', 'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php',
@ -205,6 +206,7 @@ phutil_register_library_map(array(
'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php',
'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php', 'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php',
'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php', 'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php',
'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php',
'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php', 'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php',
'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php',
'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php', 'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php',
@ -1666,6 +1668,7 @@ phutil_register_library_map(array(
'ConduitCallTestCase' => 'PhabricatorTestCase', 'ConduitCallTestCase' => 'PhabricatorTestCase',
'ConduitException' => 'Exception', 'ConduitException' => 'Exception',
'ConduitSSHWorkflow' => 'PhabricatorSSHWorkflow', 'ConduitSSHWorkflow' => 'PhabricatorSSHWorkflow',
'ConpherenceConfigOptions' => 'PhabricatorApplicationConfigOptions',
'ConpherenceController' => 'PhabricatorController', 'ConpherenceController' => 'PhabricatorController',
'ConpherenceDAO' => 'PhabricatorLiskDAO', 'ConpherenceDAO' => 'PhabricatorLiskDAO',
'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor',
@ -1675,6 +1678,7 @@ phutil_register_library_map(array(
'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipant' => 'ConpherenceDAO',
'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipationStatus' => 'ConpherenceConstants', 'ConpherenceParticipationStatus' => 'ConpherenceConstants',
'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler',
'ConpherenceThread' => 'ConpherenceThread' =>
array( array(
0 => 'ConpherenceDAO', 0 => 'ConpherenceDAO',

View file

@ -235,6 +235,13 @@ EODOC
pht( pht(
'Controls whether Phabricator sends email "From" users.')) 'Controls whether Phabricator sends email "From" users.'))
->setDescription($send_as_user_desc), ->setDescription($send_as_user_desc),
$this->newOption(
'metamta.reply-handler-domain',
'string',
'phabricator.example.com')
->setDescription(pht(
'Domain used for reply email addresses. Some applications can '.
'configure this domain.')),
$this->newOption('metamta.reply.show-hints', 'bool', true) $this->newOption('metamta.reply.show-hints', 'bool', true)
->setBoolOptions( ->setBoolOptions(
array( array(

View file

@ -0,0 +1,24 @@
<?php
final class ConpherenceConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Copherence');
}
public function getDescription() {
return pht('Configure Conpherence messaging.');
}
public function getOptions() {
return array(
$this->newOption(
'metamta.conpherence.subject-prefix',
'string',
'[Conpherence]')
->setDescription(pht('Subject prefix for Conpherence mail.')),
);
}
}

View file

@ -60,6 +60,11 @@ final class ConpherenceNewController extends ConpherenceController {
$xactions[] = id(new ConpherenceTransaction()) $xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) ->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS)
->setNewValue(array('+' => $participants)); ->setNewValue(array('+' => $participants));
if ($files) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransactionType::TYPE_FILES)
->setNewValue(array('+' => mpull($files, 'getPHID')));
}
$xactions[] = id(new ConpherenceTransaction()) $xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment( ->attachComment(
@ -67,11 +72,6 @@ final class ConpherenceNewController extends ConpherenceController {
->setContent($message) ->setContent($message)
->setConpherencePHID($conpherence->getPHID()) ->setConpherencePHID($conpherence->getPHID())
); );
if ($files) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransactionType::TYPE_FILES)
->setNewValue(array('+' => mpull($files, 'getPHID')));
}
$content_source = PhabricatorContentSource::newForSource( $content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB, PhabricatorContentSource::SOURCE_WEB,
array( array(

View file

@ -120,33 +120,40 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
} }
protected function supportsMail() { protected function supportsMail() {
return false; return true;
} }
/* TODO
protected function buildReplyHandler(PhabricatorLiskDAO $object) { protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new ConpherenceReplyHandler()) return id(new ConpherenceReplyHandler())
->setActor($this->getActor())
->setMailReceiver($object); ->setMailReceiver($object);
} }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID(); $id = $object->getID();
$title = $object->getTitle(); $title = $object->getTitle();
if (!$title) {
$title = pht(
'%s sent you a message.',
$this->getActor()->getUserName()
);
}
$phid = $object->getPHID(); $phid = $object->getPHID();
$original_name = $object->getOriginalName();
return id(new PhabricatorMetaMTAMail()) return id(new PhabricatorMetaMTAMail())
->setSubject("C{$id}: {$title}") ->setSubject("E{$id}: {$title}")
->addHeader('Thread-Topic', "C{$id}: {$phid}"); ->addHeader('Thread-Topic', "E{$id}: {$phid}");
} }
protected function getMailTo(PhabricatorLiskDAO $object) { protected function getMailTo(PhabricatorLiskDAO $object) {
$participants = $object->getParticipants(); $participants = $object->getParticipants();
$participants[$this->requireActor()->getPHID()] = true;
return array_keys($participants); return array_keys($participants);
} }
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
protected function buildMailBody( protected function buildMailBody(
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
array $xactions) { array $xactions) {
@ -162,7 +169,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.conpherence.subject-prefix'); return PhabricatorEnv::getEnvConfig('metamta.conpherence.subject-prefix');
} }
*/
protected function supportsFeed() { protected function supportsFeed() {
return false; return false;

View file

@ -0,0 +1,69 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceReplyHandler extends PhabricatorMailReplyHandler {
public function validateMailReceiver($mail_receiver) {
if (!($mail_receiver instanceof ConpherenceThread)) {
throw new Exception("Mail receiver is not a ConpherenceThread!");
}
}
public function getPrivateReplyHandlerEmailAddress(
PhabricatorObjectHandle $handle) {
return $this->getDefaultPrivateReplyHandlerEmailAddress($handle, 'E');
}
public function getPublicReplyHandlerEmailAddress() {
return $this->getDefaultPublicReplyHandlerEmailAddress('E');
}
public function getReplyHandlerInstructions() {
if ($this->supportsReplies()) {
return pht('Reply to comment and attach files.');
} else {
return null;
}
}
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) {
$conpherence = $this->getMailReceiver();
$user = $this->getActor();
$body = $mail->getCleanTextBody();
$body = trim($body);
$file_phids = $mail->getAttachments();
$body = $this->enhanceBodyWithAttachments($body, $file_phids);
$xactions = array();
if ($file_phids) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransactionType::TYPE_FILES)
->setNewValue(array('+' => $file_phids));
}
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new ConpherenceTransactionComment())
->setContent($body)
->setConpherencePHID($conpherence->getPHID())
);
$content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_EMAIL,
array(
'id' => $mail->getID(),
));
$editor = id(new ConpherenceEditor())
->setActor($user)
->setContentSource($content_source)
->setParentMessageID($mail->getMessageID())
->applyTransactions($conpherence, $xactions);
return null;
}
}

View file

@ -37,7 +37,11 @@ abstract class PhabricatorMailReplyHandler {
abstract public function validateMailReceiver($mail_receiver); abstract public function validateMailReceiver($mail_receiver);
abstract public function getPrivateReplyHandlerEmailAddress( abstract public function getPrivateReplyHandlerEmailAddress(
PhabricatorObjectHandle $handle); PhabricatorObjectHandle $handle);
abstract public function getReplyHandlerDomain(); public function getReplyHandlerDomain() {
return PhabricatorEnv::getEnvConfig(
'metamta.reply-handler-domain'
);
}
abstract public function getReplyHandlerInstructions(); abstract public function getReplyHandlerInstructions();
abstract protected function receiveEmail( abstract protected function receiveEmail(
PhabricatorMetaMTAReceivedMail $mail); PhabricatorMetaMTAReceivedMail $mail);

View file

@ -289,6 +289,10 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO {
} else if ($receiver instanceof PhabricatorRepositoryCommit) { } else if ($receiver instanceof PhabricatorRepositoryCommit) {
$handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit( $handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit(
$receiver); $receiver);
} else if ($receiver instanceof ConpherenceThread) {
$handler = id(new ConpherenceEditor())
->setActor($user)
->buildReplyHandler($receiver);
} }
$handler->setActor($user); $handler->setActor($user);
@ -331,6 +335,9 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO {
case 'C': case 'C':
$class_obj = new PhabricatorRepositoryCommit(); $class_obj = new PhabricatorRepositoryCommit();
break; break;
case 'E':
$class_obj = new ConpherenceThread();
break;
default: default:
return null; return null;
} }

View file

@ -15,6 +15,7 @@ abstract class PhabricatorApplicationTransactionEditor
private $isNewObject; private $isNewObject;
private $mentionedPHIDs; private $mentionedPHIDs;
private $continueOnNoEffect; private $continueOnNoEffect;
private $parentMessageID;
private $isPreview; private $isPreview;
@ -40,6 +41,18 @@ abstract class PhabricatorApplicationTransactionEditor
return $this->continueOnNoEffect; return $this->continueOnNoEffect;
} }
/**
* Not strictly necessary, but reply handlers ideally set this value to
* make email threading work better.
*/
public function setParentMessageID($parent_message_id) {
$this->parentMessageID = $parent_message_id;
return $this;
}
public function getParentMessageID() {
return $this->parentMessageID;
}
protected function getIsNewObject() { protected function getIsNewObject() {
return $this->isNewObject; return $this->isNewObject;
} }
@ -669,8 +682,9 @@ abstract class PhabricatorApplicationTransactionEditor
->setIsBulk(true) ->setIsBulk(true)
->setBody($body->render()); ->setBody($body->render());
// TODO if ($this->getParentMessageID()) {
// ->setParentMessageID(...) $template->setParentMessageID($this->getParentMessageID());
}
$mails = $this $mails = $this
->buildReplyHandler($object) ->buildReplyHandler($object)