PHP code example of graystackit / laravel-ahasend-api

1. Go to this page and download the library: Download graystackit/laravel-ahasend-api library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

graystackit / laravel-ahasend-api example snippets


use GraystackIT\Ahasend\AhasendService;

class OrderController
{
    public function __construct(private readonly AhasendService $mailer) {}

    public function confirm(): void
    {
        $this->mailer->sendHtml(
            to:          [['email' => '[email protected]', 'name' => 'Jane']],
            subject:     'Order confirmed',
            htmlContent: '<p>Your order is confirmed!</p>',
            textContent: 'Your order is confirmed!',
        );
    }
}

$mailer->sendText(
    to:          [['email' => '[email protected]']],
    subject:     'Hello',
    textContent: 'Hello from Ahasend!',
);

$mailer->sendHtml(
    to:          [['email' => '[email protected]']],
    subject:     'Hello',
    htmlContent: '<h1>Hello!</h1>',
    textContent: 'Hello!',   // optional plain-text fallback
);

$mailer->sendWithAttachments(
    to:          [['email' => '[email protected]']],
    subject:     'Your invoice',
    attachments: [
        ['path' => storage_path('invoices/inv-001.pdf')],           // file path
        ['name' => 'data.csv', 'content' => $csvBase64, 'mime_type' => 'text/csv'], // raw
    ],
    htmlContent: '<p>Please find your invoice attached.</p>',
);

$mailer->sendWithAttachments(
    to:          [['email' => '[email protected]']],
    subject:     'Where to click',
    attachments: [
        ['name' => 'step-1.png', 'content' => $png, 'mime_type' => 'image/png', 'content_id' => 'step-1@app'],
    ],
    htmlContent: '<p>Click here:</p><img src="cid:step-1@app">',
);

$mailer->sendTemplate(
    to:            [['email' => '[email protected]']],
    templateId:    'tmpl-uuid-1',
    substitutions: ['name' => 'Alice', 'order_id' => '1234'],
);

$mailer->sendHtml(
    to:          [['email' => '[email protected]']],
    subject:     'Test',
    htmlContent: '<p>Hi</p>',
    cc:          [['email' => '[email protected]']],
    bcc:         [['email' => '[email protected]']],
);

use GraystackIT\Ahasend\Data\EmailMessage;

$message = new EmailMessage(
    fromEmail:   '[email protected]',
    fromName:    'Sender',
    to:          [['email' => '[email protected]']],
    subject:     'Custom',
    htmlContent: '<p>Hello</p>',
);

$ahasendMessageId = $mailer->send($message);

// In EventServiceProvider or a listener class:
Event::listen(MailDelivered::class, function (MailDelivered $event): void {
    // $event->messageId, $event->recipient, $event->deliveryAttempt, $event->payload
});

// config/mail.php
'mailers' => [
    // ... other mailers ...

    'ahasend' => [
        'transport' => 'ahasend',
    ],
],

use App\Mail\OrderShipped;
use Illuminate\Support\Facades\Mail;

// Uses the default mailer if MAIL_MAILER=ahasend
Mail::to('[email protected]')->send(new OrderShipped($order));

// Or target the driver explicitly
Mail::mailer('ahasend')
    ->to('[email protected]')
    ->cc('[email protected]')
    ->send(new OrderShipped($order));



namespace App\Mail;

use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;

class OrderShipped extends Mailable
{
    public function __construct(public readonly Order $order) {}

    public function envelope(): Envelope
    {
        return new Envelope(subject: 'Your order has shipped');
    }

    public function content(): Content
    {
        return new Content(
            html: 'emails.order-shipped',   // resources/views/emails/order-shipped.blade.php
            text: 'emails.order-shipped-text',
        );
    }

    public function attachments(): array
    {
        return [
            Attachment::fromPath(storage_path("invoices/{$this->order->id}.pdf"))
                ->as('invoice.pdf')
                ->withMime('application/pdf'),
        ];
    }
}

use GraystackIT\Ahasend\Traits\TracksAhasendMail;
use Illuminate\Mail\Mailable;

class OrderShipped extends Mailable
{
    use TracksAhasendMail;

    public function build(): self
    {
        $this->initAhasendTracking(recipient: $this->order->email);

        return $this->subject('Your order has shipped')
                    ->view('emails.order-shipped');
    }
}

use GraystackIT\Ahasend\Services\MessageService;
use GraystackIT\Ahasend\Enums\MessageStatus;

class MyController
{
    public function __construct(private readonly MessageService $messages) {}
}

$message = $messages->get('msg-abc123');

