README ¶
Webhooks and plugins
If you want to use SMTPorter’s webhook functionality, you’ll need plugins.
Since I can’t just magically support the schema and format for every single transactional email provider out of the box, SMTPorter allows you to develop plugins to add that functionality yourself.
Don’t worry, it’s easy! All you need is a little knowledge of the Go programming language.
A word of caution
Because of how SMTPorter’s webhook and retry logic works, make sure you have webhooks (and the adequate plugins) enabled for all of your providers.
Plugins, how?
Go allows building plugins easily by writing some Go code and building it with
CGO_ENABLED=1 go build -buildmode=plugin -o my_plugin.so my_plugin.go
This compiles your code into a shared library that can be imported by other Go programs at runtime.
Writing your own webhook plugin for SMTPorter
SMTPorter defines a WebhookPlugin
interface to implement in order to support your favorite provider’s webhook.
The interface is very minimal:
type WebhookPlugin interface {
GetMessageIDs(webhookPayload []byte) []string
}
To satisfy the interface, write a function that takes in the webhook payload as a parameter and returns all the IDs of messages that were delivered.
The webhookPayload
parameter is a slice of bytes, the request body of the webhook request.
Example plugin
The following is a plugin that parses the payload from a Brevo webhook.
// brevo_plugin.go
package main
import "encoding/json"
type brevoPlugin string
type BrevoEvent struct {
MessageID string `json:"message-id"`
}
// this function allows `brevoPlugin` to satisfy SMTPorter’s `WebhookPlugin` interface
func (p brevoPlugin) GetMessageIDs(webhookPayload []byte) []string {
var event BrevoEvent
err := json.Unmarshal(webhookPayload, &event)
if err != nil {
// Since this is just an example, we’re silently returning an empty slice
// if an error occurs when unmarshaling JSON.
// Ideally, you’d want to handle this differently
return []string{}
}
return []string{event.MessageID}
}
// this is exported
var WebhookPlugin brevoPlugin
The plugin is built with the following command:
CGO_ENABLED=1 go build -buildmode=plugin -o brevo_plugin.so brevo_plugin.go
Next, place the newly built brevo_plugin.so
in a plugins/
directory relative to the SMTPorter executable.
Using the plugin
In SMTPorter’s web interface, edit the provider you wish to use the plugin with.
Simply enable the webhook
option and enter the exact name of the plugin file, in this case brevo_plugin.so
.
Finally, make sure to properly configure the webhook with your transactional email provider.
SMTPorter handles webhooks by receiving the provider’s name, as defined via the web interface, in the URL path.
For a provider named default
in SMTPorter, the webhook route is https://<your-smtporter-deployment>/webhook/default
That’s all there is to it!
A note regarding Go and the stdlib plugin package
In SMTPorter’s Dockerfile and the above examples, plugins are built with the CGO_ENABLED=1
flag.
This is a known limitation of the Go compiler, and requires both plugins and the base executable to be compiled with this flag. See this GitHub issue and this abandoned CL for more information.
If you’re using my official container images for SMTPorter, you don’t have to worry as it was built with CGO_ENABLED=1
to allow for plugins.
Do remember the flag when building your own plugins though!
Base plugins
For your convenience, two default plugins are provided when using the quay.io/seizeheures/smtporter:<version>-plugins
image.
Plugin | name (for provider configuration) |
---|---|
Brevo | smtporter_brevo_plugin.so |
Sendgrid | smtporter_sendgrid_plugin.so |