Domains API, #187 (#198)

This commit is contained in:
Sean Johnson 2016-10-27 01:34:27 -05:00 committed by Tobias Nyholm
parent 738e6e32e2
commit 58430e4537
19 changed files with 1775 additions and 22 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ composer.lock
nbproject/*
.idea
phpunit.phar
modd.conf

View File

@ -11,6 +11,9 @@ before_install:
install:
- travis_retry composer install
- travis_retry composer require --dev 'phpunit/php-code-coverage=^2.2.4'
script:
- phpunit
- phpunit -c phpunit.xml.dist --testsuite unit --coverage-text
- phpunit -c phpunit.xml.dist --testsuite functional --coverage-text
- '[[ "${TRAVIS_PULL_REQUEST}" == "false" ]] && ( phpunit -c phpunit.xml.dist --testsuite integration --coverage-text ) || ( echo "Testing PR - No integration tests available")'

View File

@ -11,7 +11,7 @@
"webmozart/assert": "^1.1"
},
"require-dev": {
"phpunit/phpunit": "~4.6",
"phpunit/phpunit": "~4.8",
"php-http/guzzle6-adapter": "^1.0"
},
"autoload": {

View File

@ -13,7 +13,26 @@
<testsuite>
<directory>tests</directory>
</testsuite>
<testsuite name="unit">
<directory>tests</directory>
<exclude>tests/Integration</exclude>
<exclude>test/Functional</exclude>
</testsuite>
<testsuite name="integration">
<directory>tests/Integration</directory>
</testsuite>
<testsuite name="functional">
<directory>tests/Functional</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>

View File

@ -4,10 +4,15 @@ namespace Mailgun\Api;
use Http\Client\Common\HttpMethodsClient;
use Http\Client\HttpClient;
use Http\Message\RequestFactory;
use Mailgun\Exception\HttpServerException;
use Http\Client\Exception as HttplugException;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\StreamFactoryDiscovery;
use Http\Message\RequestFactory;
use Http\Message\MultipartStream\MultipartStreamBuilder;
use Mailgun\Assert;
use Mailgun\Exception\HttpServerException;
use Mailgun\Serializer\ResponseDeserializer;
use Mailgun\Resource\Api\SimpleResponse;
use Psr\Http\Message\ResponseInterface;
/**
@ -38,6 +43,25 @@ abstract class AbstractApi
$this->serializer = $serializer;
}
/**
* Attempts to safely deserialize the response into the given class.
* If the HTTP return code != 200, deserializes into SimpleResponse::class
* to contain the error message and any other information provided.
*
* @param ResponseInterface $response
* @param string $className
*
* @return $class|SimpleResponse
*/
protected function safeDeserialize(ResponseInterface $response, $className)
{
if ($response->getStatusCode() !== 200) {
return $this->serializer->deserialize($response, SimpleResponse::class);
} else {
return $this->serializer->deserialize($response, $className);
}
}
/**
* Send a GET request with query parameters.
*
@ -76,6 +100,20 @@ abstract class AbstractApi
return $this->postRaw($path, $this->createJsonBody($parameters), $requestHeaders);
}
/**
* Send a POST request with parameters encoded as multipart-stream form data.
*
* @param string $path Request path.
* @param array $parameters POST parameters to be mutipart-stream-encoded.
* @param array $requestHeaders Request headers.
*
* @return ResponseInterface
*/
protected function postMultipart($path, array $parameters = [], array $requestHeaders = [])
{
return $this->doMultipart('POST', $path, $parameters, $requestHeaders);
}
/**
* Send a POST request with raw data.
*
@ -116,6 +154,20 @@ abstract class AbstractApi
return $response;
}
/**
* Send a PUT request with parameters encoded as multipart-stream form data.
*
* @param string $path Request path.
* @param array $parameters PUT parameters to be mutipart-stream-encoded.
* @param array $requestHeaders Request headers.
*
* @return ResponseInterface
*/
protected function putMultipart($path, array $parameters = [], array $requestHeaders = [])
{
return $this->doMultipart('PUT', $path, $parameters, $requestHeaders);
}
/**
* Send a DELETE request with JSON-encoded parameters.
*
@ -136,6 +188,60 @@ abstract class AbstractApi
return $response;
}
/**
* Send a DELETE request with parameters encoded as multipart-stream form data.
*
* @param string $path Request path.
* @param array $parameters DELETE parameters to be mutipart-stream-encoded.
* @param array $requestHeaders Request headers.
*
* @return ResponseInterface
*/
protected function deleteMultipart($path, array $parameters = [], array $requestHeaders = [])
{
return $this->doMultipart('DELETE', $path, $parameters, $requestHeaders);
}
/**
* Send a request with parameters encoded as multipart-stream form data.
*
* @param string $type Request type. (POST, PUT, etc.)
* @param string $path Request path.
* @param array $parameters POST parameters to be mutipart-stream-encoded.
* @param array $requestHeaders Request headers.
*
* @return ResponseInterface
*/
protected function doMultipart($type, $path, array $parameters = [], array $requestHeaders = [])
{
Assert::oneOf(
$type,
[
'DELETE',
'POST',
'PUT',
]
);
$streamFactory = StreamFactoryDiscovery::find();
$builder = new MultipartStreamBuilder($streamFactory);
foreach ($parameters as $k => $v) {
$builder->addResource($k, $v);
}
$multipartStream = $builder->build();
$boundary = $builder->getBoundary();
$request = MessageFactoryDiscovery::find()->createRequest(
$type,
$path,
['Content-Type' => 'multipart/form-data; boundary='.$boundary],
$multipartStream
);
return $this->httpClient->sendRequest($request);
}
/**
* Create a JSON encoded version of an array of parameters.
*

269
src/Mailgun/Api/Domain.php Normal file
View File

@ -0,0 +1,269 @@
<?php
/*
* Copyright (C) 2013-2016 Mailgun
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Api;
use Mailgun\Assert;
use Mailgun\Resource\Api\Domain\ComplexDomain;
use Mailgun\Resource\Api\Domain\Credential;
use Mailgun\Resource\Api\Domain\CredentialListResponse;
use Mailgun\Resource\Api\Domain\DeliverySettingsResponse;
use Mailgun\Resource\Api\Domain\DeliverySettingsUpdateResponse;
use Mailgun\Resource\Api\Domain\DomainListResponse;
use Mailgun\Resource\Api\SimpleResponse;
/**
* {@link https://documentation.mailgun.com/api-domains.html}.
*
* @author Sean Johnson <sean@mailgun.com>
*/
class Domain extends AbstractApi
{
/**
* Returns a list of domains on the account.
*
* @param int $limit
* @param int $skip
*
* @return DomainListResponse
*/
public function listAll($limit = 100, $skip = 0)
{
Assert::integer($limit);
Assert::integer($skip);
$params = [
'limit' => $limit,
'skip' => $skip,
];
$response = $this->get('/v3/domains', $params);
return $this->serializer->deserialize($response, DomainListResponse::class);
}
/**
* Returns a single domain.
*
* @param string $domain Name of the domain.
*
* @return ComplexDomain|array|ResponseInterface
*/
public function info($domain)
{
Assert::stringNotEmpty($domain);
$response = $this->get(sprintf('/v3/domains/%s', $domain));
return $this->serializer->deserialize($response, ComplexDomain::class);
}
/**
* Creates a new domain for the account.
* See below for spam filtering parameter information.
* {@link https://documentation.mailgun.com/user_manual.html#um-spam-filter}.
*
* @param string $domain Name of the domain.
* @param string $smtpPass Password for SMTP authentication.
* @param string $spamAction `disable` or `tag` - inbound spam filtering.
* @param bool $wildcard Domain will accept email for subdomains.
*
* @return ComplexDomain|array|ResponseInterface
*/
public function create($domain, $smtpPass, $spamAction, $wildcard)
{
Assert::stringNotEmpty($domain);
Assert::stringNotEmpty($smtpPass);
// TODO(sean.johnson): Extended spam filter input validation.
Assert::stringNotEmpty($spamAction);
Assert::boolean($wildcard);
$params = [
'name' => $domain,
'smtp_password' => $smtpPass,
'spam_action' => $spamAction,
'wildcard' => $wildcard,
];
$response = $this->postMultipart('/v3/domains', $params);
return $this->safeDeserialize($response, ComplexDomain::class);
}
/**
* Removes a domain from the account.
* WARNING: This action is irreversible! Be cautious!
*
* @param string $domain Name of the domain.
*
* @return SimpleResponse|array|ResponseInterface
*/
public function remove($domain)
{
Assert::stringNotEmpty($domain);
$response = $this->delete(sprintf('/v3/domains/%s', $domain));
return $this->serializer->deserialize($response, SimpleResponse::class);
}
/**
* Returns a list of SMTP credentials for the specified domain.
*
* @param string $domain Name of the domain.
* @param int $limit Number of credentials to return
* @param int $skip Number of credentials to omit from the list
*
* @return CredentialsListResponse
*/
public function listCredentials($domain, $limit = 100, $skip = 0)
{
Assert::stringNotEmpty($domain);
Assert::integer($limit);
Assert::integer($skip);
$params = [
'limit' => $limit,
'skip' => $skip,
];
$response = $this->get(sprintf('/v3/domains/%s/credentials', $domain), $params);
return $this->safeDeserialize($response, CredentialListResponse::class);
}
/**
* Create a new SMTP credential pair for the specified domain.
*
* @param string $domain Name of the domain.
* @param string $login SMTP Username.
* @param string $password SMTP Password. Length min 5, max 32.
*
* @return Credential|array|ResponseInterface
*/
public function newCredential($domain, $login, $password)
{
Assert::stringNotEmpty($domain);
Assert::stringNotEmpty($login);
Assert::stringNotEmpty($password);
Assert::lengthBetween($password, 5, 32, 'SMTP password must be between 5 and 32 characters.');
$params = [
'login' => $login,
'password' => $password,
];
$response = $this->postMultipart(sprintf('/v3/domains/%s/credentials', $domain), $params);
return $this->serializer->deserialize($response, SimpleResponse::class);
}
/**
* Update a set of SMTP credentials for the specified domain.
*
* @param string $domain Name of the domain.
* @param string $login SMTP Username.
* @param string $pass New SMTP Password. Length min 5, max 32.
*
* @return SimpleResponse|array|ResponseInterface
*/
public function updateCredential($domain, $login, $pass)
{
Assert::stringNotEmpty($domain);
Assert::stringNotEmpty($login);
Assert::stringNotEmpty($pass);
Assert::lengthBetween($pass, 5, 32, 'SMTP password must be between 5 and 32 characters.');
$params = [
'password' => $pass,
];
$response = $this->putMultipart(
sprintf(
'/v3/domains/%s/credentials/%s',
$domain,
$login
),
$params
);
return $this->serializer->deserialize($response, SimpleResponse::class);
}
/**
* Remove a set of SMTP credentials from the specified domain.
*
* @param string $domain Name of the domain.
* @param string $login SMTP Username.
*
* @return SimpleResponse|array|ResponseInterface
*/
public function deleteCredential($domain, $login)
{
Assert::stringNotEmpty($domain);
Assert::stringNotEmpty($login);
$response = $this->delete(
sprintf(
'/v3/domains/%s/credentials/%s',
$domain,
$login
)
);
return $this->serializer->deserialize($response, SimpleResponse::class);
}
/**
* Returns delivery connection settings for the specified domain.
*
* @param string $domain Name of the domain.
*
* @return DeliverySettingsResponse|array|ResponseInterface
*/
public function getDeliverySettings($domain)
{
Assert::stringNotEmpty($domain);
$response = $this->get(sprintf('/v3/domains/%s/connection', $domain));
return $this->serializer->deserialize($response, DeliverySettingsResponse::class);
}
/**
* Updates the specified delivery connection settings for the specified domain.
* If a parameter is passed in as null, it will not be updated.
*
* @param string $domain Name of the domain.
* @param bool|null $requireTLS Enforces that messages are sent only over a TLS connection.
* @param bool|null $noVerify Disables TLS certificate and hostname verification.
*
* @return DeliverySettingsResponse|array|ResponseInterface
*/
public function updateDeliverySettings($domain, $requireTLS, $noVerify)
{
Assert::stringNotEmpty($domain);
Assert::nullOrBoolean($requireTLS);
Assert::nullOrBoolean($noVerify);
$params = [];
if (null !== $requireTLS) {
$params['require_tls'] = $requireTLS ? 'true' : 'false';
}
if (null !== $noVerify) {
$params['skip_verification'] = $noVerify ? 'true' : 'false';
}
$response = $this->putMultipart(sprintf('/v3/domains/%s/connection', $domain), $params);
return $this->serializer->deserialize($response, DeliverySettingsUpdateResponse::class);
}
}

