Recommended Configuration
The following procedure was verified on Mautic 7.2.1 with PHP 8.4 using the current plugin version 1.5.11.
Verification results:
- ZIP installation completed successfully.
- Plugin registered with
is_missing = 0.
- Real database callback test passed.
- Duplicate webhook processing did not create duplicate DNC records.
- HTTP callback returned
200 OK.
- Response:
SendGrid Callback processed (1)
1. Download and Install the ZIP
Download the plugin ZIP from GitHub:
SendgridCallbackBundle releases
In Mautic:
Settings → Plugins → Install/Upgrade Plugins
Upload the ZIP archive and run Reload Plugins.
If installing manually, the final directory must be:
<mautic-root>/plugins/SendgridCallbackBundle/
The file structure must look like this:
plugins/SendgridCallbackBundle/SendgridCallbackBundle.php
plugins/SendgridCallbackBundle/Config/config.php
plugins/SendgridCallbackBundle/Config/services.php
plugins/SendgridCallbackBundle/EventSubscriber/CallbackSubscriber.php
plugins/SendgridCallbackBundle/Resources/views/Integration/footer.html.twig
For the standard ZIP Mautic installation, do not place it under docroot/plugins. The correct path is:
<mautic-root>/plugins/SendgridCallbackBundle
After copying the plugin manually:
php bin/console cache:clear --env=prod
php bin/console mautic:plugins:reload
2. Enable the Plugin Integration
Open:
Settings → Plugins → SendGrid Callback
Enable and publish the integration.
Enable these event handlers:
- Handle bounce events
- Handle blocked events
- Handle dropped events
- Handle spam report events
- Handle unsubscribe events
- Handle group unsubscribe events
Recommended dropped-event policy:
Auto:
unsubscribe/spam → Unsubscribed
other dropped events → Bounced
The plugin must be published. If the integration is disabled, the callback will not process events.
3. Verify the SendGrid Transport
The sending DSN should use the SendGrid API transport:
sendgrid+api://API_KEY@default
The legacy SMTP transport is also recognized:
sendgrid+smtp://USERNAME:PASSWORD@default
If API sending already works correctly, do not change the existing mailer configuration.
The plugin does not send messages itself. It only processes the SendGrid Event Webhook callback.
4. Configure SendGrid Event Webhook
In SendGrid:
Settings → Mail Settings → Event Webhook
Set the POST URL to:
https://news.mydomain.org/mailer/callback
Enable the webhook.
Select these events:
- Bounces
- Dropped
- Spam Reports
- Unsubscribes
- Group Unsubscribes
SendGrid sends event data as a JSON array. A bounce event has the following general structure:
[
{
"email": "contact@example.com",
"event": "bounce",
"reason": "550 unknown recipient",
"status": "5.1.1",
"type": "bounce"
}
]
SendGrid documents email as the recipient address and event as the event type. SendGrid Event Webhook Reference
A blocked bounce is normally represented by:
{
"event": "bounce",
"type": "blocked"
}
The plugin recognizes this and applies the blocked-event setting.
5. Test the Endpoint with cURL
Use an email address that already exists as a contact in Mautic:
curl -i -X POST 'https://news.mydomain.org/mailer/callback' \
-H 'Content-Type: application/json' \
-H 'User-Agent: SendGrid Event API' \
--data '[{
"event": "bounce",
"email": "existing-contact@example.com",
"reason": "mailbox not found",
"status": "5.1.1",
"type": "bounce"
}]'
Expected response:
HTTP/2 200
Response body:
SendGrid Callback processed (1)
The contact should receive the Mautic DNC status:
Bounced
Spam report test:
curl -i -X POST 'https://news.mydomain.org/mailer/callback' \
-H 'Content-Type: application/json' \
-H 'User-Agent: SendGrid Event API' \
--data '[{
"event": "spamreport",
"email": "existing-contact@example.com"
}]'
Expected contact status:
Unsubscribed
Dropped event test:
curl -i -X POST 'https://news.mydomain.org/mailer/callback' \
-H 'Content-Type: application/json' \
-H 'User-Agent: SendGrid Event API' \
--data '[{
"event": "dropped",
"email": "existing-contact@example.com",
"reason": "Bounced Address"
}]'
The result depends on the configured dropped-event policy.
6. SendGrid Test Button
SendGrid has a Test Your Integration button. It sends a POST request with sample events and sample data, not necessarily a real event from an actual contact. Therefore, this test verifies:
- URL availability;
- HTTPS connectivity;
- POST method;
- JSON format;
- Mautic HTTP response.
It does not necessarily update a Mautic contact.
SendGrid confirms that the integration test uses example events. SendGrid Event Webhook Overview
For a real DNC verification, use the cURL request above with an existing Mautic contact.
7. Logs to Check
Nginx access log
grep '/mailer/callback' /var/log/nginx/access.log
Or:
grep '/mailer/callback' /var/log/nginx/*access*.log
A valid request should contain:
POST /mailer/callback
Interpretation:
200 Plugin processed the event
404 Plugin/integration is not active or callback handler is unavailable
403 Firewall, authentication or access rule blocked the request
301/302 Redirect was returned instead of processing the POST
500 PHP or Mautic application error
Mautic log
From the Mautic root:
tail -f var/logs/mautic_prod.php
Depending on the Mautic log configuration:
tail -f var/logs/mautic_prod-*.php
Useful plugin messages include:
Processed SendGrid bounce for ...
Processed SendGrid dropped for ...
Processed SendGrid unsubscribe for ...
If the email cannot be matched:
Provider feedback lacks a valid Mautic email ID; applying contact-level DNC only.
This is not necessarily an error. The contact can still be marked DNC by email address.
8. Meaning of the 404 Error
If the response is:
No email transport that could process this callback was found
check these items in order:
SendgridCallbackBundle is present under plugins/SendgridCallbackBundle.
- The plugin appears in Mautic’s plugin list.
- The plugin integration is published.
- The Mautic cache was cleared.
mautic:plugins:reload was executed.
- The DSN uses
sendgrid+api:// or sendgrid+smtp://.
- The webhook URL is exactly:
https://news.mydomain.org/mailer/callback
- SendGrid is sending a
POST request with Content-Type: application/json.
The most common cause is that the plugin is installed but its integration remains disabled, or the cache was not rebuilt after installation.
Supported Events
| SendGrid event |
Mautic result |
bounce |
Bounced |
bounce with type: blocked |
Bounced |
dropped |
Based on dropped-event policy |
spamreport |
Unsubscribed |
unsubscribe |
Unsubscribed |
group_unsubscribe |
Unsubscribed |
The plugin does not process ordinary delivery, open or click events because those events do not represent a DNC change.
SendGrid also supports signed webhook requests using X-Twilio-Email-Event-Webhook-Signature and X-Twilio-Email-Event-Webhook-Timestamp. SendGrid Webhook Security