eustasy/browning

Browning: A Lightweight Mailgun Script using Curl.

Maintainers

Package info

github.com/eustasy/browning

pkg:composer/eustasy/browning

Fund package maintenance!

Issuehunt

eustasy

Ko Fi

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 3

Open Issues: 0

1.31 2026-05-31 15:38 UTC

This package is auto-updated.

Last update: 2026-06-03 11:15:22 UTC


README

Normal (PHP) Normal (Markdown) Normal (Security) Test (PHP) CodeQL Maintainability Code Coverage

Browning is a tiny PHP library to send emails with Mailgun, that uses CURL instead of Mailgun's (slightly porky) library. Requires PHP 8.1+ and the cURL extension.

Installation

composer require eustasy/browning

Then include the Composer autoloader:

require 'vendor/autoload.php';

This makes the Eustasy\Browning\Mailer and Eustasy\Browning\Recaptcha classes available.

1. Setup with Mailgun

The cURL extension is required. On Debian/Ubuntu:

sudo apt-get install php-curl

Sign up for Mailgun — the free tier covers 100 emails per day. See pricing for the paid tiers.

Copy the bundled config template out of vendor/, for example to config/browning.php:

cp vendor/eustasy/browning/config/browning.default.php config/browning.php

Open your copy and fill in your details — it's a PHP file that returns a config array (loaded with require in step 2):

<?php

return [
    // Mailgun API URL
    // Replace `<`example.com`>` with your verified Mailgun domain.
    'URL' => 'https://api.mailgun.net/v3/example.com',

    // Mailgun private API key.
    // Get it from "Domain Settings" > "Sending Keys" in your Mailgun dashboard.
    'Key' => '<your-mailgun-api-key>',

    'Default' => [
        'Regards' => 'Example Support',     // Sender display name
        'ReplyTo' => 'support@example.com', // From / reply-to address
    ],

    // Optional reCAPTCHA v2 keys (see section 3).
    'Recaptcha' => [
        'SiteKey' => '<your-recaptcha-site-key>',
        'SecretKey' => '<your-recaptcha-secret-key>',
    ],
];

Add config/browning.php to your .gitignore to avoid committing credentials.

2. Sending email

Build a Mailer from your config and call send():

require 'vendor/autoload.php';

use Eustasy\Browning\Mailer;

$config = require 'config/browning.php';
$mailer = Mailer::fromArray($config);

$result = $mailer->send(
    'recipient@example.com', // Required: recipient address
    'Message Subject',       // Required: subject line
    'Text or HTML body',     // Required: message body
    'Sender Name',           // Optional: overrides Default.Regards
    'reply-to@example.com',  // Optional: overrides Default.ReplyTo
);

if ($result->success) {
    echo 'Email sent successfully.';
} else {
    echo 'Failed to send email: ' . $result->error;
}

send() returns a Eustasy\Browning\Result:

Property Type Description
success bool true if the email was accepted by Mailgun.
error string|null Error message, or null on success.

By default error is a friendly, user-safe message. Pass debug: true to get technical detail instead:

$mailer = Mailer::fromArray($config, debug: true);

Prefer explicit wiring? Construct it directly. The constructor also accepts a custom Transport as its fifth argument — that's how the tests avoid the network:

$mailer = new Mailer(
    apiUrl: 'https://api.mailgun.net/v3/example.com',
    apiKey: $secret,
    fromName: 'Example Support',
    fromAddress: 'support@example.com',
);

3. Setup with reCAPTCHA

To protect a form with Google reCAPTCHA v2, add your keys under Recaptcha in the config — SiteKey for the form, SecretKey for verification.

Keys come from the Google reCAPTCHA admin console.

4. CAPTCHA form

Add the widget to your HTML form, using your site key:

<script src="https://www.google.com/recaptcha/api.js"></script>

<form method="post" action="">
    <input type="email" name="dear" placeholder="Recipient email" required>
    <input type="text" name="subject" placeholder="Subject" required>
    <textarea name="message" placeholder="Message" required></textarea>
    <div class="g-recaptcha" data-sitekey="your-site-key"></div>
    <button type="submit">Send</button>
</form>

5. CAPTCHA validation

Verify the response server-side before sending:

use Eustasy\Browning\Mailer;
use Eustasy\Browning\Recaptcha;

$config = require 'config/browning.php';

$check = Recaptcha::fromArray($config)->verify(
    $_POST['g-recaptcha-response'] ?? null,
    $_SERVER['REMOTE_ADDR'] ?? null, // Optional: user's IP address
);

if (! $check->success) {
    echo 'reCAPTCHA failed. Please go back and try again.';
} else {
    // reCAPTCHA passed — send the email.
    $result = Mailer::fromArray($config)->send(
        $_POST['dear'] ?? '',
        $_POST['subject'] ?? '',
        $_POST['message'] ?? '',
    );
}

verify() returns a Eustasy\Browning\RecaptchaResult with success (bool), errorCodes (string[]), and error (string|null).