echo $message->id;            // 'msg-abc123'
echo $message->subject;       // 'Hello World'
echo $message->sender;        // '[email protected]'
echo $message->recipient;     // '[email protected]'
echo $message->status->value; // 'delivered'
echo $message->status->isTerminal(); // true
echo $message->direction;             // 'outbound'
echo $message->numAttempts;           // 1
echo $message->clickCount;            // 0
echo $message->openCount;             // 1
echo $message->bounceClassification;  // null unless is_bounce_notification

$result = $messages->list(
    limit:     25,                       // optional — max results to return
    after:     'cursor-xyz',             // optional — cursor for the next page
    before:    'cursor-abc',             // optional — cursor for the previous page
    status:    'delivered',              // optional
    sender:    '[email protected]',     // optional
    recipient: '[email protected]',  // optional
    tags:      'welcome',                // optional — comma-separated
    fromTime:  '2026-01-01T00:00:00Z',   // optional — RFC3339
    toTime:    '2026-01-31T23:59:59Z',   // optional — RFC3339
);

foreach ($result['data'] as $message) {
    echo $message->id . ': ' . $message->subject;
}

// $result['pagination'] contains has_more / next_cursor / previous_cursor

$cancelled = $messages->cancel('msg-scheduled-001'); // true on success

use GraystackIT\Ahasend\Services\SmtpCredentialService;

class MyController
{
    public function __construct(private readonly SmtpCredentialService $smtp) {}
}

// Global credential (can send from any domain)
$credential = $smtp->create('My Application');

// Scoped credential (restricted to specific domains)
$credential = $smtp->create(
    name:    'My Application',
    scope:   'scoped',
    domains: ['yourdomain.com', 'anotherdomain.com'],
);

// Sandbox credential (no real emails sent)
$credential = $smtp->create('Test App', sandbox: true);

// Save the password — the API will not return it again.
echo $credential->id;       // 'cred-xyz'
echo $credential->username; // 'smtp_my_application'
echo $credential->password; // 'generated-secret' (only available on create)
echo $credential->sandbox;  // bool
echo $credential->scope;    // 'global' or 'scoped'
echo $credential->domains;  // string[] — the domains it's scoped to; empty when scope is 'global'

$credentials = $smtp->list(
    limit:  10,           // optional
    after:  'cursor-xyz', // optional
    before: 'cursor-abc', // optional
);

foreach ($credentials as $cred) {
    echo $cred->id . ': ' . $cred->name;
}

$credential = $smtp->get('cred-xyz');

$smtp->delete('cred-xyz'); // true on success

use GraystackIT\Ahasend\Services\SuppressionService;

class MyController
{
    public function __construct(private readonly SuppressionService $suppressions) {}
}

$suppression = $suppressions->create(
    email:     '[email protected]',
    expiresAt: '2026-12-31T00:00:00Z', // RFC3339 datetime — n
);

echo $suppression->id;     // 'sup-xyz'
echo $suppression->email;  // '[email protected]'

$result = $suppressions->list(
    limit:    50,                    // optional
    after:    'cursor-xyz',          // optional
    before:   'cursor-abc',          // optional
    domain:   'example.com',         // optional — filter by sending domain
    email:    '[email protected]',    // optional — filter by recipient email
    fromTime: '2026-01-01T00:00:00Z', // optional — RFC3339, created after
    toTime:   '2026-01-31T23:59:59Z', // optional — RFC3339, created before
);

foreach ($result['data'] as $suppression) {
    echo $suppression->email;
}

// $result['pagination'] contains has_more / next_cursor / previous_cursor

$suppressions->delete('[email protected]'); // true on success
$suppressions->delete('[email protected]', domain: 'example.com'); // scoped to one domain

$suppressions->deleteAll(); // true on success — wipes the entire account list
$suppressions->deleteAll(domain: 'example.com'); // wipes only suppressions for this domain

use GraystackIT\Ahasend\Services\ReportService;

class MyController
{
    public function __construct(private readonly ReportService $reports) {}
}

$buckets = $reports->bounceStatistics(
    fromTime:         '2024-01-01T00:00:00Z', // optional
    toTime:           '2024-01-31T23:59:59Z', // optional
    senderDomain:     'gmail.com',             // optional — filter by sending domain
    recipientDomains: 'gmail.com,outlook.com', // optional — comma-separated
    tags:             'transactional',         // optional — comma-separated
    groupBy:          'day',                   // optional — hour, day, week, month
);

foreach ($buckets as $bucket) {
    echo $bucket->fromTimestamp . ' – ' . $bucket->toTimestamp . "\n";

    foreach ($bucket->bounces as $bounce) {
        echo "  {$bounce['classification']}: {$bounce['count']}\n";
    }
}

