Merge branch 'gmacon-verifyWebhookSignature'

This commit is contained in:
Travis Swientek 2014-11-19 14:29:50 -08:00
commit f4c6fd012b
2 changed files with 90 additions and 46 deletions

View File

@ -17,66 +17,90 @@ use Mailgun\Messages\MessageBuilder;
*/ */
class Mailgun{ class Mailgun{
protected $workingDomain; protected $workingDomain;
protected $restClient; protected $restClient;
protected $apiKey;
public function __construct($apiKey = null, $apiEndpoint = "api.mailgun.net", $apiVersion = "v2", $ssl = true){ public function __construct($apiKey = null, $apiEndpoint = "api.mailgun.net", $apiVersion = "v2", $ssl = true){
$this->restClient = new RestClient($apiKey, $apiEndpoint, $apiVersion, $ssl); $this->apiKey = $apiKey;
$this->restClient = new RestClient($apiKey, $apiEndpoint, $apiVersion, $ssl);
} }
public function sendMessage($workingDomain, $postData, $postFiles = array()){ public function sendMessage($workingDomain, $postData, $postFiles = array()){
/*
* This function allows the sending of a fully formed message OR a custom
* MIME string. If sending MIME, the string must be passed in to the 3rd
* position of the function call.
*/
if(is_array($postFiles)){
return $this->post("$workingDomain/messages", $postData, $postFiles);
}
else if(is_string($postFiles)){
/* $tempFile = tempnam(sys_get_temp_dir(), "MG_TMP_MIME");
This function allows the sending of a fully formed message OR a custom $fileHandle = fopen($tempFile, "w");
MIME string. If sending MIME, the string must be passed in to the 3rd fwrite($fileHandle, $postFiles);
position of the function call.
*/
if(is_array($postFiles)){ $result = $this->post("$workingDomain/messages.mime", $postData, array("message" => $tempFile));
return $this->post("$workingDomain/messages", $postData, $postFiles);
}
else if(is_string($postFiles)){
$tempFile = tempnam(sys_get_temp_dir(), "MG_TMP_MIME");
$fileHandle = fopen($tempFile, "w");
fwrite($fileHandle, $postFiles);
$result = $this->post("$workingDomain/messages.mime", $postData, array("message" => $tempFile));
fclose($fileHandle); fclose($fileHandle);
unlink($tempFile); unlink($tempFile);
return $result; return $result;
} }
else{ else{
throw new Exceptions\MissingRequiredMIMEParameters(EXCEPTION_MISSING_REQUIRED_MIME_PARAMETERS); throw new Exceptions\MissingRequiredMIMEParameters(EXCEPTION_MISSING_REQUIRED_MIME_PARAMETERS);
} }
} }
public function post($endpointUrl, $postData = array(), $files = array()){ public function verifyWebhookSignature($postData = NULL) {
return $this->restClient->post($endpointUrl, $postData, $files); /*
} * This function checks the signature in a POST request to see if it is
* authentic.
*
* Pass an array of parameters. If you pass nothing, $_POST will be
* used instead.
*
* If this function returns FALSE, you must not process the request.
* You should reject the request with status code 403 Forbidden.
*/
if(is_null($postData)) {
$postData = $_POST;
}
$hmac = hash_hmac('sha256', "{$postData["timestamp"]}{$postData["token"]}", $this->apiKey);
$sig = $postData['signature'];
if(function_exists('hash_equals')) {
// hash_equals is constant time, but will not be introduced until PHP 5.6
return hash_equals($hmac, $sig);
}
else {
return ($hmac == $sig);
}
}
public function get($endpointUrl, $queryString = array()){ public function post($endpointUrl, $postData = array(), $files = array()){
return $this->restClient->get($endpointUrl, $queryString); return $this->restClient->post($endpointUrl, $postData, $files);
} }
public function delete($endpointUrl){ public function get($endpointUrl, $queryString = array()){
return $this->restClient->delete($endpointUrl); return $this->restClient->get($endpointUrl, $queryString);
} }
public function put($endpointUrl, $putData){ public function delete($endpointUrl){
return $this->restClient->put($endpointUrl, $putData); return $this->restClient->delete($endpointUrl);
} }
public function MessageBuilder(){ public function put($endpointUrl, $putData){
return new MessageBuilder(); return $this->restClient->put($endpointUrl, $putData);
} }
public function OptInHandler(){ public function MessageBuilder(){
return new OptInHandler(); return new MessageBuilder();
} }
public function BatchMessage($workingDomain, $autoSend = true){ public function OptInHandler(){
return new BatchMessage($this->restClient, $workingDomain, $autoSend); return new OptInHandler();
} }
public function BatchMessage($workingDomain, $autoSend = true){
return new BatchMessage($this->restClient, $workingDomain, $autoSend);
}
} }

View File

@ -13,4 +13,24 @@ class MailgunTest extends \Mailgun\Tests\MailgunTestCase
$client = new Mailgun(); $client = new Mailgun();
$client->sendMessage("test.mailgun.com", "etss", 1); $client->sendMessage("test.mailgun.com", "etss", 1);
} }
public function testVerifyWebhookGood() {
$client = new Mailgun('key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
$postData = [
'timestamp' => '1403645220',
'token' => '5egbgr1vjgqxtrnp65xfznchgdccwh5d6i09vijqi3whgowmn6',
'signature' => '9cfc5c41582e51246e73c88d34db3af0a3a2692a76fbab81492842f000256d33',
];
assert($client->verifyWebhookSignature($postData));
}
public function testVerifyWebhookBad() {
$client = new Mailgun('key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
$postData = [
'timestamp' => '1403645220',
'token' => 'owyldpe6nxhmrn78epljl6bj0orrki1u3d2v5e6cnlmmuox8jr',
'signature' => '9cfc5c41582e51246e73c88d34db3af0a3a2692a76fbab81492842f000256d33',
];
assert(!$client->verifyWebhookSignature($postData));
}
} }