Skip to the documentation
PHP

Changelog

Every release of the package, newest first.

0.0.1

The first release of the PHP package. It has a method for every one of the 684 methods of the TypeScript SDK, in 53 namespaces, each under its TypeScript name, and a parity check in the package’s own build proves that every one sends the same request as its TypeScript twin, retries the same way and returns the same shape.

  • Nextmail\Nextmail has a property for every namespace, from emails, threads and templates to automations, bookings and connectedMailboxes. A request body is an associative array whose keys keep the API’s camelCase names, the options of a call are named arguments such as idempotencyKey: and limit:, and a response comes back as the decoded associative array.
  • new Nextmail() and Nextmail::createClient() take apiKey: or accessToken:, and accessToken: also takes a callable that returns a token, called before every request. Anything you leave out is read from NEXTMAIL_API_KEY, NEXTMAIL_ACCESS_TOKEN and NEXTMAIL_BASE_URL, and baseUrl:, timeout:, maxRetries:, headers:, userAgent: and httpClient: set the rest. Every method takes apiKey:, or inboxToken: on tempMail, to act with another credential for one call.
  • Nextmail::init(), Nextmail::getClient() and Nextmail::resetClient() manage one shared client, and Nextmail::createTempMail() opens disposable inboxes with no credential.
  • Every paginated resource has list, which returns one Nextmail\Result\Page with items, hasMore and nextCursor, listAll, which returns every item as an array, and iterate, which returns a Generator that fetches the next page only when it gets there.
  • An API refusal throws Nextmail\Exception\ApiException or its subclass for the error type, such as NotFoundException, ValidationException or RateLimitException, with status, type, errorCode, param, docUrl, requestId, retryAfterSeconds and fields, and methods such as isValidation(), isStepUpRequired() and isRetryable(). No response at all throws NetworkException, with isTimeout() when the deadline passed, and a mistake in the call itself throws InvalidArgumentException before anything is sent. Every exception the package throws implements Nextmail\Exception\NextmailException.
  • Reads, sends and every write that is safe to repeat are retried on 408, 500, 502, 503 and 504 with backoff, and on a 429 only when its Retry-After is a minute or less. A send carries an idempotency key that its retries reuse, so a retry never sends a second message. timeout: bounds a whole attempt, and uploads wait at least ten minutes.
  • Nextmail::verifyWebhookSignature() checks a delivery in constant time, refuses one more than five minutes old and returns the decoded event. It reads the signature from an array of headers in any case, from $_SERVER, from a Symfony or Laravel header bag, or from a PSR-7 message.
  • The helpers of the TypeScript SDK are here too, such as Nextmail::toBase64() and Nextmail::resolveLanguage(), and every value set it exports is a class in Nextmail\Constants, such as WebhookEvents and ApiScopes, with a values() method for the whole set.
  • Requests go through one cURL handle per client, which keeps its connection open between requests and opens a new one after pcntl_fork. Nextmail\Http\Psr18HttpClient sends them through Guzzle, Symfony HttpClient or any other PSR-18 client instead, and anything that implements Nextmail\Http\HttpClient can take the place of either, which is how a test runs without a network.
  • Credentials stay out of sight: every parameter that carries one is marked #[\SensitiveParameter], no dump of a client or a request shows one, and the client never sends one over plain http: to anything but this machine.
  • When a newer version is on Packagist, the client says so once, on the command line and only on a terminal. disableUpdateNotice: true or NEXTMAIL_DISABLE_UPDATE_NOTICE=1 turns that off.
  • It needs PHP 8.2 or later with the curl and json extensions, and nothing else.