View File

@ -260,4 +260,12 @@ class Mailgun
{
return new Api\Stats($this->httpClient, $this->requestFactory, $this->serializer);
}
/**
* @return Api\Domain
*/
public function getDomainApi()
{
return new Api\Domain($this->httpClient, $this->requestFactory, $this->serializer);
}
}

View File

@ -0,0 +1,95 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* ComplexDomain uses DomainTrait and exposes a "complex" constructor
* where an array or \stdClass can be passed in to find the appropriate
* fields.
*
* @author Sean Johnson <sean@mailgun.com>
*/
class ComplexDomain implements CreatableFromArray
{
/**
* @var SimpleDomain
*/
private $domain;
/**
* @var DomainDnsRecord[]
*/
private $inboundDnsRecords;
/**
* @var DomainDnsRecord[]
*/
private $outboundDnsRecords;
/**
* @param array $data
*
* @return ComplexDomain
*/
public static function createFromArray(array $data)
{
Assert::keyExists($data, 'domain');
Assert::keyExists($data, 'receiving_dns_records');
Assert::keyExists($data, 'sending_dns_records');
// Let DomainDnsRecord::createFromArray() handle validation of
// the `receiving_dns_records` and `sending_dns_records` data.
// Also let SimpleDomain::createFromArray() handle validation of
// the `domain` fields.
return new static(
SimpleDomain::createFromArray($data['domain']),
DomainDnsRecord::createFromArray($data['receiving_dns_records']),
DomainDnsRecord::createFromArray($data['sending_dns_records'])
);
}
/**
* @param SimpleDomain $domainInfo
* @param array $rxRecords Array of DomainDnsRecord instances
* @param array $txRecords Array of DomainDnsRecord instances
*/
public function __construct(SimpleDomain $domainInfo, array $rxRecords, array $txRecords)
{
$this->domain = $domainInfo;
$this->inboundDnsRecords = $rxRecords;
$this->outboundDnsRecords = $txRecords;
}
/**
* @return SimpleDomain
*/
public function getDomain()
{
return $this->domain;
}
/**
* @return DomainDnsRecord[]
*/
public function getInboundDNSRecords()
{
return $this->inboundDnsRecords;
}
/**
* @return DomainDnsRecord[]
*/
public function getOutboundDNSRecords()
{
return $this->outboundDnsRecords;
}
}

