Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ Email marketing:
General API:
- Templates CRUD – [`templates/all.php`](examples/templates/all.php)
- API tokens CRUD – [`api-tokens/all.php`](examples/api-tokens/all.php)
- Sub-accounts (list, create, delete) – [`sub-accounts/all.php`](examples/sub-accounts/all.php)
- Billing info – [`general/billing.php`](examples/general/billing.php)
- Accounts info – [`general/accounts.php`](examples/general/accounts.php)
- Permissions listing – [`general/permissions.php`](examples/general/permissions.php)
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Central index of runnable example scripts demonstrating Mailtrap PHP SDK feature
| Purpose | File |
|---------|------|
| API tokens CRUD | [`api-tokens/all.php`](api-tokens/all.php) |
| Sub-accounts (list, create, delete) | [`sub-accounts/all.php`](sub-accounts/all.php) |
| Accounts info | [`general/accounts.php`](general/accounts.php) |
| Billing info | [`general/billing.php`](general/billing.php) |
| Permissions listing | [`general/permissions.php`](general/permissions.php) |
Expand Down
24 changes: 22 additions & 2 deletions examples/sub-accounts/all.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

require __DIR__ . '/../../vendor/autoload.php';

$organizationId = $_ENV['MAILTRAP_ORGANIZATION_ID'];
$organizationId = (int) $_ENV['MAILTRAP_ORGANIZATION_ID'];
$config = new Config($_ENV['MAILTRAP_API_KEY']); #your API token from here https://mailtrap.io/api-tokens
$subAccounts = (new MailtrapGeneralClient($config))->organization($organizationId)->subAccounts();

Expand All @@ -31,7 +31,27 @@
try {
$response = $subAccounts->createSubAccount('My new sub-account');

var_dump(ResponseHelper::toArray($response));
$subAccount = ResponseHelper::toArray($response);
$subAccountId = $subAccount['id']; // deleted by the example below

var_dump($subAccount);
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";

exit(1); // the example below deletes the sub-account created here
}

/**
* Delete a sub-account from the organization. Requires organization admin permissions.
* The deletion is permanent and removes all sub-account data; deleting the organization's last
* sub-account also deletes the organization. A repeated call for the same ID returns 404.
*
* DELETE https://mailtrap.io/api/organizations/{organization_id}/sub_accounts/{sub_account_id}
*/
try {
$response = $subAccounts->deleteSubAccount($subAccountId);

echo $response->getStatusCode(); // 204
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
18 changes: 18 additions & 0 deletions src/Api/General/SubAccount.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ public function createSubAccount(string $name): ResponseInterface
);
}

/**
* Delete a sub-account by ID. Requires organization admin permissions.
* The organization must have the Organization & Sub-accounts feature enabled; otherwise the call fails with 403.
* The deletion is permanent and removes all sub-account data; deleting the organization's last
* sub-account also deletes the organization. A repeated call for the same ID returns 404.
* A concurrent deletion of the same sub-account fails with 409.
* Rate limit: 10 requests per minute per organization.
*
* @param int $subAccountId
* @return ResponseInterface
*/
public function deleteSubAccount(int $subAccountId): ResponseInterface
{
return $this->handleResponse(
$this->httpDelete($this->getBasePath() . '/' . $subAccountId)
);
}

public function getOrganizationId(): int
{
return $this->organizationId;
Expand Down
50 changes: 49 additions & 1 deletion tests/Api/General/SubAccountTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ protected function setUp(): void
{
parent::setUp();
$this->subAccount = $this->getMockBuilder(SubAccount::class)
->onlyMethods(['httpGet', 'httpPost'])
->onlyMethods(['httpGet', 'httpPost', 'httpDelete'])
->setConstructorArgs([$this->getConfigMock(), self::FAKE_ORGANIZATION_ID])
->getMock();
}
Expand Down Expand Up @@ -110,6 +110,54 @@ public function testCreateSubAccountFailsWithValidationError(): void
$this->subAccount->createSubAccount($invalidName);
}

public function testDeleteSubAccount(): void
{
$subAccountId = 1;

$this->subAccount->expects($this->once())
->method('httpDelete')
->with(AbstractApi::DEFAULT_HOST . '/api/organizations/' . self::FAKE_ORGANIZATION_ID . '/sub_accounts/' . $subAccountId)
->willReturn(new Response(204));

$response = $this->subAccount->deleteSubAccount($subAccountId);

$this->assertEquals(204, $response->getStatusCode());
}

public function testDeleteSubAccountFailsWithForbidden(): void
{
$subAccountId = 1;

$this->subAccount->expects($this->once())
->method('httpDelete')
->with(AbstractApi::DEFAULT_HOST . '/api/organizations/' . self::FAKE_ORGANIZATION_ID . '/sub_accounts/' . $subAccountId)
->willReturn(
new Response(403, ['Content-Type' => 'application/json'], json_encode(['errors' => 'Access forbidden']))
);

$this->expectException(HttpClientException::class);
$this->expectExceptionMessage('Access forbidden');

$this->subAccount->deleteSubAccount($subAccountId);
}

public function testDeleteSubAccountFailsWithNotFound(): void
{
$subAccountId = 1;

$this->subAccount->expects($this->once())
->method('httpDelete')
->with(AbstractApi::DEFAULT_HOST . '/api/organizations/' . self::FAKE_ORGANIZATION_ID . '/sub_accounts/' . $subAccountId)
->willReturn(
new Response(404, ['Content-Type' => 'application/json'], json_encode(['error' => 'Not Found']))
);

$this->expectException(HttpClientException::class);
$this->expectExceptionMessage('Not Found');

$this->subAccount->deleteSubAccount($subAccountId);
}

private function getExpectedSubAccountResponse(int $id = 1, string $name = 'My sub-account'): array
{
return [
Expand Down
Loading