PHP client for the Mailcore mail-server control API (users, mailboxes, domains, filters, reports).
Unofficial. Third-party client; not published by Mailcore.
AI-assisted. Code, tests, and docs were written largely by AI (Claude Code) under human direction and review. Review it before relying on it in production.
This is the core package — a PSR-18 client with no framework dependency. For the command-line tool see inboxcom/mailcore-cli; for the Laravel bridge see inboxcom/mailcore-laravel.
composer require inboxcom/mailcore-phpRequires PHP >= 8.4. Guzzle is used by default (it is itself a PSR-18 client), but you can inject any PSR-18 client + PSR-17 request factory.
The default client uses a 30s request timeout and 10s connect timeout; override per client (seconds, 0 disables):
$client = new MailcoreClient('your-api-key', timeout: 60.0, connectTimeout: 5.0);A whole dump from datadump()->fetch() can be large — raise timeout (or pass 0) for it. These options apply only to the default Guzzle client; when you inject your own (below), configure timeouts on it.
use Inboxcom\Mailcore\MailcoreClient;
use Inboxcom\Mailcore\Exception\ConflictException;
$client = new MailcoreClient('your-api-key');
$emails = $client->users()->list(filter: '*', limit: '0,100');
$user = $client->users()->get('holger@example.com'); // returns a User DTO
try {
$client->users()->add('new@example.com', 'S3cretPassw0rd', mailboxplanId: 4);
} catch (ConflictException $e) {
// $e->statusCode === 409, $e->statusMsg === 'User already exists'
}The core carries no Console/Laravel dependency, so it drops into any host:
$client = new MailcoreClient(
apiKey: 'your-api-key',
httpClient: $yourPsr18Client,
requestFactory: $yourPsr17RequestFactory,
);Every non-2xx response throws a subclass of Inboxcom\Mailcore\Exception\ApiException, chosen by HTTP status (NotFoundException, ConflictException, NotAcceptableException, …). The API's statusmsg is preserved on $e->statusMsg for finer branching. Catch MailcoreException to catch everything this package throws. The API key is never included in any exception message.
The core covers all 54 operations of the live Mailcore API, grouped by tag onto resource accessors:
| Accessor | Operations |
|---|---|
users() |
34 — CRUD, aliases (+ list), forwards (+ list), passwords, flags, snapshots/restores, logins, limits, spam tolerance, temporary access |
domains() |
5 — count, add, add alias, list, remove |
mailboxplans() |
1 — list |
mailfilter() |
12 — SMTP-limit/spam-flag feeds, white/blacklists, RBL + CDL lookups |
reports() |
1 — suspicious mailbox activity |
datadump() |
1 — fetch latest (raw bytes) |
Object responses come back as typed models in src/Model; list endpoints return list<Model>. A few binary-outcome endpoints are exposed as predicates (isAvailable(), isReserved(), verifyPassword(), mailfilter()->isListedOnRbl(), mailfilter()->isListedOnCdl()).
The OpenAPI document is generated from #[OA\*] attributes on the resource methods plus the holders in src/Doc, so the spec can't drift from the client. swagger-php is a dev-only dependency and the attributes are inert at runtime.
composer gen:openapi # write build/openapi.yaml
composer openapi:check # generate + validate only (CI gate)
composer docs:swagger # serve Swagger UI at http://localhost:8081/ (PHP only)This package is developed in the Fjordmail/mailcore-sdk monorepo (this repository is a read-only subtree split). Issues, contributions, the live contract suite, and the full compatibility notes against the official v1.23 docs all live there.
MIT — see LICENSE.