Remove specific email from Mailgun queue using message ID

Removing Scheduled Messages from Mailgun Queue

I’m building an email service with PHP and need to cancel specific messages that are scheduled to send later. I can send emails fine and view what’s waiting in the queue, but I want to remove individual emails using their unique message identifier.

Here’s my current email sending setup:

class EmailServiceHandler 
{
    private $emailProvider;
    private $responseHandler;

    public function __construct(EmailApiClient $client, ResponseProcessor $processor)
    {
        $this->emailProvider = $client;
        $this->responseHandler = $processor;
    }

    public function sendScheduledEmail(): ResponseProcessor
    {
        $client = $this->emailProvider->initialize();
        
        $messageData = [
            "from" => $this->emailProvider->getSenderAddress(),
            "to" => $this->getRecipientEmail(),
            "subject" => $this->getEmailSubject(),
            "text" => $this->getMessageBody(),
            "o:deliverytime" => Carbon::now()->addDays(2)->toRfc2822String(),
        ];

        $response = $client->messages()->send($this->emailProvider->getDomain(), $messageData);
        
        $responseData = [
            "messageId" => $response->getId(),
            "status" => $response->getMessage()
        ];

        $this->responseHandler->setData($responseData);
        return $this->responseHandler;
    }
}

The message gets scheduled successfully but I can’t figure out how to delete it before it sends. Is there an API endpoint for removing individual queued messages? The documentation only shows clearing the entire domain queue which is too broad for my needs.

The Problem:

You’re trying to remove specific scheduled emails from the Mailgun queue, but the Mailgun API doesn’t offer a way to delete individual scheduled messages. The API only allows for deleting all messages within a domain, which isn’t suitable for selectively canceling individual emails.

:thinking: Understanding the “Why” (The Root Cause):

Mailgun’s API prioritizes bulk operations for efficiency. Providing an endpoint for deleting single messages from the queue would add significant complexity to their infrastructure, potentially impacting performance and scalability. The design choice reflects a trade-off between granular control and overall system robustness.

:gear: Step-by-Step Guide:

Step 1: Implement a Database-Based Scheduling System:

Instead of relying on Mailgun’s o:deliverytime parameter for scheduling, create your own scheduling mechanism using a database. This gives you complete control over individual email management.

Here’s how you can modify your EmailServiceHandler class:

use Carbon\Carbon;

class EmailServiceHandler 
{
    private $emailProvider;
    private $database; // Add database connection

    public function __construct(EmailApiClient $client, DatabaseConnection $db) // Modify constructor
    {
        $this->emailProvider = $client;
        $this->database = $db; // Initialize database connection
    }

    public function scheduleEmail(): void // Rename function to reflect scheduling
    {
        $messageData = [
            "from" => $this->emailProvider->getSenderAddress(),
            "to" => $this->getRecipientEmail(),
            "subject" => $this->getEmailSubject(),
            "text" => $this->getMessageBody(),
        ];

        $scheduledTime = Carbon::now()->addDays(2);
        $messageId = uniqid(); // Generate unique ID

        $this->database->insert('scheduled_emails', [ // Insert into database
            'id' => $messageId,
            'from' => $messageData['from'],
            'to' => $messageData['to'],
            'subject' => $messageData['subject'],
            'body' => $messageData['text'],
            'scheduled_time' => $scheduledTime->toDateTimeString(),
            'status' => 'pending' // Add a status field
        ]);
    }

    public function sendScheduledEmails(): void
    {
        $pendingEmails = $this->database->select('scheduled_emails', ['status' => 'pending', 'scheduled_time <=' => Carbon::now()->toDateTimeString()]);

        foreach ($pendingEmails as $email) {
            $messageData = [
                "from" => $email['from'],
                "to" => $email['to'],
                "subject" => $email['subject'],
                "text" => $email['body'],
            ];

            $response = $this->emailProvider->send($this->emailProvider->getDomain(), $messageData);

            if ($response->isSuccess()) {
                $this->database->update('scheduled_emails', ['id' => $email['id']], ['status' => 'sent']);
            } else {
                // Handle error appropriately (e.g., retry, log, etc.)
            }
        }
    }

    public function cancelScheduledEmail(string $messageId): void
    {
        $this->database->update('scheduled_emails', ['id' => $messageId], ['status' => 'cancelled']);
    }
}

Step 2: Create a Cron Job (or Scheduled Task):

Set up a cron job (or equivalent scheduled task) to run $emailServiceHandler->sendScheduledEmails() regularly (e.g., every few minutes). This job will fetch pending emails from the database and send them via Mailgun’s immediate send API.

Step 3: Implement Cancellation Logic:

Use the cancelScheduledEmail method to update the status of an email in the database to ‘cancelled’. The cron job will skip emails with a ‘cancelled’ status.

:mag: Common Pitfalls & What to Check Next:

  • Database Design: Ensure your database schema efficiently handles large volumes of scheduled emails. Consider indexing relevant columns (e.g., scheduled_time, status).
  • Error Handling: Implement robust error handling within the cron job and the EmailServiceHandler class to manage failed sends, database errors, or other unexpected issues. Log errors for debugging.
  • Cron Job Reliability: Test your cron job thoroughly to ensure it runs reliably and at the expected frequency. Implement monitoring to detect any failures or delays.
  • Scalability: If you anticipate a large number of scheduled emails, consider using a message queue (e.g., RabbitMQ, Redis) to handle email processing asynchronously for better performance and scalability.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!

Nope, Mailgun doesn’t let you cancel individual scheduled emails once they’re queued. Caught me off guard too when I started using it. I built a workaround by adding a database layer that tracks scheduled messages before they hit Mailgun. When I need to cancel something, I mark it cancelled in my DB and check that status before sending. If it’s already in Mailgun’s queue though, you’re screwed - either wait for it to send or nuke everything. Found this out the hard way after accidentally scheduling hundreds of test emails. I ended up ditching scheduled sends entirely and built my own system with cron jobs and queue workers (using Laravel). Way better since emails stay in your control until you actually want them sent.

Mailgun’s API can’t delete individual messages from the scheduled queue. Once you queue something with o:deliverytime, you’re stuck with it until delivery or you cancel everything domain-wide.

I hit this same wall last year and built a workaround. Skip Mailgun’s scheduling entirely - store your scheduled emails in your own database with a status field. Run a background job every few minutes to check for pending messages. When it’s time to send, the job verifies the message is still active, then hits Mailgun’s immediate send endpoint.

To cancel? Just flip the database status to ‘cancelled’ and your processor ignores it. You get full control over individual messages without fighting Mailgun’s limitations. Yeah, you’re managing your own scheduler, but it’s way more reliable when cancellation matters.

Been there with Mailgun’s limitations. Their API won’t let you delete individual messages from the queue once they’re scheduled. You can only cancel all pending messages for a domain or wait for them to send.

This is why I stopped trying to manage email queues through providers like Mailgun directly. I handle all the scheduling logic myself using automation.

Now I send emails immediately through Mailgun but control timing with Latenode workflows. I create a workflow that waits for the exact delivery time, then triggers the email send. Need to cancel? Just stop the workflow before it executes.

The setup’s simple - create a Latenode scenario that accepts your email data, waits using a delay node for your specified time, then calls Mailgun to send immediately. You get a workflow ID back that you can use to cancel anytime before execution.

This gives you granular control over individual messages and works with any email provider. Plus you can add conditional logic, retry mechanisms, or even switch providers mid-flight if needed.

mailgun’s api really makes it hard if ya wanna cancel queued emails. i switched to redis for my scheduled messages. just save the data with an expiry and have a worker check it every minute. if ya need to cancel, just delete the redis key before it gets sent. much easier!

You’re hitting the same wall everyone does with Mailgun. Their API doesn’t support deleting individual scheduled messages. You can either wait it out or nuke the entire domain queue.

Here’s the thing though - fighting with email providers over scheduling is backwards. I learned this after dealing with similar headaches across multiple platforms.

Flip the approach instead of wrestling with Mailgun’s limitations. Send everything immediately through their API but let automation handle the timing.

I use Latenode for this exact scenario. Create a workflow that receives your email data, waits for your specified delay, then fires the send request to Mailgun. Your PHP code gets back a workflow execution ID instead of dealing with Mailgun’s message queue.

Want to cancel? Just kill that specific workflow execution before it triggers. No database layers, no cron jobs checking statuses, no background workers.

You keep your existing Mailgun setup but gain actual control over cancellation. Plus if you need to modify message content or change recipients before sending, you can update the workflow data on the fly.

Works with any email provider too, so you’re not locked into Mailgun’s quirks.

Nope, Mailgun’s API doesn’t let you delete individual scheduled messages once they’re queued. You can only bulk delete everything for your domain, which is pretty useless most of the time. Here’s what I did instead: I still use Mailgun for sending but handle all the scheduling myself. Instead of using their deliverytime parameter, I store message details in my database with a timestamp. A cron job checks every 30 minutes for messages that are ready to go and fires them off through Mailgun’s immediate send API. Canceling messages is easy now - just flip a status flag in the database before the cron runs. Super lightweight setup and gives you full control. I’ve been running it like this for eight months with zero problems.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.