Search by

mailengin / mailengin-php

vishveshrathore20

Official PHP SDK for the MailEngin Email API

v0.1.0 2026-08-31 12:04 UTC

This package is auto-updated.

Last update: 2026-09-01 07:37:41 UTC


README

PHP Composer License: MIT

The official PHP SDK for sending transactional email through MailEngin. It provides typed request and response objects, Guzzle integration, configurable timeouts, and structured exceptions.

Important

This package is for server-side applications only. Never expose a MailEngin API key in JavaScript, browser, mobile, or other client-distributed code.

Requirements

  • PHP 8.2 or newer
  • Composer 2
  • A MailEngin API key and verified sending domain

Installation

composer require mailengin/mailengin-php

Before You Send

  1. Verify a sending domain.
  2. Create an API key and save the full secret.
  3. Create and publish a Developer Template.
  4. Copy the template API name, such as welcome-email.

Store the API key in your server's secret manager or environment:

MAILENGIN_API_KEY=re_your_full_secret_key

MailEngin displays the full key only once. A masked key cannot authenticate requests.

Quick Start

<?php

declare(strict_types=1);

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

use MailEngin\MailEnginClient;
use MailEngin\Model\SendEmailRequest;

$client = new MailEnginClient($_ENV['MAILENGIN_API_KEY']);

$email = $client->emails()->send(new SendEmailRequest(
    to: 'user@example.com',
    fromEmail: 'hello@yourdomain.com',
    templateName: 'welcome-email',
    variables: ['first_name' => 'Asha'],
));

echo $email->id;

The published template supplies the subject and HTML. Values in variables replace matching template variables such as {{first_name}}.

Send One Email

use MailEngin\Model\SendEmailRequest;

$email = $client->emails()->send(new SendEmailRequest(
    to: 'customer@example.com',
    fromEmail: 'hello@yourdomain.com',
    templateName: 'account-verification',
    variables: [
        'first_name' => 'Asha',
        'verification_url' => 'https://yourapp.com/verify/token',
    ],
    replyToMailEngin: true,
));

printf("Queued email %s at %s\n", $email->id, $email->createdAt);

Send request fields

Constructor argument Type Required Description
to string Yes Recipient email address.
templateName ?string Recommended Published template API name or exact display name.
templateId ?string No Legacy template identifier. Prefer templateName.
variables ?array No Values used to render template variables.
subject ?string Raw HTML only Template subject override, or required subject for raw HTML.
fromEmail ?string Recommended Sender on a verified domain authorized for the API key.
html ?string Advanced Raw HTML used when no template is supplied.
replyToMailEngin ?bool No Route recipient replies into the MailEngin inbox.

Exactly one content source is required: templateName, templateId, or html. Raw HTML sends also require subject.

Send Personalized Bulk Email

Bulk requests support up to 1,000 recipients. Request-level variables apply to every recipient; recipient variables take precedence.

use MailEngin\Model\BulkRecipient;
use MailEngin\Model\SendBulkEmailRequest;

$job = $client->emails()->sendBulk(new SendBulkEmailRequest(
    to: [
        new BulkRecipient(
            email: 'asha@example.com',
            variables: ['first_name' => 'Asha'],
        ),
        new BulkRecipient(
            email: 'ben@example.com',
            variables: ['first_name' => 'Ben'],
        ),
    ],
    fromEmail: 'hello@yourdomain.com',
    templateName: 'product-update',
    variables: ['product_name' => 'MailEngin'],
));

printf("Queued %d recipients in job %s\n", $job->queuedCount, $job->jobId);

For the same content without recipient-specific variables, use strings:

$job = $client->emails()->sendBulk(new SendBulkEmailRequest(
    to: ['a@example.com', 'b@example.com'],
    templateName: 'maintenance-notice',
));

A successful bulk response confirms that recipients were queued. It is not a guarantee that every message was delivered.

Send Raw HTML

Published templates are recommended for reusable product email. For a one-off message, provide both subject and html:

$email = $client->emails()->send(new SendEmailRequest(
    to: 'user@example.com',
    fromEmail: 'reports@yourdomain.com',
    subject: 'Your report is ready',
    html: '<h1>Report ready</h1><p>You can download it now.</p>',
));

Sender Selection

MailEngin resolves the sender in this order:

  1. fromEmail supplied in the request.
  2. Sender saved in the published Developer Template.
  3. noreply@<authorized-domain> fallback.

The sender domain must be verified and authorized for the API key. Set the sender in the template or request for predictable production sends.

Error Handling

API, timeout, malformed-response, and network failures throw MailEnginError:

use MailEngin\Exception\MailEnginError;
use MailEngin\Model\SendEmailRequest;

try {
    $client->emails()->send(new SendEmailRequest(
        to: 'user@example.com',
        templateName: 'welcome-email',
    ));
} catch (MailEnginError $error) {
    echo $error->getMessage();
    var_dump($error->status);       // HTTP status, when available
    var_dump($error->errorCode);    // Machine-readable error code
    var_dump($error->requestId);    // Include when contacting support
    var_dump($error->retryAfter);   // Seconds supplied with HTTP 429
    var_dump($error->body);         // Parsed JSON or response text
    var_dump($error->isRetryable());
}

isRetryable() returns true for network errors, timeouts, HTTP 408, HTTP 429, and 5xx responses. The SDK never retries sends automatically because a retry could create a duplicate email until idempotency keys are supported.

Invalid local input, such as an empty recipient or raw HTML without a subject, throws InvalidArgumentException before an API request is made.

Configuration

use MailEngin\MailEnginClient;

$client = new MailEnginClient(
    apiKey: $_ENV['MAILENGIN_API_KEY'],
    baseUrl: 'https://api.mailengin.app',
    timeout: 15.0,
);
Constructor argument Default Description
apiKey None Full server-side MailEngin API key.
baseUrl https://api.mailengin.app Override for local, test, or dedicated environments.
timeout 30.0 Request timeout in seconds.
httpClient New Guzzle client Injectable PSR-compatible ClientInterface implementation.

Framework Integration

Create one client in your dependency-injection container and reuse it. For example, a Laravel service provider can register a singleton:

use Illuminate\Contracts\Foundation\Application;
use MailEngin\MailEnginClient;

$this->app->singleton(MailEnginClient::class, function (Application $app): MailEnginClient {
    return new MailEnginClient((string) config('services.mailengin.api_key'));
});

Configuration belongs in config/services.php, backed by MAILENGIN_API_KEY; do not commit the secret to source control.

Testing With an Injected Client

Use Guzzle's mock handler to test your integration without a real API key or network request:

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use MailEngin\MailEnginClient;

$mock = new MockHandler([
    new Response(200, ['Content-Type' => 'application/json'], json_encode([
        'id' => 'email_123',
        'from' => 'hello@example.com',
        'to' => 'user@example.com',
        'template_name' => 'welcome-email',
        'created_at' => '2026-08-31T12:00:00Z',
    ], JSON_THROW_ON_ERROR)),
]);

$httpClient = new Client(['handler' => HandlerStack::create($mock)]);
$client = new MailEnginClient('test_key', httpClient: $httpClient);

Development

composer install
composer validate --strict
composer analyse
composer test
composer archive --format=zip

See CONTRIBUTING.md for contribution rules and PUBLISHING.md for maintainer release instructions.

Resources

License

Released under the MIT License. Copyright 2026 MailEngin.