diff --git a/browser.go b/browser.go index 09e506b10ec4b8945ef1a6687ea406e208a5e677..e4c546d5a7a32ec2cb882a6c4513696b5c7887a3 100644 --- a/browser.go +++ b/browser.go @@ -21,6 +21,8 @@ type report struct { type ReportHandler struct{} +func (h *ReportHandler) Name() string { return "report-api" } + func (h *ReportHandler) Parse(contentType string, req *http.Request) ([]Event, error) { if contentType != "application/reports+json" { return nil, ErrNoMatch diff --git a/collector.go b/collector.go index 24e3a9a29f50aa8fe30fa85973651f5b58169ae7..aefe291229aea6db26fdbb1a61c91e035f50d18c 100644 --- a/collector.go +++ b/collector.go @@ -16,6 +16,7 @@ import ( var ErrNoMatch = errors.New("no match") type Handler interface { + Name() string Parse(string, *http.Request) ([]Event, error) ParseMIME(*enmime.Part) ([]Event, error) } @@ -60,19 +61,22 @@ func (c *Collector) ServeHTTP(w http.ResponseWriter, req *http.Request) { // Find a handler that can successfully parse the request, and // get a list of Events. - var events []Event - matched := false -hloop: for _, h := range c.handlers { - var err error - events, err = h.Parse(ct, req) + events, err := h.Parse(ct, req) switch err { - case ErrNoMatch: - continue case nil: - matched = true + // Send the parsed events to the Sink. + for _, e := range events { + c.sink.Send(e) + reportsByType.WithLabelValues( + e.GetString("type"), e.GetString("domain")).Inc() + } + + log.Printf("http: %s: received %d events from %s", h.Name(), len(events), getRemoteIP(req)) w.WriteHeader(http.StatusOK) - break hloop + return + case ErrNoMatch: + continue default: log.Printf("error parsing report (%s): %v", ct, err) http.Error(w, err.Error(), http.StatusBadRequest) @@ -80,19 +84,8 @@ hloop: } } - if !matched { - log.Printf("no matching handlers for \"%s\"", ct) - http.Error(w, "No matching handlers", http.StatusBadRequest) - return - } - - // Augment the Events with additional information obtained - // from the HTTP request, and send them to the forwarder. - for _, e := range events { - c.sink.Send(e) - reportsByType.WithLabelValues( - e.GetString("type"), e.GetString("domain")).Inc() - } + log.Printf("no matching handlers for \"%s\"", ct) + http.Error(w, "No matching handlers", http.StatusBadRequest) } func (c *Collector) ServeSMTP(peer smtpd.Peer, env smtpd.Envelope) error { @@ -104,18 +97,20 @@ func (c *Collector) ServeSMTP(peer smtpd.Peer, env smtpd.Envelope) error { // Find a handler that can successfully parse the request, and // get a list of Events. - var events []Event - matched := false -hloop: for _, h := range c.handlers { - var err error - events, err = h.ParseMIME(msgParts) + events, err := h.ParseMIME(msgParts) switch err { + case nil: + // Send the parsed events to the Sink. + for _, e := range events { + c.sink.Send(e) + reportsByType.WithLabelValues( + e.GetString("type"), e.GetString("domain")).Inc() + } + log.Printf("smtp: %s: received %d events from %s", h.Name(), len(events), env.Sender) + return nil case ErrNoMatch: continue - case nil: - matched = true - break hloop default: log.Printf("smtp: error handling report: %v", err) // Discard the message. @@ -123,19 +118,8 @@ hloop: } } - if !matched { - log.Printf("smtp: no matching handlers") - // Discard the message. - return nil - } - - // Augment the Events with additional information obtained - // from the HTTP request, and send them to the forwarder. - for _, e := range events { - c.sink.Send(e) - reportsByType.WithLabelValues( - e.GetString("type"), e.GetString("domain")).Inc() - } + log.Printf("smtp: no matching handlers") + // Discard the message. return nil } diff --git a/csp.go b/csp.go index 698c38eaf93b0131e912071e3711356f6b3071c8..a69445784f40150d2467973e7334aa1254dd37a9 100644 --- a/csp.go +++ b/csp.go @@ -27,6 +27,8 @@ type legacyCSPReportContainer struct { type LegacyCSPHandler struct{} +func (h *LegacyCSPHandler) Name() string { return "legacy-csp" } + func (h *LegacyCSPHandler) Parse(contentType string, req *http.Request) ([]Event, error) { if contentType != "application/csp-report" { return nil, ErrNoMatch diff --git a/dmarc.go b/dmarc.go index 064036cb13f895a9c238cf23a9591d6a76656b0a..152a1107a7339691a1e49c1f17fdc87c38d357a4 100644 --- a/dmarc.go +++ b/dmarc.go @@ -75,6 +75,8 @@ type dmarcReport struct { type DMARCHandler struct{} +func (h *DMARCHandler) Name() string { return "dmarc" } + func (h *DMARCHandler) parseDMARC(r io.Reader) ([]Event, error) { var report dmarcReport if err := xml.NewDecoder(r).Decode(&report); err != nil { diff --git a/tlsrpt.go b/tlsrpt.go index 3f169e73673e6e54c1df64f0d9d8ae7fbda33421..d293b0d7fbabebcba9924789c9a1f9d5c2c931ba 100644 --- a/tlsrpt.go +++ b/tlsrpt.go @@ -51,6 +51,8 @@ type tlsrpt struct { type TLSRPTHandler struct{} +func (h *TLSRPTHandler) Name() string { return "tls-rpt" } + func (h *TLSRPTHandler) Parse(contentType string, req *http.Request) ([]Event, error) { var r io.Reader switch contentType {