mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-15 12:29:52 +00:00
This PR extends email support to add another email delivery provider called Postal for user management. It is a, open source, self hosted email delivery and reputation management service. It adds 2 new additional configuration settings to the userManagement.mail object which are "postalBaseUrl" and "postalApiKey". It also adds "postal" as a supported value for the "provider" setting. All existing functionality including email delivery notification is supported by Postal. Included test cases to support the new functionality and all pipelines pass. --------- Co-authored-by: CoderNemesis <rfedor@comchan.net>
58 lines
1.9 KiB
Go
58 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/meshcore-analyzer/mailer"
|
|
)
|
|
|
|
// handleBrevoWebhook ingests Brevo transactional events. Brevo is configured
|
|
// with auth {"type":"bearer","token":<webhookSecret>}, so it sends
|
|
// "Authorization: Bearer <secret>".
|
|
func (s *Server) handleBrevoWebhook(w http.ResponseWriter, r *http.Request) {
|
|
s.handleMailWebhook(w, r, "brevo", func(r *http.Request) bool {
|
|
return constantTimeEqual(r.Header.Get("Authorization"), "Bearer "+s.auth.set.webhookSecret)
|
|
}, mailer.ParseBrevoWebhook)
|
|
}
|
|
|
|
// handlePostalWebhook ingests Postal message events. Postal cannot add a
|
|
// header of its own, so the webhook URL carries the secret as Basic auth
|
|
// (https://postal:<secret>@host/api/mail/postal/webhook); the user name is
|
|
// not checked.
|
|
func (s *Server) handlePostalWebhook(w http.ResponseWriter, r *http.Request) {
|
|
s.handleMailWebhook(w, r, "postal", func(r *http.Request) bool {
|
|
_, pass, ok := r.BasicAuth()
|
|
return ok && constantTimeEqual(pass, s.auth.set.webhookSecret)
|
|
}, mailer.ParsePostalWebhook)
|
|
}
|
|
|
|
// handleMailWebhook is the shared webhook flow. Authenticated payloads that
|
|
// cannot be used, and unknown message ids, get 200 so the provider does not
|
|
// retry forever.
|
|
func (s *Server) handleMailWebhook(w http.ResponseWriter, r *http.Request, provider string,
|
|
authorized func(*http.Request) bool, parse func([]byte) ([]mailer.Event, error)) {
|
|
a := s.auth
|
|
if !a.allow(w, r, a.hook) {
|
|
return
|
|
}
|
|
if !authorized(r) {
|
|
writeError(w, http.StatusUnauthorized, "unauthorized")
|
|
return
|
|
}
|
|
body, err := io.ReadAll(http.MaxBytesReader(w, r.Body, 256<<10))
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "body too large")
|
|
return
|
|
}
|
|
evs, err := parse(body)
|
|
if err != nil {
|
|
log.Printf("[users] %s webhook: ignored payload: %s", provider, redactAddrs(err))
|
|
writeJSON(w, okResponse{OK: true})
|
|
return
|
|
}
|
|
a.ingestMailEvents(evs)
|
|
writeJSON(w, okResponse{OK: true})
|
|
}
|