Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14082187
D11418.id27480.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
30 KB
Referenced Files
None
Subscribers
None
D11418.id27480.diff
View Options
diff --git a/resources/sql/autopatches/20150115.applicationemails.sql b/resources/sql/autopatches/20150115.applicationemails.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150115.applicationemails.sql
@@ -0,0 +1,12 @@
+CREATE TABLE {$NAMESPACE}_metamta.metamta_applicationemail (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ applicationPHID VARBINARY(64) NOT NULL,
+ address VARCHAR(128) NOT NULL COLLATE {$COLLATE_SORT},
+ configData LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ KEY `key_application` (applicationPHID),
+ UNIQUE KEY `key_address` (address),
+ UNIQUE KEY `key_phid` (phid)
+) ENGINE=MyISAM DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20150116.maniphestapplicationemails.php b/resources/sql/autopatches/20150116.maniphestapplicationemails.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150116.maniphestapplicationemails.php
@@ -0,0 +1,20 @@
+<?php
+
+$key = 'metamta.maniphest.public-create-email';
+echo "Migrating `$key` to new application email infrastructure...\n";
+$value = PhabricatorEnv::getEnvConfigIfExists($key);
+$maniphest = new PhabricatorManiphestApplication();
+
+if ($value) {
+ try {
+ PhabricatorMetaMTAApplicationEmail::initializeNewAppEmail(
+ PhabricatorUser::getOmnipotentUser())
+ ->setAddress($value)
+ ->setApplicationPHID($maniphest->getPHID())
+ ->save();
+ } catch (AphrontDuplicateKeyQueryException $ex) {
+ // already migrated?
+ }
+}
+
+echo "Done.\n";
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1258,6 +1258,7 @@
'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php',
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
+ 'PhabricatorApplicationEditEmailController' => 'applications/meta/controller/PhabricatorApplicationEditEmailController.php',
'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php',
'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php',
'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php',
@@ -1945,6 +1946,9 @@
'PhabricatorMetaMTAActor' => 'applications/metamta/query/PhabricatorMetaMTAActor.php',
'PhabricatorMetaMTAActorQuery' => 'applications/metamta/query/PhabricatorMetaMTAActorQuery.php',
'PhabricatorMetaMTAApplication' => 'applications/metamta/application/PhabricatorMetaMTAApplication.php',
+ 'PhabricatorMetaMTAApplicationEmail' => 'applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php',
+ 'PhabricatorMetaMTAApplicationEmailPHIDType' => 'applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php',
+ 'PhabricatorMetaMTAApplicationEmailQuery' => 'applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php',
'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/PhabricatorMetaMTAAttachment.php',
'PhabricatorMetaMTAConfigOptions' => 'applications/config/option/PhabricatorMetaMTAConfigOptions.php',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/PhabricatorMetaMTAController.php',
@@ -4418,6 +4422,7 @@
'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
+ 'PhabricatorApplicationEditEmailController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationLaunchView' => 'AphrontTagView',
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController',
@@ -5142,6 +5147,12 @@
'PhabricatorMercurialGraphStream' => 'PhabricatorRepositoryGraphStream',
'PhabricatorMetaMTAActorQuery' => 'PhabricatorQuery',
'PhabricatorMetaMTAApplication' => 'PhabricatorApplication',
+ 'PhabricatorMetaMTAApplicationEmail' => array(
+ 'PhabricatorMetaMTADAO',
+ 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorMetaMTAApplicationEmailPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorMetaMTAApplicationEmailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php
--- a/src/applications/base/PhabricatorApplication.php
+++ b/src/applications/base/PhabricatorApplication.php
@@ -4,6 +4,7 @@
* @task info Application Information
* @task ui UI Integration
* @task uri URI Routing
+ * @task mail Email integration
* @task fact Fact Integration
* @task meta Application Management
*/
@@ -193,6 +194,22 @@
}
+/* -( Email Integration )-------------------------------------------------- */
+
+
+ public function supportsEmailIntegration() {
+ return false;
+ }
+
+ protected function getInboundEmailSupportLink() {
+ return PhabricatorEnv::getDocLink('Configuring Inbound Email');
+ }
+
+ public function getAppEmailBlurb() {
+ throw new Exception('Not Implemented.');
+ }
+
+
/* -( Fact Integration )--------------------------------------------------- */
diff --git a/src/applications/maniphest/application/PhabricatorManiphestApplication.php b/src/applications/maniphest/application/PhabricatorManiphestApplication.php
--- a/src/applications/maniphest/application/PhabricatorManiphestApplication.php
+++ b/src/applications/maniphest/application/PhabricatorManiphestApplication.php
@@ -109,6 +109,20 @@
return $items;
}
+ public function supportsEmailIntegration() {
+ return true;
+ }
+
+ public function getAppEmailBlurb() {
+ return pht(
+ 'Send email to these addresses to create tasks. %s',
+ phutil_tag(
+ 'a',
+ array(
+ 'href' => $this->getInboundEmailSupportLink(),),
+ pht('Learn More')));
+ }
+
protected function getCustomCapabilities() {
return array(
ManiphestDefaultViewCapability::CAPABILITY => array(
diff --git a/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php b/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
--- a/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
+++ b/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
@@ -294,9 +294,16 @@
'metamta.maniphest.public-create-email',
'string',
null)
- ->setSummary(pht('Allow filing bugs via email.'))
+ ->setLocked(true)
+ ->setLockedMessage(pht(
+ 'This configuration is deprecated. See description for details.'))
+ ->setSummary(pht('DEPRECATED - Allow filing bugs via email.'))
->setDescription(
pht(
+ 'This config has been deprecated in favor of [[ '.
+ '/applications/view/PhabricatorManiphestApplication/ | '.
+ 'application settings ]], which allow for multiple email '.
+ 'addresses and other functionality.'."\n\n".
'You can configure an email address like '.
'"bugs@phabricator.example.com" which will automatically create '.
'Maniphest tasks when users send email to it. This relies on the '.
diff --git a/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php b/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
--- a/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
+++ b/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
@@ -8,12 +8,18 @@
}
public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail) {
- $config_key = 'metamta.maniphest.public-create-email';
- $create_address = PhabricatorEnv::getEnvConfig($config_key);
+ $maniphest_app = new PhabricatorManiphestApplication();
+ $application_emails = id(new PhabricatorMetaMTAApplicationEmailQuery())
+ ->setViewer($this->getViewer())
+ ->withApplicationPHIDs(array($maniphest_app->getPHID()))
+ ->execute();
foreach ($mail->getToAddresses() as $to_address) {
- if ($this->matchAddresses($create_address, $to_address)) {
- return true;
+ foreach ($application_emails as $application_email) {
+ $create_address = $application_email->getAddress();
+ if ($this->matchAddresses($create_address, $to_address)) {
+ return true;
+ }
}
}
diff --git a/src/applications/meta/application/PhabricatorApplicationsApplication.php b/src/applications/meta/application/PhabricatorApplicationsApplication.php
--- a/src/applications/meta/application/PhabricatorApplicationsApplication.php
+++ b/src/applications/meta/application/PhabricatorApplicationsApplication.php
@@ -41,6 +41,8 @@
=> 'PhabricatorApplicationDetailViewController',
'edit/(?P<application>\w+)/'
=> 'PhabricatorApplicationEditController',
+ 'editemail/(?P<application>\w+)/'
+ => 'PhabricatorApplicationEditEmailController',
'(?P<application>\w+)/(?P<action>install|uninstall)/'
=> 'PhabricatorApplicationUninstallController',
),
diff --git a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php
--- a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php
+++ b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php
@@ -3,23 +3,18 @@
final class PhabricatorApplicationDetailViewController
extends PhabricatorApplicationsController {
- private $application;
public function shouldAllowPublic() {
return true;
}
- public function willProcessRequest(array $data) {
- $this->application = $data['application'];
- }
-
- public function processRequest() {
- $request = $this->getRequest();
+ public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
+ $application = $request->getURIData('application');
$selected = id(new PhabricatorApplicationQuery())
->setViewer($user)
- ->withClasses(array($this->application))
+ ->withClasses(array($application))
->executeOne();
if (!$selected) {
return new Aphront404Response();
@@ -119,6 +114,26 @@
idx($descriptions, $capability));
}
+ if ($application->supportsEmailIntegration()) {
+ $properties->addSectionHeader(pht('Application Emails'));
+ $properties->addTextContent($application->getAppEmailBlurb());
+ $email_addresses = id(new PhabricatorMetaMTAApplicationEmailQuery())
+ ->setViewer($viewer)
+ ->withApplicationPHIDs(array($application->getPHID()))
+ ->execute();
+ if (empty($email_addresses)) {
+ $properties->addProperty(
+ null,
+ pht('No email addresses configured.'));
+ } else {
+ foreach ($email_addresses as $email_address) {
+ $properties->addProperty(
+ null,
+ $email_address->getAddress());
+ }
+ }
+ }
+
return $properties;
}
@@ -153,6 +168,18 @@
->setWorkflow(!$can_edit)
->setHref($edit_uri));
+ if ($selected->supportsEmailIntegration()) {
+ $edit_email_uri = $this->getApplicationURI(
+ 'editemail/'.get_class($selected).'/');
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Application Emails'))
+ ->setIcon('fa-envelope')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit)
+ ->setHref($edit_email_uri));
+ }
+
if ($selected->canUninstall()) {
if ($selected->isInstalled()) {
$view->addAction(
diff --git a/src/applications/meta/controller/PhabricatorApplicationEditEmailController.php b/src/applications/meta/controller/PhabricatorApplicationEditEmailController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/meta/controller/PhabricatorApplicationEditEmailController.php
@@ -0,0 +1,307 @@
+<?php
+
+final class PhabricatorApplicationEditEmailController
+ extends PhabricatorApplicationsController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getUser();
+ $application = $request->getURIData('application');
+
+ $application = id(new PhabricatorApplicationQuery())
+ ->setViewer($viewer)
+ ->withClasses(array($application))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$application) {
+ return new Aphront404Response();
+ }
+
+ $title = $application->getName();
+
+ $uri = $request->getRequestURI();
+ $uri->setQueryParams(array());
+
+ $new = $request->getStr('new');
+ $edit = $request->getInt('edit');
+ $delete = $request->getInt('delete');
+
+ if ($new) {
+ return $this->returnNewAddressResponse($request, $uri, $application);
+ }
+
+ if ($edit) {
+ return $this->returnEditAddressResponse($request, $uri, $edit);
+ }
+
+ if ($delete) {
+ return $this->returnDeleteAddressResponse($request, $uri, $delete);
+ }
+
+ $emails = id(new PhabricatorMetaMTAApplicationEmailQuery())
+ ->setViewer($viewer)
+ ->withApplicationPHIDs(array($application->getPHID()))
+ ->execute();
+
+ $highlight = $request->getInt('highlight');
+ $rowc = array();
+ $rows = array();
+ foreach ($emails as $email) {
+
+ $button_edit = javelin_tag(
+ 'a',
+ array(
+ 'class' => 'button small grey',
+ 'href' => $uri->alter('edit', $email->getID()),
+ 'sigil' => 'workflow',
+ ),
+ pht('Edit'));
+
+ $button_remove = javelin_tag(
+ 'a',
+ array(
+ 'class' => 'button small grey',
+ 'href' => $uri->alter('delete', $email->getID()),
+ 'sigil' => 'workflow',
+ ),
+ pht('Delete'));
+
+ if ($highlight == $email->getID()) {
+ $rowc[] = 'highlighted';
+ } else {
+ $rowc[] = null;
+ }
+
+ $rows[] = array(
+ $email->getAddress(),
+ $button_edit,
+ $button_remove,
+ );
+ }
+
+ $table = id(new AphrontTableView($rows))
+ ->setNoDataString(pht('No application emails created yet.'));
+ $table->setHeaders(
+ array(
+ pht('Email'),
+ pht('Edit'),
+ pht('Delete'),
+ ));
+ $table->setColumnClasses(
+ array(
+ 'wide',
+ 'action',
+ 'action',
+ ));
+ $table->setRowClasses($rowc);
+ $table->setColumnVisibility(
+ array(
+ true,
+ true,
+ true,
+ ));
+ $form = id(new AphrontFormView())
+ ->setUser($viewer);
+
+ $view_uri = $this->getApplicationURI('view/'.get_class($application).'/');
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb($application->getName(), $view_uri);
+ $crumbs->addTextCrumb(pht('Edit Application Emails'));
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(pht('Edit Application Emails: %s', $application->getName()));
+
+ $icon = id(new PHUIIconView())
+ ->setIconFont('fa-plus');
+ $button = new PHUIButtonView();
+ $button->setText(pht('Add New Address'));
+ $button->setTag('a');
+ $button->setHref($uri->alter('new', 'true'));
+ $button->setIcon($icon);
+ $button->addSigil('workflow');
+ $header->addActionLink($button);
+
+ $object_box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->appendChild($table)
+ ->appendChild(
+ id(new PHUIBoxView())
+ ->appendChild($application->getAppEmailBlurb())
+ ->addPadding(PHUI::PADDING_MEDIUM));
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $object_box,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+ private function validateApplicationEmail($email) {
+ $errors = array();
+ $e_email = true;
+
+ if (!strlen($email)) {
+ $e_email = pht('Required');
+ $errors[] = pht('Email is required.');
+ } else if (!PhabricatorUserEmail::isValidAddress($email)) {
+ $e_email = pht('Invalid');
+ $errors[] = PhabricatorUserEmail::describeValidAddresses();
+ } else if (!PhabricatorUserEmail::isAllowedAddress($email)) {
+ $e_email = pht('Disallowed');
+ $errors[] = PhabricatorUserEmail::describeAllowedAddresses();
+ }
+ $user_emails = id(new PhabricatorUserEmail())
+ ->loadAllWhere('address = %s', $email);
+ if ($user_emails) {
+ $e_email = pht('Duplicate');
+ $errors[] = pht('A user already has this email.');
+ }
+
+ return array($e_email, $errors);
+ }
+
+ private function returnNewAddressResponse(
+ AphrontRequest $request,
+ PhutilURI $uri,
+ PhabricatorApplication $application) {
+
+ $viewer = $request->getUser();
+ $email_object =
+ PhabricatorMetaMTAApplicationEmail::initializeNewAppEmail($viewer)
+ ->setApplicationPHID($application->getPHID());
+
+ return $this->returnSaveAddressResponse(
+ $request,
+ $uri,
+ $email_object,
+ $is_new = true);
+ }
+
+ private function returnEditAddressResponse(
+ AphrontRequest $request,
+ PhutilURI $uri,
+ $email_object_id) {
+
+ $viewer = $request->getUser();
+ $email_object = id(new PhabricatorMetaMTAApplicationEmailQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($email_object_id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$email_object) {
+ return new Aphront404Response();
+ }
+
+ return $this->returnSaveAddressResponse(
+ $request,
+ $uri,
+ $email_object,
+ $is_new = false);
+ }
+
+ private function returnSaveAddressResponse(
+ AphrontRequest $request,
+ PhutilURI $uri,
+ PhabricatorMetaMTAApplicationEmail $email_object,
+ $is_new) {
+
+ $viewer = $request->getUser();
+
+ $e_email = true;
+ $email = null;
+ $errors = array();
+ if ($request->isDialogFormPost()) {
+ $email = trim($request->getStr('email'));
+ list($e_email, $errors) = $this->validateApplicationEmail($email);
+ $email_object->setAddress($email);
+
+ if (!$errors) {
+ try {
+ $email_object->save();
+ return id(new AphrontRedirectResponse())->setURI(
+ $uri->alter('highlight', $email_object->getID()));
+ } catch (AphrontDuplicateKeyQueryException $ex) {
+ $e_email = pht('Duplicate');
+ $errors[] = pht(
+ 'Another application is already configured to use this email '.
+ 'address.');
+ }
+ }
+ }
+
+ if ($errors) {
+ $errors = id(new AphrontErrorView())
+ ->setErrors($errors);
+ }
+
+ $form = id(new PHUIFormLayoutView())
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('Email'))
+ ->setName('email')
+ ->setValue($email_object->getAddress())
+ ->setCaption(PhabricatorUserEmail::describeAllowedAddresses())
+ ->setError($e_email));
+
+ $dialog = id(new AphrontDialogView())
+ ->setUser($viewer)
+ ->setTitle(pht('New Address'))
+ ->appendChild($errors)
+ ->appendChild($form)
+ ->addSubmitButton(pht('Save'))
+ ->addCancelButton($uri);
+
+ if ($is_new) {
+ $dialog->addHiddenInput('new', 'true');
+ }
+
+ return id(new AphrontDialogResponse())->setDialog($dialog);
+ }
+
+ private function returnDeleteAddressResponse(
+ AphrontRequest $request,
+ PhutilURI $uri,
+ $email_object_id) {
+
+ $viewer = $request->getUser();
+ $email_object = id(new PhabricatorMetaMTAApplicationEmailQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($email_object_id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$email_object) {
+ return new Aphront404Response();
+ }
+
+ if ($request->isDialogFormPost()) {
+ $email_object->delete();
+ return id(new AphrontRedirectResponse())->setURI($uri);
+ }
+
+ $dialog = id(new AphrontDialogView())
+ ->setUser($viewer)
+ ->addHiddenInput('delete', $email_object_id)
+ ->setTitle(pht('Delete Address'))
+ ->appendParagraph(pht(
+ 'Are you sure you want to delete this email address?'))
+ ->addSubmitButton(pht('Delete'))
+ ->addCancelButton($uri);
+
+ return id(new AphrontDialogResponse())->setDialog($dialog);
+ }
+
+}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
@@ -0,0 +1,116 @@
+<?php
+
+final class PhabricatorMetaMTAApplicationEmailQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $addresses;
+ private $applicationPHIDs;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withAddresses(array $addresses) {
+ $this->addresses = $addresses;
+ return $this;
+ }
+
+ public function withApplicationPHIDs(array $phids) {
+ $this->applicationPHIDs = $phids;
+ return $this;
+ }
+
+ protected function loadPage() {
+ $table = new PhabricatorMetaMTAApplicationEmail();
+ $conn_r = $table->establishConnection('r');
+
+ $data = queryfx_all(
+ $conn_r,
+ 'SELECT * FROM %T appemail %Q %Q %Q %Q',
+ $table->getTableName(),
+ $this->buildWhereClause($conn_r),
+ $this->buildApplicationSearchGroupClause($conn_r),
+ $this->buildOrderClause($conn_r),
+ $this->buildLimitClause($conn_r));
+
+ return $table->loadAllFromArray($data);
+ }
+
+ protected function willFilterPage(array $app_emails) {
+ $app_emails_map = mgroup($app_emails, 'getApplicationPHID');
+ $applications = id(new PhabricatorApplicationQuery())
+ ->setViewer($this->getViewer())
+ ->withPHIDs(array_keys($app_emails_map))
+ ->execute();
+ $applications = mpull($applications, null, 'getPHID');
+
+ foreach ($app_emails_map as $app_phid => $app_emails_group) {
+ foreach ($app_emails_group as $app_email) {
+ $application = idx($applications, $app_phid);
+ if (!$application) {
+ unset($app_emails[$app_phid]);
+ continue;
+ }
+ $app_email->attachApplication($application);
+ }
+ }
+ return $app_emails;
+ }
+
+ private function buildWhereClause($conn_r) {
+ $where = array();
+
+ if ($this->addresses !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'appemail.address IN (%Ls)',
+ $this->addresses);
+ }
+
+ if ($this->applicationPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'appemail.applicationPHID IN (%Ls)',
+ $this->applicationPHIDs);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'appemail.phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'appemail.id IN (%Ld)',
+ $this->ids);
+ }
+
+ $where[] = $this->buildPagingClause($conn_r);
+
+ return $this->formatWhereClause($where);
+ }
+
+ protected function getPagingColumn() {
+ return 'appemail.id';
+ }
+
+ protected function getApplicationSearchObjectPHIDColumn() {
+ return 'appemail.phid';
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorMetaMTAApplication';
+ }
+
+}
diff --git a/src/applications/metamta/receiver/PhabricatorMailReceiver.php b/src/applications/metamta/receiver/PhabricatorMailReceiver.php
--- a/src/applications/metamta/receiver/PhabricatorMailReceiver.php
+++ b/src/applications/metamta/receiver/PhabricatorMailReceiver.php
@@ -15,6 +15,10 @@
$this->processReceivedMail($mail, $sender);
}
+ public function getViewer() {
+ return PhabricatorUser::getOmnipotentUser();
+ }
+
public function validateSender(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
@@ -103,7 +107,7 @@
if ($allow_email_users) {
$from_obj = new PhutilEmailAddress($from);
$xuser = id(new PhabricatorExternalAccountQuery())
- ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->setViewer($this->getViewer())
->withAccountTypes(array('email'))
->withAccountDomains(array($from_obj->getDomainName(), 'self'))
->withAccountIDs(array($from_obj->getAddress()))
diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php b/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php
new file mode 100644
--- /dev/null
+++ b/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php
@@ -0,0 +1,80 @@
+<?php
+
+final class PhabricatorMetaMTAApplicationEmail
+ extends PhabricatorMetaMTADAO
+ implements PhabricatorPolicyInterface {
+
+ protected $applicationPHID;
+ protected $address;
+ protected $configData;
+
+ private $application = self::ATTACHABLE;
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_SERIALIZATION => array(
+ 'configData' => self::SERIALIZATION_JSON,
+ ),
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'address' => 'sort128',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_address' => array(
+ 'columns' => array('address'),
+ 'unique' => true,
+ ),
+ 'key_application' => array(
+ 'columns' => array('applicationPHID'),
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function generatePHID() {
+ return PhabricatorPHID::generateNewPHID(
+ PhabricatorMetaMTAApplicationEmailPHIDType::TYPECONST);
+ }
+
+ public static function initializeNewAppEmail(PhabricatorUser $actor) {
+ return id(new PhabricatorMetaMTAApplicationEmail())
+ ->setConfigData(array());
+ }
+
+ public function attachApplication(PhabricatorApplication $app) {
+ $this->application = $app;
+ return $this;
+ }
+
+ public function getApplication() {
+ return self::assertAttached($this->application);
+ }
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ );
+ }
+
+ public function getPolicy($capability) {
+ return $this->getApplication()->getPolicy($capability);
+ }
+
+ public function hasAutomaticCapability(
+ $capability,
+ PhabricatorUser $viewer) {
+
+ return $this->getApplication()->hasAutomaticCapability(
+ $capability,
+ $viewer);
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return $this->getApplication()->describeAutomaticCapability($capability);
+ }
+
+}
diff --git a/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php b/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
--- a/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
+++ b/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
@@ -64,10 +64,9 @@
}
public function testDropUnknownSenderMail() {
+ $this->setManiphestCreateEmail();
+
$env = PhabricatorEnv::beginScopedEnv();
- $env->overrideEnvConfig(
- 'metamta.maniphest.public-create-email',
- 'bugs@example.com');
$env->overrideEnvConfig('phabricator.allow-email-users', false);
$env->overrideEnvConfig('metamta.maniphest.default-public-author', null);
@@ -89,10 +88,7 @@
public function testDropDisabledSenderMail() {
- $env = PhabricatorEnv::beginScopedEnv();
- $env->overrideEnvConfig(
- 'metamta.maniphest.public-create-email',
- 'bugs@example.com');
+ $this->setManiphestCreateEmail();
$user = $this->generateNewTestUser()
->setIsDisabled(true)
@@ -114,4 +110,15 @@
$mail->getStatus());
}
+ private function setManiphestCreateEmail() {
+ $maniphest_app = new PhabricatorManiphestApplication();
+ try {
+ id(new PhabricatorMetaMTAApplicationEmail())
+ ->setApplicationPHID($maniphest_app->getPHID())
+ ->setAddress('bugs@example.com')
+ ->setConfigData(array())
+ ->save();
+ } catch (AphrontDuplicateKeyQueryException $ex) {}
+ }
+
}
diff --git a/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
@@ -0,0 +1,44 @@
+<?php
+
+final class PhabricatorMetaMTAApplicationEmailPHIDType
+ extends PhabricatorPHIDType {
+
+ const TYPECONST = 'APPE';
+
+ public function getTypeName() {
+ return pht('Application Email');
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorMetaMTAApplication';
+ }
+
+ public function getTypeIcon() {
+ return 'fa-email bluegrey';
+ }
+
+ public function newObject() {
+ return new PhabricatorMetaMTAApplicationEmail();
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorMetaMTAApplicationEmailQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $email = $objects[$phid];
+
+ $handle->setName($email->getAddress());
+ $handle->setFullName($email->getAddress());
+ }
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 23, 11:04 PM (19 h, 24 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6780046
Default Alt Text
D11418.id27480.diff (30 KB)
Attached To
Mode
D11418: MetaMTA - add (basic) application emails and deploy to Maniphest
Attached
Detach File
Event Timeline
Log In to Comment