-
ale authored
Run our own little SMTP server, attempt to parse all incoming messages. Currently only DMARC email support is implemented (both ZIP and gzip formats).
ale authoredRun our own little SMTP server, attempt to parse all incoming messages. Currently only DMARC email support is implemented (both ZIP and gzip formats).
browser.go 1.59 KiB
package reportscollector
import (
"encoding/json"
"net"
"net/http"
"net/url"
"time"
"github.com/jhillyerd/enmime"
)
// Generic browser report as per https://www.w3.org/TR/reporting/.
type report struct {
Type string `json:"type"`
Age int `json:"age"`
URL string `json:"url"`
UserAgent string `json:"user_agent"`
Body map[string]interface{} `json:"body"`
}
type ReportHandler struct{}
func (h *ReportHandler) Parse(contentType string, req *http.Request) ([]Event, error) {
if contentType != "application/reports+json" {
return nil, ErrNoMatch
}
var reports []*report
if err := json.NewDecoder(req.Body).Decode(&reports); err != nil {
return nil, err
}
var events []Event
for _, r := range reports {
events = append(events, h.eventFromReport(req, r))
}
return events, nil
}
func (h *ReportHandler) ParseMIME(*enmime.Part) ([]Event, error) {
return nil, ErrNoMatch
}
func (h *ReportHandler) eventFromReport(req *http.Request, report *report) Event {
ts := time.Now().Add(time.Duration(-report.Age) * time.Second)
e := make(Event)
if asn, ok := lookupASN(getRemoteIP(req)); ok {
e.Set("asn", asn)
}
e.Set("type", report.Type)
e.Set("event_timestamp", ts)
e.Set("url", report.URL)
e.Set("domain", domainFromURL(report.URL))
e.Set("user_agent", report.UserAgent)
e.Set("body", report.Body)
return e
}
func domainFromURL(u string) string {
if uri, err := url.Parse(u); err == nil {
if host, _, err := net.SplitHostPort(uri.Host); err == nil {
return host
}
return uri.Host
}
return ""
}