mirror of
https://we.phorge.it/source/phorge.git
synced 2025-04-03 16:08:19 +02:00
Add a Twilio SMS message adapter
Summary: Ref T920. Adds a "phone number" object, an "SMS" message type, and Twilio glue. Test Plan: Used this test script to send myself some text messages after configuring Twilio in `cluster.mailers`. ``` <?php require_once 'scripts/init/init-script.php'; if ($argc < 3) { throw new Exception('usage: test.php <number> <body>'); } $to_number = $argv[1]; $text_body = $argv[2]; $mailers = PhabricatorMetaMTAMail::newMailers( array( 'outbound' => true, 'media' => array( PhabricatorMailSMSMessage::MESSAGETYPE, ), )); if (!$mailers) { return new Aphront404Response(); } $mailer = head($mailers); $message = id(new PhabricatorMailSMSMessage()) ->setToNumber(new PhabricatorPhoneNumber($to_number)) ->setTextBody($text_body); $mailer->sendMessage($message); ``` Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T920 Differential Revision: https://secure.phabricator.com/D19971
This commit is contained in:
parent
96d3e73eed
commit
35f0e31ed3
5 changed files with 136 additions and 0 deletions
|
@ -3423,6 +3423,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
|
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
|
||||||
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
||||||
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
||||||
|
'PhabricatorMailSMSMessage' => 'applications/metamta/message/PhabricatorMailSMSMessage.php',
|
||||||
'PhabricatorMailSMTPAdapter' => 'applications/metamta/adapter/PhabricatorMailSMTPAdapter.php',
|
'PhabricatorMailSMTPAdapter' => 'applications/metamta/adapter/PhabricatorMailSMTPAdapter.php',
|
||||||
'PhabricatorMailSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailSendGridAdapter.php',
|
'PhabricatorMailSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailSendGridAdapter.php',
|
||||||
'PhabricatorMailSendmailAdapter' => 'applications/metamta/adapter/PhabricatorMailSendmailAdapter.php',
|
'PhabricatorMailSendmailAdapter' => 'applications/metamta/adapter/PhabricatorMailSendmailAdapter.php',
|
||||||
|
@ -3430,6 +3431,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
|
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
|
||||||
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
||||||
'PhabricatorMailTestAdapter' => 'applications/metamta/adapter/PhabricatorMailTestAdapter.php',
|
'PhabricatorMailTestAdapter' => 'applications/metamta/adapter/PhabricatorMailTestAdapter.php',
|
||||||
|
'PhabricatorMailTwilioAdapter' => 'applications/metamta/adapter/PhabricatorMailTwilioAdapter.php',
|
||||||
'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php',
|
'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php',
|
||||||
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
||||||
'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php',
|
'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php',
|
||||||
|
@ -3851,6 +3853,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPholioApplication' => 'applications/pholio/application/PhabricatorPholioApplication.php',
|
'PhabricatorPholioApplication' => 'applications/pholio/application/PhabricatorPholioApplication.php',
|
||||||
'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php',
|
'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php',
|
||||||
'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php',
|
'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php',
|
||||||
|
'PhabricatorPhoneNumber' => 'applications/metamta/message/PhabricatorPhoneNumber.php',
|
||||||
'PhabricatorPhortuneApplication' => 'applications/phortune/application/PhabricatorPhortuneApplication.php',
|
'PhabricatorPhortuneApplication' => 'applications/phortune/application/PhabricatorPhortuneApplication.php',
|
||||||
'PhabricatorPhortuneContentSource' => 'applications/phortune/contentsource/PhabricatorPhortuneContentSource.php',
|
'PhabricatorPhortuneContentSource' => 'applications/phortune/contentsource/PhabricatorPhortuneContentSource.php',
|
||||||
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php',
|
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php',
|
||||||
|
@ -9257,6 +9260,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
|
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorMailReplyHandler' => 'Phobject',
|
'PhabricatorMailReplyHandler' => 'Phobject',
|
||||||
'PhabricatorMailRoutingRule' => 'Phobject',
|
'PhabricatorMailRoutingRule' => 'Phobject',
|
||||||
|
'PhabricatorMailSMSMessage' => 'PhabricatorMailExternalMessage',
|
||||||
'PhabricatorMailSMTPAdapter' => 'PhabricatorMailAdapter',
|
'PhabricatorMailSMTPAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailSendGridAdapter' => 'PhabricatorMailAdapter',
|
'PhabricatorMailSendGridAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailSendmailAdapter' => 'PhabricatorMailAdapter',
|
'PhabricatorMailSendmailAdapter' => 'PhabricatorMailAdapter',
|
||||||
|
@ -9264,6 +9268,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailStamp' => 'Phobject',
|
'PhabricatorMailStamp' => 'Phobject',
|
||||||
'PhabricatorMailTarget' => 'Phobject',
|
'PhabricatorMailTarget' => 'Phobject',
|
||||||
'PhabricatorMailTestAdapter' => 'PhabricatorMailAdapter',
|
'PhabricatorMailTestAdapter' => 'PhabricatorMailAdapter',
|
||||||
|
'PhabricatorMailTwilioAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailUtil' => 'Phobject',
|
'PhabricatorMailUtil' => 'Phobject',
|
||||||
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
||||||
'PhabricatorMainMenuSearchView' => 'AphrontView',
|
'PhabricatorMainMenuSearchView' => 'AphrontView',
|
||||||
|
@ -9768,6 +9773,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPholioApplication' => 'PhabricatorApplication',
|
'PhabricatorPholioApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
||||||
|
'PhabricatorPhoneNumber' => 'Phobject',
|
||||||
'PhabricatorPhortuneApplication' => 'PhabricatorApplication',
|
'PhabricatorPhortuneApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorPhortuneContentSource' => 'PhabricatorContentSource',
|
'PhabricatorPhortuneContentSource' => 'PhabricatorContentSource',
|
||||||
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow',
|
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow',
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMailTwilioAdapter
|
||||||
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'twilio';
|
||||||
|
|
||||||
|
public function getSupportedMessageTypes() {
|
||||||
|
return array(
|
||||||
|
PhabricatorMailSMSMessage::MESSAGETYPE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'account-sid' => 'string',
|
||||||
|
'auth-token' => 'string',
|
||||||
|
'from-number' => 'string',
|
||||||
|
));
|
||||||
|
|
||||||
|
// Construct an object from the "from-number" to validate it.
|
||||||
|
$number = new PhabricatorPhoneNumber($options['from-number']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'account-sid' => null,
|
||||||
|
'auth-token' => null,
|
||||||
|
'from-number' => null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendMessage(PhabricatorMailExternalMessage $message) {
|
||||||
|
$account_sid = $this->getOption('account-sid');
|
||||||
|
|
||||||
|
$auth_token = $this->getOption('auth-token');
|
||||||
|
$auth_token = new PhutilOpaqueEnvelope($auth_token);
|
||||||
|
|
||||||
|
$from_number = $this->getOption('from-number');
|
||||||
|
$from_number = new PhabricatorPhoneNumber($from_number);
|
||||||
|
|
||||||
|
$to_number = $message->getToNumber();
|
||||||
|
$text_body = $message->getTextBody();
|
||||||
|
|
||||||
|
$parameters = array(
|
||||||
|
'From' => $from_number->toE164(),
|
||||||
|
'To' => $to_number->toE164(),
|
||||||
|
'Body' => $text_body,
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = id(new PhabricatorTwilioFuture())
|
||||||
|
->setAccountSID($account_sid)
|
||||||
|
->setAuthToken($auth_token)
|
||||||
|
->setMethod('Messages.json', $parameters)
|
||||||
|
->setTimeout(60)
|
||||||
|
->resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ final class PhabricatorTwilioFuture extends FutureProxy {
|
||||||
private $authToken;
|
private $authToken;
|
||||||
private $method;
|
private $method;
|
||||||
private $parameters;
|
private $parameters;
|
||||||
|
private $timeout;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
parent::__construct(null);
|
parent::__construct(null);
|
||||||
|
@ -28,6 +29,15 @@ final class PhabricatorTwilioFuture extends FutureProxy {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setTimeout($timeout) {
|
||||||
|
$this->timeout = $timeout;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTimeout() {
|
||||||
|
return $this->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getProxiedFuture() {
|
protected function getProxiedFuture() {
|
||||||
if (!$this->future) {
|
if (!$this->future) {
|
||||||
if ($this->accountSID === null) {
|
if ($this->accountSID === null) {
|
||||||
|
@ -58,6 +68,11 @@ final class PhabricatorTwilioFuture extends FutureProxy {
|
||||||
->setMethod('POST')
|
->setMethod('POST')
|
||||||
->addHeader('Accept', 'application/json');
|
->addHeader('Accept', 'application/json');
|
||||||
|
|
||||||
|
$timeout = $this->getTimeout();
|
||||||
|
if ($timeout) {
|
||||||
|
$future->setTimeout($timeout);
|
||||||
|
}
|
||||||
|
|
||||||
$this->future = $future;
|
$this->future = $future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMailSMSMessage
|
||||||
|
extends PhabricatorMailExternalMessage {
|
||||||
|
|
||||||
|
const MESSAGETYPE = 'sms';
|
||||||
|
|
||||||
|
private $toNumber;
|
||||||
|
private $textBody;
|
||||||
|
|
||||||
|
public function setToNumber(PhabricatorPhoneNumber $to_number) {
|
||||||
|
$this->toNumber = $to_number;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToNumber() {
|
||||||
|
return $this->toNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTextBody($text_body) {
|
||||||
|
$this->textBody = $text_body;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTextBody() {
|
||||||
|
return $this->textBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
src/applications/metamta/message/PhabricatorPhoneNumber.php
Normal file
25
src/applications/metamta/message/PhabricatorPhoneNumber.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorPhoneNumber
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $number;
|
||||||
|
|
||||||
|
public function __construct($raw_number) {
|
||||||
|
$number = preg_replace('/[^\d]+/', '', $raw_number);
|
||||||
|
|
||||||
|
if (!preg_match('/^[1-9]\d{1,14}\z/', $number)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Phone number ("%s") is not in a recognized format.',
|
||||||
|
$raw_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->number = $number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toE164() {
|
||||||
|
return '+'.$this->number;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue