Search code examples
gosendgridsendgrid-api-v3

Unable to cancel scheduled SendGrid email (with batch_id)


Using SendGrid to schedule an email, but then I cancel it right away and delete (looking at scheduled_events shows that status is in fact canceled). However, e-mail is still delievered to user.

I know it says "You can cancel or pause all of the mail/send requests associated with a batch ID up to 10 minutes before the scheduled send time by passing a batch_id to the "Cancel or pause a scheduled send" endpoint." (https://docs.sendgrid.com/api-reference/cancel-scheduled-sends/delete-a-cancellation-or-pause-from-a-scheduled-send)

But in this example code I have the time set to 20 minutes, and also tried it for 90 minutes and more and the emails was still delivered. Lastly, I tried doing the same with and without deleting the email (request4).

I contacted their support, but haven't received a response yet, and was wondering if I am doing something out of the ordinary or wrong here.

BTW, I checked the status code and responses - they all seem fine (added comments describing the printed out statuses)

Thanks

package main

import (
    "fmt"
    "time"

    "github.com/sendgrid/sendgrid-go"
    "github.com/sendgrid/sendgrid-go/helpers/mail"
    "github.com/tidwall/gjson"
)

const apiKey = "*******" // replace with yours
const host = "https://api.sendgrid.com"

func main() {
    const MINUTES_TO_ADD = 20 // 20 mins
    email := "[email protected]"

    from := mail.NewEmail("X", "[email protected]")
    subject := "subject"
    to := mail.NewEmail("Test", email)

    request := sendgrid.GetRequest(apiKey, "/v3/mail/batch", host)
    request.Method = "POST"
    response, err := sendgrid.API(request)

    if err != nil {
        return
    }

    batchId := gjson.Get(
        response.Body,
        "batch_id",
    ).Str

    htmlContent := `Hi`

    message := mail.NewSingleEmail(from, subject, to, "", htmlContent)
    message.SendAt = int(time.Now().Add(time.Minute * MINUTES_TO_ADD).Unix())
    message.BatchID = batchId
    client := sendgrid.NewSendClient(apiKey)
    mailSendResponse, err := client.Send(message)

    if err != nil {
        return
    } else {
        fmt.Println(mailSendResponse.StatusCode) // prints 202
    }

    request3 := sendgrid.GetRequest(apiKey, "/v3/user/scheduled_sends", host)
    request3.Method = "POST"
    request3.Body = []byte(`{
"batch_id": "` + batchId + `",
"status": "cancel"
}`)

    response3, err := sendgrid.API(request3)

    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Println(response3.StatusCode) // prints 201

    request4 := sendgrid.GetRequest(apiKey, "/v3/user/scheduled_sends/"+batchId, host)
    request4.Method = "DELETE"
    response4, err := sendgrid.API(request4)

    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Println(response4.StatusCode) // prints 204

    request5 := sendgrid.GetRequest(apiKey, "/v3/user/scheduled_sends", host)
    request5.Method = "GET"
    response5, err := sendgrid.API(request5)

    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Println(response5.StatusCode) // prints 200
}

Solution

  • When you send emails in a batch, you are able to cancel those emails by cancelling the batch. However, I think what you are doing here is cancelling the cancellation by deleting the batch.

    From the docs:

    When a batch is canceled, all messages associated with that batch will stay in your sending queue. When their send_at value is reached, they will be discarded.

    When a batch is paused, all messages associated with that batch will stay in your sending queue, even after their send_at value has passed. This means you can remove a pause status, and your scheduled send will be delivered once the pause is removed. Any messages left with a pause status that are more than 72 hours old will be discarded as Expired.

    The batch holds the cancelled/paused status but the messages remain in the queue. If you delete the batch, then the messages are still in the queue and no longer know that they are cancelled.

    To fix this, I believe you need to stop your above code at your 3rd request. Do not perform request 4 (deleting the batch) and your messages should fail to send as required.