View File

@ -0,0 +1,113 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class Credential implements CreatableFromArray
{
/**
* @var int|null
*/
private $sizeBytes;
/**
* @var \DateTime
*/
private $createdAt;
/**
* @var string
*/
private $mailbox;
/**
* @var string
*/
private $login;
/**
* @param array $data
*
* @return Credential
*/
public static function createFromArray(array $data)
{
Assert::keyExists($data, 'created_at');
Assert::keyExists($data, 'mailbox');
Assert::keyExists($data, 'login');
$sizeBytes = array_key_exists('size_bytes', $data) ? $data['size_bytes'] : null;
$createdAt = new \DateTime($data['created_at']);
$mailbox = $data['mailbox'];
$login = $data['login'];
Assert::nullOrInteger($sizeBytes);
Assert::isInstanceOf($createdAt, '\DateTime');
Assert::string($mailbox);
Assert::string($login);
return new static(
$sizeBytes,
$createdAt,
$mailbox,
$login
);
}
/**
* @param int $sizeBytes
* @param \DateTime $createdAt
* @param string $mailbox
* @param string $login
*/
public function __construct($sizeBytes, \DateTime $createdAt, $mailbox, $login)
{
$this->sizeBytes = $sizeBytes;
$this->createdAt = $createdAt;
$this->mailbox = $mailbox;
$this->login = $login;
}
/**
* @return int|null
*/
public function getSizeBytes()
{
return $this->sizeBytes;
}
/**
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* @return string
*/
public function getMailbox()
{
return $this->mailbox;
}
/**
* @return string
*/
public function getLogin()
{
return $this->login;
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* Copyright (C) 2013-2016 Mailgun
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class CredentialListResponse implements CreatableFromArray
{
/**
* @var int
*/
private $totalCount;
/**
* @var Credential[]
*/
private $items;
/**
* @param array $data
*
* @return CredentialListResponse|array|ResponseInterface
*/
public static function createFromArray(array $data)
{
$items = [];
Assert::keyExists($data, 'total_count');
Assert::keyExists($data, 'items');
foreach ($data['items'] as $item) {
$items[] = Credential::createFromArray($item);
}
return new self($data['total_count'], $items);
}
/**
* @param int $totalCount
* @param Credential[] $items
*/
public function __construct($totalCount, array $items)
{
Assert::integer($totalCount);
Assert::isArray($items);
Assert::allIsInstanceOf($items, 'Mailgun\Resource\Api\Domain\Credential');
$this->totalCount = $totalCount;
$this->items = $items;
}
/**
* @return int
*/
public function getTotalCount()
{
return $this->totalCount;
}
/**
* @return Credential[]
*/
public function getCredentials()
{
return $this->items;
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class DeliverySettingsResponse implements CreatableFromArray
{
/**
* @var bool
*/
private $noVerify;
/**
* @var bool
*/
private $requireTLS;
/**
* @param array $data
*
* @return DeliverySettingsResponse
*/
public static function createFromArray(array $data)
{
Assert::keyExists($data, 'connection');
Assert::isArray($data['connection']);
$connSettings = $data['connection'];
Assert::keyExists($connSettings, 'skip_verification');
Assert::keyExists($connSettings, 'require_tls');
return new static(
$connSettings['skip_verification'],
$connSettings['require_tls']
);
}
/**
* @param bool $noVerify Disable remote TLS certificate verification
* @param bool $requireTLS Requires TLS for all outbound communication
*/
public function __construct($noVerify, $requireTLS)
{
$this->noVerify = $noVerify;
$this->requireTLS = $requireTLS;
}
/**
* @return bool
*/
public function getSkipVerification()
{
return $this->noVerify;
}
/**
* @return bool
*/
public function getRequireTLS()
{
return $this->requireTLS;
}
}

View File

@ -0,0 +1,91 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
use Mailgun\Resource\Api\SimpleResponse;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class DeliverySettingsUpdateResponse extends SimpleResponse implements CreatableFromArray
{
/**
* @var bool
*/
private $noVerify;
/**
* @var bool
*/
private $requireTLS;
/**
* @param array $data
*
* @return SettingsUpdateResponse
*/
public static function createFromArray(array $data)
{
Assert::keyExists($data, 'message');
Assert::keyExists($data, 'skip_verification');
Assert::keyExists($data, 'require_tls');
$message = $data['message'];
$noVerify = $data['skip_verification'];
$requireTLS = $data['require_tls'];
Assert::nullOrString($message);
Assert::boolean($noVerify);
Assert::boolean($requireTLS);
return new static(
$message,
$noVerify,
$requireTLS
);
}
/**
* @param string $message
* @param bool $noVerify
* @param bool $requireTLS
*/
public function __construct($message, $noVerify, $requireTLS)
{
$this->message = $message;
$this->noVerify = $noVerify;
$this->requireTLS = $requireTLS;
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @return bool
*/
public function getSkipVerification()
{
return $this->noVerify;
}
/**
* @return bool
*/
public function getRequireTLS()
{
return $this->requireTLS;
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* Represents a single DNS record for a domain.
*
* @author Sean Johnson <sean@mailgun.com>
*/
class DomainDnsRecord implements CreatableFromArray
{
/**
* @var string|null
*/
private $name;
/**
* @var string
*/
private $type;
/**
* @var string
*/
private $value;
/**
* @var string|null
*/
private $priority;
/**
* @var string
*/
private $valid;
/**
* @param array $data
*
* @return DomainDnsRecord[]|array|ResponseInterface
*/
public static function createFromArray(array $data)
{
$items = [];
foreach ($data as $item) {
Assert::keyExists($item, 'record_type');
Assert::keyExists($item, 'value');
Assert::keyExists($item, 'valid');
$items[] = new static(
array_key_exists('name', $item) ? $item['name'] : null,
$item['record_type'],
$item['value'],
array_key_exists('priority', $item) ? $item['priority'] : null,
$item['valid']
);
}
return $items;
}
/**
* @param string|null $name Name of the record, as used in CNAME, etc.
* @param string $type DNS record type
* @param string $value DNS record value
* @param string|null $priority Record priority, used for MX
* @param string $valid DNS record has been added to domain DNS?
*/
public function __construct($name, $type, $value, $priority, $valid)
{
Assert::nullOrString($name);
Assert::string($type);
Assert::string($value);
Assert::nullOrString($priority);
Assert::string($valid);
$this->name = $name;
$this->type = $type;
$this->value = $value;
$this->priority = $priority;
$this->valid = $valid;
}
/**
* @return string|null
*/
public function getName()
{
return $this->name;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @return value
*/
public function getValue()
{
return $this->value;
}
/**
* @return string|null
*/
public function getPriority()
{
return $this->priority;
}
/**
* @return bool
*/
public function isValid()
{
return 'valid' === $this->value;
}
/**
* @return string
*/
public function getValidity()
{
return $this->valid;
}
}

View File

@ -0,0 +1,95 @@
<?php
/*
* Copyright (C) 2013-2016 Mailgun
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class DomainListResponse implements CreatableFromArray
{
/**
* @var int
*/
private $totalCount;
/**
* @var SimpleDomain[]
*/
private $items;
/**
* @param array $data
*
* @return DomainListResponse|array|ResponseInterface
*/
public static function createFromArray(array $data)
{
$items = [];
Assert::keyExists($data, 'total_count');
Assert::keyExists($data, 'items');
foreach ($data['items'] as $item) {
Assert::keyExists($item, 'name');
Assert::keyExists($item, 'smtp_login');
Assert::keyExists($item, 'smtp_password');
Assert::keyExists($item, 'wildcard');
Assert::keyExists($item, 'spam_action');
Assert::keyExists($item, 'state');
Assert::keyExists($item, 'created_at');
$items[] = SimpleDomain::createFromArray($item);
$items[] = new SimpleDomain(
$item['name'],
$item['smtp_login'],
$item['smtp_password'],
$item['wildcard'],
$item['spam_action'],
$item['state'],
new \DateTime($item['created_at'])
);
}
return new self($data['total_count'], $items);
}
/**
* @param int $totalCount
* @param SimpleDomain[] $items
*/
public function __construct($totalCount, array $items)
{
Assert::integer($totalCount);
Assert::isArray($items);
Assert::allIsInstanceOf($items, 'Mailgun\Resource\Api\Domain\SimpleDomain');
$this->totalCount = $totalCount;
$this->items = $items;
}
/**
* @return int
*/
public function getTotalCount()
{
return $this->totalCount;
}
/**
* @return SimpleDomain[]
*/
public function getDomains()
{
return $this->items;
}
}

View File

@ -0,0 +1,167 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api\Domain;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* Represents domain information in its simplest form.
*
* @author Sean Johnson <sean@ramcloud.io>
*/
class SimpleDomain implements CreatableFromArray
{
/**
* @var \DateTime
*/
private $createdAt;
/**
* @var string
*/
private $smtpLogin;
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $smtpPassword;
/**
* @var bool
*/
private $wildcard;
/**
* @var string
*/
private $spamAction;
/**
* @var string
*/
private $state;
/**
* @param array $data
*
* @return SimpleDomain
*/
public static function createFromArray(array $data)
{
Assert::isArray($data);
Assert::keyExists($data, 'name');
Assert::keyExists($data, 'smtp_login');
Assert::keyExists($data, 'smtp_password');
Assert::keyExists($data, 'wildcard');
Assert::keyExists($data, 'spam_action');
Assert::keyExists($data, 'state');
Assert::keyExists($data, 'created_at');
return new static(
$data['name'],
$data['smtp_login'],
$data['smtp_password'],
$data['wildcard'],
$data['spam_action'],
$data['state'],
new \DateTime($data['created_at'])
);
}
/**
* @param string $name
* @param string $smtpLogin
* @param string $smtpPass
* @param bool $wildcard
* @param string $spamAction
* @param string $state
* @param \DateTime $createdAt
*/
public function __construct($name, $smtpLogin, $smtpPassword, $wildcard, $spamAction, $state, \DateTime $createdAt)
{
Assert::string($name);
Assert::string($smtpLogin);
Assert::string($smtpPassword);
Assert::boolean($wildcard);
Assert::string($spamAction);
Assert::string($state);
Assert::isInstanceOf($createdAt, '\DateTime');
$this->name = $name;
$this->smtpLogin = $smtpLogin;
$this->smtpPassword = $smtpPassword;
$this->wildcard = $wildcard;
$this->spamAction = $spamAction;
$this->state = $state;
$this->createdAt = $createdAt;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return string
*/
public function getSmtpUsername()
{
return $this->smtpLogin;
}
/**
* @return string
*/
public function getSmtpPassword()
{
return $this->smtpPassword;
}
/**
* @return bool
*/
public function isWildcard()
{
return $this->wildcard;
}
/**
* @return string
*/
public function getSpamAction()
{
return $this->spamAction;
}
/**
* @return string
*/
public function getState()
{
return $this->state;
}
/**
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
}

View File

@ -0,0 +1,99 @@
<?php
/**
* Copyright (C) 2013-2016 Mailgun.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Resource\Api;
use Mailgun\Assert;
use Mailgun\Resource\CreatableFromArray;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class SimpleResponse implements CreatableFromArray
{
/**
* @var string
*/
private $message;
/**
* Only set when API rate limit is hit and a rate limit response is returned.
*
* @var int
*/
private $retrySeconds = null;
/**
* Only set on calls such as DELETE /v3/domains/.../credentials/<user>.
*
* @var string
*/
private $spec = null;
/**
* @param array $data
*
* @return SimpleResponse
*/
public static function createFromArray(array $data)
{
$message = array_key_exists('message', $data) ? $data['message'] : null;
$retrySeconds = array_key_exists('retry_seconds', $data) ? $data['retry_seconds'] : null;
$spec = array_key_exists('spec', $data) ? $data['spec'] : null;
return new static($message, $retrySeconds, $spec);
}
/**
* @param string|null $message
* @param int|null $retrySeconds
* @param string|null $spec
*/
public function __construct($message, $retrySeconds, $spec)
{
Assert::nullOrString($message);
Assert::nullOrInteger($retrySeconds);
Assert::nullOrString($spec);
$this->message = $message;
$this->retrySeconds = $retrySeconds;
$this->spec = $spec;
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @return string
*/
public function getSpec()
{
return $this->spec;
}
/**
* @return bool
*/
public function isRateLimited()
{
return null !== $this->retrySeconds;
}
/**
* @return int
*/
public function getRetrySeconds()
{
return $this->retrySeconds;
}
}

View File

@ -29,14 +29,15 @@ class StatsTest extends TestCase
$api->total('domain', $data);
}
/**
* expectedException \Mailgun\Exception\InvalidArgumentException.
*/
//public function testTotalInvalidArgument()
//{
// $api = $this->getApiMock();
// $api->total('');
//}
// /**
// * @expectedException \Mailgun\Exception\InvalidArgumentException
// */
// public function testTotalInvalidArgument()
// {
// $api = $this->getApiMock();
//
// $api->total('');
// }
public function testAll()
{
@ -53,12 +54,13 @@ class StatsTest extends TestCase
$api->all('domain', $data);
}
/*
* expectedException \Mailgun\Exception\InvalidArgumentException
*/
//public function testAllInvalidArgument()
//{
// $api = $this->getApiMock();
// $api->all('');
//}
// /**
// * @expectedException \Mailgun\Exception\InvalidArgumentException
// */
// public function testAllInvalidArgument()
// {
// $api = $this->getApiMock();
//
// $api->all('');
// }
}

View File

@ -8,6 +8,34 @@ namespace Mailgun\Tests\Api;
*/
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
/**
* Private Mailgun API key.
*
* @var string
*/
protected $apiPrivKey;
/**
* Public Mailgun API key.
*
* @var string
*/
protected $apiPubKey;
/**
* Domain used for API testing.
*
* @var string
*/
protected $testDomain;
public function __construct()
{
$this->apiPrivKey = getenv('MAILGUN_PRIV_KEY');
$this->apiPubKey = getenv('MAILGUN_PUB_KEY');
$this->testDomain = getenv('MAILGUN_DOMAIN');
}
abstract protected function getApiClass();
protected function getApiMock()
@ -28,8 +56,20 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
->getMock();
return $this->getMockBuilder($this->getApiClass())
->setMethods(['get', 'post', 'postRaw', 'delete', 'put'])
->setMethods(
[
'get',
'post', 'postRaw', 'postMultipart',
'delete', 'deleteMultipart',
'put', 'putMultipart',
]
)
->setConstructorArgs([$httpClient, $requestClient, $serializer])
->getMock();
}
protected function getMailgunClient()
{
return new \Mailgun\Mailgun($this->apiPrivKey);
}
}

View File

@ -0,0 +1,352 @@
<?php
/*
* Copyright (C) 2013-2016 Mailgun
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Tests\Integration;
use Mailgun\Tests\Api\TestCase;
use Mailgun\Resource\Api\SimpleResponse;
use Mailgun\Resource\Api\Domain\Credential;
use Mailgun\Resource\Api\Domain\CredentialListResponse;
use Mailgun\Resource\Api\Domain\DeliverySettingsResponse;
use Mailgun\Resource\Api\Domain\DeliverySettingsUpdateResponse;
use Mailgun\Resource\Api\Domain\SimpleDomain;
/**
* @author Sean Johnson <sean@mailgun.com>
*/
class DomainApiTest extends TestCase
{
protected function getApiClass()
{
return 'Mailgun\Api\Domains';
}
/**
* Performs `GET /v3/domains` and ensures $this->testDomain exists
* in the returned list.
*/
public function testDomainsList()
{
$mg = $this->getMailgunClient();
$domainList = $mg->getDomainApi()->listAll();
$found = false;
foreach ($domainList->getDomains() as $domain) {
if ($domain->getName() === $this->testDomain) {
$found = true;
}
}
$this->assertContainsOnlyInstancesOf(SimpleDomain::class, $domainList->getDomains());
$this->assertTrue($found);
}
/**
* Performs `GET /v3/domains/<domain>` and ensures $this->testDomain
* is properly returned.
*/
public function testDomainGet()
{
$mg = $this->getMailgunClient();
$domain = $mg->getDomainApi()->info($this->testDomain);
$this->assertNotNull($domain);
$this->assertNotNull($domain->getDomain());
$this->assertNotNull($domain->getInboundDNSRecords());
$this->assertNotNull($domain->getOutboundDNSRecords());
$this->assertEquals($domain->getDomain()->getState(), 'active');
}
/**
* Performs `DELETE /v3/domains/<domain>` on a non-existent domain.
*/
public function testRemoveDomain_NoExist()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->remove('example.notareal.tld');
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Domain not found', $ret->getMessage());
}
/**
* Performs `POST /v3/domains` to attempt to create a domain with valid
* values.
*/
public function testDomainCreate()
{
$mg = $this->getMailgunClient();
$domain = $mg->getDomainApi()->create(
'example.notareal.tld', // domain name
'exampleOrgSmtpPassword12', // smtp password
'tag', // default spam action
false // wildcard domain?
);
$this->assertNotNull($domain);
$this->assertNotNull($domain->getDomain());
$this->assertNotNull($domain->getInboundDNSRecords());
$this->assertNotNull($domain->getOutboundDNSRecords());
}
/**
* Performs `POST /v3/domains` to attempt to create a domain with duplicate
* values.
*/
public function testDomainCreate_DuplicateValues()
{
$mg = $this->getMailgunClient();
$domain = $mg->getDomainApi()->create(
'example.notareal.tld', // domain name
'exampleOrgSmtpPassword12', // smtp password
'tag', // default spam action
false // wildcard domain?
);
$this->assertNotNull($domain);
$this->assertInstanceOf(SimpleResponse::class, $domain);
$this->assertEquals('This domain name is already taken', $domain->getMessage());
}
/**
* Performs `DELETE /v3/domains/<domain>` to remove a domain from the account.
*/
public function testRemoveDomain()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->remove('example.notareal.tld');
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Domain has been deleted', $ret->getMessage());
}
/**
* Performs `POST /v3/domains/<domain>/credentials` to add a credential pair
* to the domain.
*/
public function testCreateCredential()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->newCredential(
$this->testDomain,
'user-test@'.$this->testDomain,
'Password.01!'
);
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Created 1 credentials pair(s)', $ret->getMessage());
}
/**
* Performs `POST /v3/domains/<domain>/credentials` to attempt to add an invalid
* credential pair.
*
* @expectedException InvalidArgumentException
*/
public function testCreateCredentialBadPasswordLong()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->newCredential(
$this->testDomain,
'user-test',
'ExtremelyLongPasswordThatCertainlyWillNotBeAccepted'
);
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
}
/**
* Performs `POST /v3/domains/<domain>/credentials` to attempt to add an invalid
* credential pair.
*
* @expectedException InvalidArgumentException
*/
public function testCreateCredentialBadPasswordShort()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->newCredential(
$this->testDomain,
'user-test',
'no'
);
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
}
/**
* Performs `GET /v3/domains/<domain>/credentials` to get a list of active credentials.
*/
public function testListCredentials()
{
$mg = $this->getMailgunClient();
$found = false;
$ret = $mg->getDomainApi()->listCredentials($this->testDomain);
$this->assertNotNull($ret);
$this->assertInstanceOf(CredentialListResponse::class, $ret);
$this->assertContainsOnlyInstancesOf(Credential::class, $ret->getCredentials());
foreach ($ret->getCredentials() as $cred) {
if ($cred->getLogin() === 'user-test@'.$this->testDomain) {
$found = true;
}
}
$this->assertTrue($found);
}
/**
* Performs `GET /v3/domains/<domain>/credentials` on a non-existent domain.
*/
public function testListCredentialsBadDomain()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->listCredentials('mailgun.org');
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Domain not found: mailgun.org', $ret->getMessage());
}
/**
* Performs `PUT /v3/domains/<domain>/credentials/<login>` to update a credential's
* password.
*/
public function testUpdateCredential()
{
$login = 'user-test@'.$this->testDomain;
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->updateCredential(
$this->testDomain,
$login,
'Password..02!'
);
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Password changed', $ret->getMessage());
}
/**
* Performs `PUT /v3/domains/<domain>/credentials/<login>` with a bad password.
*
* @expectedException InvalidArgumentException
*/
public function testUpdateCredentialBadPasswordLong()
{
$login = 'user-test@'.$this->testDomain;
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->updateCredential(
$this->testDomain,
$login,
'ThisIsAnExtremelyLongPasswordThatSurelyWontBeAccepted'
);
$this->assertNotNull($ret);
}
/**
* Performs `PUT /v3/domains/<domain>/credentials/<login>` with a bad password.
*
* @expectedException InvalidArgumentException
*/
public function testUpdateCredentialBadPasswordShort()
{
$login = 'user-test@'.$this->testDomain;
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->updateCredential(
$this->testDomain,
$login,
'no'
);
$this->assertNotNull($ret);
}
/**
* Performs `DELETE /v3/domains/<domain>/credentials/<login>` to remove a credential
* pair from a domain.
*/
public function testRemoveCredential()
{
$login = 'user-test@'.$this->testDomain;
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->deleteCredential(
$this->testDomain,
$login
);
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Credentials have been deleted', $ret->getMessage());
$this->assertEquals($login, $ret->getSpec());
}
/**
* Performs `DELETE /v3/domains/<domain>/credentials/<login>` to remove an invalid
* credential pair from a domain.
*/
public function testRemoveCredentialNoExist()
{
$login = 'user-noexist-test@'.$this->testDomain;
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->deleteCredential(
$this->testDomain,
$login
);
$this->assertNotNull($ret);
$this->assertInstanceOf(SimpleResponse::class, $ret);
$this->assertEquals('Credentials not found', $ret->getMessage());
}
/**
* Performs `GET /v3/domains/<domain>/connection` to retrieve connection settings.
*/
public function testGetDeliverySettings()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->getDeliverySettings($this->testDomain);
$this->assertNotNull($ret);
$this->assertInstanceOf(DeliverySettingsResponse::class, $ret);
$this->assertTrue(is_bool($ret->getSkipVerification()));
$this->assertTrue(is_bool($ret->getRequireTLS()));
}
/**
* Performs `PUT /v3/domains/<domain>/connection` to set connection settings.
*/
public function testSetDeliverySettings()
{
$mg = $this->getMailgunClient();
$ret = $mg->getDomainApi()->updateDeliverySettings(
$this->testDomain,
true,
false
);
$this->assertNotNull($ret);
$this->assertInstanceOf(DeliverySettingsUpdateResponse::class, $ret);
$this->assertEquals('Domain connection settings have been updated, may take 10 minutes to fully propagate', $ret->getMessage());
$this->assertEquals(true, $ret->getRequireTLS());
$this->assertEquals(false, $ret->getSkipVerification());
}
}