Page MenuHomestyx hydra

No OneTemporary

diff --git a/scripts/mail/mail_handler.php b/scripts/mail/mail_handler.php
index 19e315364d..11d8f1c29f 100755
--- a/scripts/mail/mail_handler.php
+++ b/scripts/mail/mail_handler.php
@@ -1,67 +1,96 @@
#!/usr/bin/env php
<?php
+// NOTE: This script is very oldschool and takes the environment as an argument.
+// Some day, we could take a shot at cleaning this up.
if ($argc > 1) {
- $_SERVER['PHABRICATOR_ENV'] = $argv[1];
+ foreach (array_slice($argv, 1) as $arg) {
+ if (!preg_match('/^-/', $arg)) {
+ $_SERVER['PHABRICATOR_ENV'] = $arg;
+ break;
+ }
+ }
}
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
require_once $root.'/externals/mimemailparser/MimeMailParser.class.php';
+$args = new PhutilArgumentParser($argv);
+$args->parseStandardArguments();
+$args->parse(
+ array(
+ array(
+ 'name' => 'process-duplicates',
+ 'help' => pht(
+ "Process this message, even if it's a duplicate of another message. ".
+ "This is mostly useful when debugging issues with mail routing."),
+ ),
+ array(
+ 'name' => 'env',
+ 'wildcard' => true,
+ ),
+ ));
+
$parser = new MimeMailParser();
$parser->setText(file_get_contents('php://stdin'));
$text_body = $parser->getMessageBody('text');
$text_body_headers = $parser->getMessageBodyHeaders('text');
$content_type = idx($text_body_headers, 'content-type');
if (
!phutil_is_utf8($text_body) &&
(preg_match('/charset="(.*?)"/', $content_type, $matches) ||
preg_match('/charset=(\S+)/', $content_type, $matches))
) {
$text_body = phutil_utf8_convert($text_body, "UTF-8", $matches[1]);
}
$headers = $parser->getHeaders();
$headers['subject'] = iconv_mime_decode($headers['subject'], 0, "UTF-8");
$headers['from'] = iconv_mime_decode($headers['from'], 0, "UTF-8");
+if ($args->getArg('process-duplicates')) {
+ $headers['message-id'] = Filesystem::readRandomCharacters(64);
+}
+
$received = new PhabricatorMetaMTAReceivedMail();
$received->setHeaders($headers);
$received->setBodies(array(
'text' => $text_body,
'html' => $parser->getMessageBody('html'),
));
$attachments = array();
foreach ($parser->getAttachments() as $attachment) {
if (preg_match('@text/(plain|html)@', $attachment->getContentType()) &&
$attachment->getContentDisposition() == 'inline') {
// If this is an "inline" attachment with some sort of text content-type,
// do not treat it as a file for attachment. MimeMailParser already picked
// it up in the getMessageBody() call above. We still want to treat 'inline'
// attachments with other content types (e.g., images) as attachments.
continue;
}
$file = PhabricatorFile::newFromFileData(
$attachment->getContent(),
array(
'name' => $attachment->getFilename(),
));
$attachments[] = $file->getPHID();
}
try {
$received->setAttachments($attachments);
$received->save();
$received->processReceivedMail();
} catch (Exception $e) {
$received
->setMessage('EXCEPTION: '.$e->getMessage())
->save();
+
+ throw $e;
}
diff --git a/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php b/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php
index 6e2fa8cd71..aba7adc756 100644
--- a/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php
+++ b/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php
@@ -1,65 +1,67 @@
<?php
final class ConpherenceCreateThreadMailReceiver
extends PhabricatorMailReceiver {
public function isEnabled() {
$app_class = 'PhabricatorApplicationConpherence';
return PhabricatorApplication::isClassInstalled($app_class);
}
public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail) {
$usernames = $this->getMailUsernames($mail);
if (!$usernames) {
return false;
}
$users = $this->loadMailUsers($mail);
if (count($users) != count($usernames)) {
// At least some of the addresses are not users, so don't accept this as
// a new Conpherence thread.
return false;
}
return true;
}
private function getMailUsernames(PhabricatorMetaMTAReceivedMail $mail) {
$usernames = array();
foreach ($mail->getToAddresses() as $to_address) {
$address = self::stripMailboxPrefix($to_address);
$usernames[] = id(new PhutilEmailAddress($address))->getLocalPart();
}
return array_unique($usernames);
}
private function loadMailUsers(PhabricatorMetaMTAReceivedMail $mail) {
$usernames = $this->getMailUsernames($mail);
if (!$usernames) {
return array();
}
return id(new PhabricatorUser())->loadAllWhere(
'username in (%Ls)',
$usernames);
}
protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
$users = $this->loadMailUsers($mail);
$phids = mpull($users, 'getPHID');
$conpherence = id(new ConpherenceReplyHandler())
- ->setMailReceiver(new ConpherenceThread())
+ ->setMailReceiver(ConpherenceThread::initializeNewThread($sender))
->setMailAddedParticipantPHIDs($phids)
->setActor($sender)
->setExcludeMailRecipientPHIDs($mail->loadExcludeMailRecipientPHIDs())
->processEmail($mail);
- $mail->setRelatedPHID($conpherence->getPHID());
+ if ($conpherence) {
+ $mail->setRelatedPHID($conpherence->getPHID());
+ }
}
}
diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php
index 3e632fec27..0622f9fa9f 100644
--- a/src/applications/conpherence/storage/ConpherenceThread.php
+++ b/src/applications/conpherence/storage/ConpherenceThread.php
@@ -1,194 +1,200 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceThread extends ConpherenceDAO
implements PhabricatorPolicyInterface {
protected $title;
protected $messageCount;
protected $recentParticipantPHIDs = array();
protected $mailKey;
private $participants = self::ATTACHABLE;
private $transactions = self::ATTACHABLE;
private $handles = self::ATTACHABLE;
private $filePHIDs = self::ATTACHABLE;
private $widgetData = self::ATTACHABLE;
private $images = array();
+ public function initializeNewThread(PhabricatorUser $sender) {
+ return id(new ConpherenceThread())
+ ->setMessageCount(0)
+ ->setTitle('');
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'recentParticipantPHIDs' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorConpherencePHIDTypeThread::TYPECONST);
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function attachParticipants(array $participants) {
assert_instances_of($participants, 'ConpherenceParticipant');
$this->participants = $participants;
return $this;
}
public function getParticipants() {
return $this->assertAttached($this->participants);
}
public function getParticipant($phid) {
$participants = $this->getParticipants();
return $participants[$phid];
}
public function getParticipantPHIDs() {
$participants = $this->getParticipants();
return array_keys($participants);
}
public function attachHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function getHandles() {
return $this->assertAttached($this->handles);
}
public function attachTransactions(array $transactions) {
assert_instances_of($transactions, 'ConpherenceTransaction');
$this->transactions = $transactions;
return $this;
}
public function getTransactions() {
return $this->assertAttached($this->transactions);
}
public function getTransactionsFrom($begin = 0, $amount = null) {
$length = count($this->transactions);
return array_slice(
$this->getTransactions(),
$length - $begin - $amount,
$amount);
}
public function attachFilePHIDs(array $file_phids) {
$this->filePHIDs = $file_phids;
return $this;
}
public function getFilePHIDs() {
return $this->assertAttached($this->filePHIDs);
}
public function attachWidgetData(array $widget_data) {
$this->widgetData = $widget_data;
return $this;
}
public function getWidgetData() {
return $this->assertAttached($this->widgetData);
}
public function getDisplayData(PhabricatorUser $user) {
$recent_phids = $this->getRecentParticipantPHIDs();
$handles = $this->getHandles();
// luck has little to do with it really; most recent participant who isn't
// the user....
$lucky_phid = null;
$lucky_index = null;
foreach ($recent_phids as $index => $phid) {
if ($phid == $user->getPHID()) {
continue;
}
$lucky_phid = $phid;
break;
}
reset($recent_phids);
if ($lucky_phid) {
$lucky_handle = $handles[$lucky_phid];
// this will be just the user talking to themselves. weirdos.
} else {
$lucky_handle = reset($handles);
}
$title = $js_title = $this->getTitle();
if (!$title) {
$title = $lucky_handle->getName();
$js_title = pht('[No Title]');
}
$img_src = $lucky_handle->getImageURI();
$count = 0;
$final = false;
$subtitle = null;
foreach ($recent_phids as $phid) {
if ($phid == $user->getPHID()) {
continue;
}
$handle = $handles[$phid];
if ($subtitle) {
if ($final) {
$subtitle .= '...';
break;
} else {
$subtitle .= ', ';
}
}
$subtitle .= $handle->getName();
$count++;
$final = $count == 3;
}
$participants = $this->getParticipants();
$user_participation = $participants[$user->getPHID()];
$unread_count = $this->getMessageCount() -
$user_participation->getSeenMessageCount();
return array(
'title' => $title,
'js_title' => $js_title,
'subtitle' => $subtitle,
'unread_count' => $unread_count,
'epoch' => $this->getDateModified(),
'image' => $img_src,
);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
return PhabricatorPolicies::POLICY_NOONE;
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
// this bad boy isn't even created yet so go nuts $user
if (!$this->getID()) {
return true;
}
$participants = $this->getParticipants();
return isset($participants[$user->getPHID()]);
}
public function describeAutomaticCapability($capability) {
return pht("Participants in a thread can always view and edit it.");
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Dec 3, 3:17 PM (1 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
433663
Default Alt Text
(11 KB)

Event Timeline