$buckets = $reports->deliverabilityBreakdown(
    fromTime:         '2024-01-01T00:00:00Z', // optional
    toTime:           '2024-01-31T23:59:59Z', // optional
    senderDomain:     'yourdomain.com',        // optional
    recipientDomains: 'gmail.com,outlook.com', // optional — comma-separated
    tags:             'transactional,welcome', // optional — comma-separated
    groupBy:          'day',                   // optional — hour, day, week, month
);

foreach ($buckets as $bucket) {
    echo $bucket->fromTimestamp . ': ' . $bucket->deliveredCount . ' delivered, ' . $bucket->bouncedCount . ' bounced';
}

$buckets = $reports->deliveryTimeAnalytics(
    fromTime:         '2024-01-01T00:00:00Z', // optional
    toTime:           '2024-01-31T23:59:59Z', // optional
    senderDomain:     'yahoo.com',             // optional
    recipientDomains: 'yahoo.com',             // optional — comma-separated
    tags:             'transactional',         // optional — comma-separated
    groupBy:          'day',                   // optional — hour, day, week, month
);

foreach ($buckets as $bucket) {
    echo $bucket->fromTimestamp . ': avg ' . $bucket->avgDeliveryTime . 's across ' . $bucket->deliveredCount . ' messages';

    foreach ($bucket->deliveryTimes as $byDomain) {
        echo "  {$byDomain['recipient_domain']}: {$byDomain['delivery_time']}s ({$byDomain['count']} messages)\n";
    }
}

use GraystackIT\Ahasend\Exceptions\AhasendException;

try {
    $messages->get('nonexistent-id');
} catch (AhasendException $e) {
    echo $e->getCode();    // 404
    echo $e->getMessage(); // "Ahasend API error [404]: ..."
}

use GraystackIT\Ahasend\Services\DomainManager;

$domains = app(DomainManager::class);

// $owner is any Eloquent model — the package never interprets it.
$domain = $domains->add('acme.at', $owner);

foreach ($domain->outstandingRecords() as $record) {
    echo "{$record->type->value}  {$record->host}  {$record->content}";
}

$domain = $domains->refresh($domain);   // "check DNS" button

$domain->isVerified();                  // true once every 

Schedule::command('ahasend:domains:poll')->hourly();
Schedule::command('ahasend:domains:expire')->daily();

use GraystackIT\Ahasend\Exceptions\DomainLimitExceededException;

try {
    $domains->add('second.at', $owner);
} catch (DomainLimitExceededException $e) {
    $e->blockingDomains;   // ['first.at'] — offer "check DNS" or "delete" for these
}

use GraystackIT\Ahasend\Support\InboundChannels;

app(InboundChannels::class)->register(
    name: 'payslip',                                      // → POST /ahasend/inboundmail/payslip
    domain: config('payroll.mail.receiving_domain'),
    secret: config('payroll.mail.inbound_secret'),        // e.g. PAYROLL_MAIL_SECRET
    queue: null,                                          // optional, see "Handoff" below
);

$this->app->bind(InboundScreen::class, VirusScreen::class);

final class VirusScreen implements InboundScreen
{
    public function screen(InboundDelivery $delivery): ScreenVerdict
    {
        // ScreenVerdict::accept()      — hand it to the listeners
        // ScreenVerdict::discard()     — drop it; no listener ever sees it
        // ScreenVerdict::defer(300)    — ask again in five minutes
    }

    public function gaveUp(InboundDelivery $delivery): void
    {
        // Deferred until the retry window closed; tell the sender if you like.
    }
}

'secrets' => [
    'postbox.example.com' => env('AHASEND_INBOUND_SECRET_POSTBOX'),
    'tickets.example.com' => env('AHASEND_INBOUND_SECRET_TICKETS'),
],

use GraystackIT\Ahasend\Events\InboundMailReceived;

class RouteInboundMail
{
    public function handle(InboundMailReceived $event): void
    {
        // With a handoff queue this already runs in a worker. Without one, queue
        // the real work: AhaSend retries on any non-2xx response, so slow
        // synchronous handling produces duplicates. $deliveryId is stable across
        // those retries — use it as the idempotency key.
        ProcessInboundMail::dispatch($event->message, $event->deliveryId);
    }
}

$message->text();               // reply-stripped body when the route produced one
$message->parentMessageIds();   // In-Reply-To, then References newest-first
$message->isAutomated();        // Auto-Submitted / Precedence / List-Id / X-Auto-Response-Suppress
$message->inlineAttachments();  // parts referenced by cid: in the HTML body
$message->attachments[0]->contents();   // decoded bytes
$message->spamScore;
$message->raw;                  // anything not modelled yet
bash
php artisan vendor:publish --tag=ahasend-config
bash
php artisan vendor:publish --tag=ahasend-migrations
php artisan migrate