1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-09 16:32:39 +01:00
This commit is contained in:
epriestley 2011-01-25 17:40:21 -08:00
parent 74eb6d2bd5
commit bc57b12ef0
18 changed files with 676 additions and 8 deletions

View file

@ -17,7 +17,7 @@ celerity_register_resource_map(array(
),
'aphront-form-view-css' =>
array(
'path' => '/res/17285e65/rsrc/css/aphront/form-view.css',
'path' => '/res/51ec6383/rsrc/css/aphront/form-view.css',
'type' => 'css',
'requires' =>
array(
@ -25,7 +25,7 @@ celerity_register_resource_map(array(
),
'aphront-panel-view-css' =>
array(
'path' => '/res/d1ce0c3d/rsrc/css/aphront/panel-view.css',
'path' => '/res/fe62e634/rsrc/css/aphront/panel-view.css',
'type' => 'css',
'requires' =>
array(
@ -74,7 +74,7 @@ celerity_register_resource_map(array(
),
'differential-changeset-view-css' =>
array(
'path' => '/res/921d3a0c/rsrc/css/application/differential/changeset-view.css',
'path' => '/res/658d181a/rsrc/css/application/differential/changeset-view.css',
'type' => 'css',
'requires' =>
array(

View file

@ -19,6 +19,7 @@ phutil_register_library_map(array(
'AphrontDialogView' => 'view/dialog',
'AphrontErrorView' => 'view/form/error',
'AphrontFileResponse' => 'aphront/response/file',
'AphrontFormCheckboxControl' => 'view/form/control/checkbox',
'AphrontFormControl' => 'view/form/control/base',
'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormMarkupControl' => 'view/form/control/markup',
@ -111,6 +112,11 @@ phutil_register_library_map(array(
'PhabricatorFileUploadController' => 'applications/files/controller/upload',
'PhabricatorFileViewController' => 'applications/files/controller/view',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base',
'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list',
'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail',
'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send',
'PhabricatorPHID' => 'applications/phid/storage/phid',
'PhabricatorPHIDAllocateController' => 'applications/phid/controller/allocate',
'PhabricatorPHIDController' => 'applications/phid/controller/base',
@ -155,6 +161,7 @@ phutil_register_library_map(array(
'AphrontDialogView' => 'AphrontView',
'AphrontErrorView' => 'AphrontView',
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormMarkupControl' => 'AphrontFormControl',
@ -226,6 +233,11 @@ phutil_register_library_map(array(
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileViewController' => 'PhabricatorFileController',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController',
'PhabricatorPHID' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController',
'PhabricatorPHIDController' => 'PhabricatorController',

View file

@ -93,6 +93,12 @@ class AphrontDefaultApplicationConfiguration
'common/(?<type>\w+)/$'
=> 'PhabricatorTypeaheadCommonDatasourceController',
),
'/mail/' => array(
'$' => 'PhabricatorMetaMTAListController',
'send/$' => 'PhabricatorMetaMTASendController',
'view/(?<id>\d+)/$' => 'PhabricatorMetaMTAViewController',
)
);
}

View file

@ -63,7 +63,7 @@ class AphrontRequest {
}
}
final public function getArr($name, $default = null) {
final public function getArr($name, $default = array()) {
if (isset($this->requestData[$name]) &&
is_array($this->requestData[$name])) {
return $this->requestData[$name];

View file

@ -0,0 +1,34 @@
<?php
/*
* Copyright 2011 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.
*/
abstract class PhabricatorMetaMTAController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = new PhabricatorStandardPageView();
$page->setApplicationName('MetaMTA');
$page->setBaseURI('/mail/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("@");
$page->appendChild($view);
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/webpage');
phutil_require_module('phabricator', 'applications/base/controller/base');
phutil_require_module('phabricator', 'view/page/standard');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorMetaMTAController.php');

View file

@ -0,0 +1,53 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorMetaMTAListController extends PhabricatorMetaMTAController {
public function processRequest() {
$mails = id(new PhabricatorMetaMTAMail())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT 100');
$rows = array();
foreach ($mails as $mail) {
$rows[] = array(
$mail->getID(),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'ID',
));
$table->setColumnClasses(
array(
null,
));
$panel = new AphrontPanelView();
$panel->appendChild($table);
$panel->setHeader('MetaMTA Messages');
$panel->setCreateButton('Send New Message', '/mail/send/');
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'MetaMTA',
));
}
}

View file

@ -0,0 +1,17 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/metamta/controller/base');
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorMetaMTAListController.php');

View file

@ -0,0 +1,145 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorMetaMTASendController extends PhabricatorMetaMTAController {
public function processRequest() {
$request = $this->getRequest();
if ($request->isFormPost()) {
$mail = new PhabricatorMetaMTAMail();
$mail->addTos($request->getArr('to'));
$mail->addCCs($request->getArr('cc'));
$mail->setSubject($request->getStr('subject'));
$mail->setBody($request->getStr('body'));
// TODO!
// $mail->setFrom($request->getViewerContext()->getUserID());
$mail->setSimulatedFailureCount($request->getInt('failures'));
$mail->setIsHTML($request->getInt('html'));
$mail->save();
if ($request->getInt('immediately')) {
$mail->sendNow($force_send = true);
}
return id(new AphrontRedirectResponse())
->setURI('/mail/view/'.$mail->getID().'/');
}
$failure_caption =
"Enter a number to simulate that many consecutive send failures before ".
"really attempting to deliver via the underlying MTA.";
$form = new AphrontFormView();
$form->setAction('/mail/send/');
$form
->appendChild(
'<p class="aphront-form-instructions">This form will send a normal '.
'email using MetaMTA as a transport mechanism.</p>')
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel('To')
->setName('to')
->setDatasource('/typeahead/common/user/'))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel('CC')
->setName('cc')
->setDatasource('/typeahead/common/user/'))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Subject')
->setName('subject'))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Body')
->setName('body'))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Simulate Failures')
->setName('failures')
->setCaption($failure_caption))
->appendChild(
id(new AphrontFormCheckboxControl())
->setLabel('HTML')
->addCheckbox('html', '1', 'Send as HTML email.'))
->appendChild(
id(new AphrontFormCheckboxControl())
->setLabel('Send Now')
->addCheckbox(
'immediately',
'1',
'Send immediately, not via MetaMTA background script.'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Send Mail'));
$panel = new AphrontPanelView();
$panel->setHeader('Send Email');
$panel->appendChild($form);
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'Send Mail',
));
/*
return
<metamta:standard-page title="Send Email">
<tools:form width="wide" method="post" action={URI::getRequestURI()}>
<h1>Send Email</h1>
<tools:fieldset>
<tools:instructions>This form will send a normal email using MetaMTA
as a transport mechanism.</tools:instructions>
<tools:control type="text" label="To">
<tools:tokenizer name="to" datasource="mailable" />
</tools:control>
<tools:control type="text" label="CC">
<tools:tokenizer name="cc" datasource="mailable" />
</tools:control>
<tools:control type="text" label="Subject">
<input type="text" name="subject" />
</tools:control>
<tools:control type="textarea" label="Body">
<textarea name="body"></textarea>
</tools:control>
<tools:control type="text" label="Simulate Failures"
caption={$failure_caption}>
<input type="text" name="failures" />
</tools:control>
<tools:control type="checkbox" label="HTML">
<input type="checkbox" name="html" value="1" />
Send as HTML email.
</tools:control>
<tools:control type="checkbox" label="Send Now">
<input type="checkbox" name="immediately" value="1" />
Send immediately, not via MetaMTA daemon.
</tools:control>
<tools:control type="submit">
<button>Send Email</button>
</tools:control>
</tools:fieldset>
</tools:form>
</metamta:standard-page>;
*/
}
}

View file

@ -0,0 +1,19 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/metamta/controller/base');
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorMetaMTASendController.php');

View file

@ -0,0 +1,25 @@
<?php
/*
* Copyright 2011 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.
*/
abstract class PhabricatorMetaMTADAO extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'metamta';
}
}

View file

@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/base/storage/lisk');
phutil_require_source('PhabricatorMetaMTADAO.php');

View file

@ -0,0 +1,218 @@
<?php
/*
* Copyright 2011 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.
*/
/**
* See #394445 for an explanation of why this thing even exists.
*/
class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO {
const STATUS_QUEUE = 'queued';
const STATUS_SENT = 'sent';
const STATUS_FAIL = 'fail';
const MAX_RETRIES = 250;
const RETRY_DELAY = 5;
protected $parameters;
protected $status;
protected $message;
protected $retryCount;
protected $nextRetry;
protected $relatedPHID;
public function __construct() {
$this->status = self::STATUS_QUEUE;
$this->retryCount = 0;
$this->nextRetry = time();
$this->parameters = array();
parent::__construct();
}
public function getConfiguration() {
return array(
self::CONFIG_SERIALIZATION => array(
'parameters' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
protected function setParam($param, $value) {
$this->parameters[$param] = $value;
return $this;
}
protected function getParam($param) {
return idx($this->parameters, $param);
}
public function getSubject() {
return $this->getParam('subject');
}
public function addTos(array $phids) {
$this->setParam('to', $phids);
return $this;
}
public function addCCs(array $phids) {
$this->setParam('cc', $phids);
return $this;
}
public function addHeader($name, $value) {
$this->parameters['headers'][$name] = $value;
return $this;
}
public function setFrom($from) {
$this->setParam('from', $from);
return $this;
}
public function setReplyTo($phid) {
$this->setParam('reply-to', $phid);
return $this;
}
public function setSubject($subject) {
$this->setParam('subject', $subject);
return $this;
}
public function setBody($body) {
$this->setParam('body', $body);
return $this;
}
public function setIsHTML($html) {
$this->setParam('is-html', $html);
return $this;
}
public function getSimulatedFailureCount() {
return nonempty($this->getParam('simulated-failures'), 0);
}
public function setSimulatedFailureCount($count) {
$this->setParam('simulated-failures', $count);
return $this;
}
public function sendNow($force_send = false) {
/*
if (!$force_send) {
if ($this->getStatus() != self::STATUS_QUEUE) {
throw new Exception("Trying to send an already-sent mail!");
}
if (time() < $this->getNextRetry()) {
throw new Exception("Trying to send an email before next retry!");
}
}
require_module_lazy('intern/mailer');
try {
$mailer = new InternMailer();
foreach ($this->parameters as $key => $value) {
switch ($key) {
case 'from':
$mailer->setFrom($value);
break;
case 'reply-to':
$mailer->addReplyTo($value);
break;
case 'to':
$mailer->addTos($value);
break;
case 'cc':
$mailer->addCCs($value);
break;
case 'headers':
foreach ($value as $header_key => $header_value) {
$mailer->addHeader($header_key, $header_value);
}
break;
case 'body':
$mailer->setBody($value);
break;
case 'subject':
$mailer->setSubject($value);
break;
case 'is-html':
if ($value) {
$mailer->setIsHTML(true);
}
break;
default:
// Just discard.
}
}
$mailer->addHeader('X-Mail-Transport-Agent', 'MetaMTA');
if (!$mailer->hasValidRecipients()) {
throw new Exception("Permanent failure: no valid recipients.");
}
} catch (Exception $ex) {
$this->setStatus(self::STATUS_FAIL);
$this->setMessage($ex->getMessage());
$this->save();
return;
}
if ($this->getRetryCount() < $this->getSimulatedFailureCount()) {
$ok = false;
$error = 'Simulated failure.';
} else {
$ok = $mailer->send();
$error = $mailer->getError();
}
*/
$error = null;
$ok = true;
if (!$ok) {
$this->setMessage($error);
if ($this->getRetryCount() > self::MAX_RETRIES) {
$this->setStatus(self::STATUS_FAIL);
} else {
$this->setRetryCount($this->getRetryCount() + 1);
$next_retry = time() + ($this->getRetryCount() * self::RETRY_DELAY);
$this->setNextRetry($next_retry);
}
} else {
$this->setStatus(self::STATUS_SENT);
}
$this->save();
}
public static function getReadableStatus($status_code) {
static $readable = array(
self::STATUS_QUEUE => "Queued for Delivery",
self::STATUS_FAIL => "Delivery Failed",
self::STATUS_SENT => "Sent",
);
$status_code = coalesce($status_code, '?');
return idx($readable, $status_code, $status_code);
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/metamta/storage/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorMetaMTAMail.php');

View file

@ -87,7 +87,7 @@ abstract class AphrontFormControl extends AphrontView {
if (strlen($this->getLabel())) {
$label =
'<label>'.
'<label class="aphront-form-label">'.
phutil_escape_html($this->getLabel()).
':'.
'</label>';

View file

@ -0,0 +1,68 @@
<?php
/*
* Copyright 2011 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.
*/
class AphrontFormCheckboxControl extends AphrontFormControl {
private $boxes = array();
public function addCheckbox($name, $value, $label, $checked = false) {
$this->boxes[] = array(
'name' => $name,
'value' => $value,
'label' => $label,
'checked' => $checked,
);
return $this;
}
protected function getCustomControlClass() {
return 'aphront-form-control-checkbox';
}
protected function renderInput() {
$rows = array();
foreach ($this->boxes as $box) {
$id = celerity_generate_unique_node_id();
$checkbox = phutil_render_tag(
'input',
array(
'id' => $id,
'type' => 'checkbox',
'name' => $box['name'],
'value' => $box['value'],
'checked' => $box['checked'] ? 'checked' : null,
));
$label = phutil_render_tag(
'label',
array(
'for' => $id,
),
phutil_escape_html($box['label']));
$rows[] =
'<tr>'.
'<td>'.$checkbox.'</td>'.
'<th>'.$label.'</th>'.
'</tr>';
}
return
'<table class="aphront-form-control-checkbox-layout">'.
implode("\n", $rows).
'</table>';
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'infratructure/celerity/api');
phutil_require_module('phabricator', 'view/form/control/base');
phutil_require_module('phutil', 'markup');
phutil_require_source('AphrontFormCheckboxControl.php');

View file

@ -8,7 +8,7 @@
padding: 1em;
}
.aphront-form-view label {
.aphront-form-view label.aphront-form-label {
padding-top: 4px;
width: 19%;
float: left;
@ -64,7 +64,7 @@
text-align: right;
clear: both;
margin-right: 25%;
margin-left: 15%;
margin-left: 20%;
}
.aphront-error-view {
@ -76,10 +76,24 @@
}
.aphront-form-instructions {
margin: 2em 3%;
margin: 0.75em 3% 1.25em;
}
.aphront-form-control-static .aphront-form-input {
padding-top: 4px;
font-size: 13px;
}
table.aphront-form-control-checkbox-layout {
margin-top: 3px;
font-size: 13px;
}
table.aphront-form-control-checkbox-layout th {
padding-top: 2px;
padding-left: 0.35em;
}
.aphront-form-control-checkbox-layout td input {
width: auto;
}