Documentation
¶
Overview ¶
Package spam scores arriving mail. Rule features (authentication, DNS blocklists, header and link anomalies), a Bayesian token classifier and sender reputation are combined by logistic weights. Every time the operator moves a message between inbox and junk, the Bayes tokens, the reputation and the weights learn from it.
Index ¶
- Variables
- func Executable(p *msg.Parsed) string
- func Features(in Input) map[string]float64
- func ReputationKeys(in Input) []string
- func Tokens(p *msg.Parsed) []string
- type Classifier
- func (c *Classifier) Classify(ctx context.Context, in Input) Verdict
- func (c *Classifier) Reset(ctx context.Context) error
- func (c *Classifier) Stats(ctx context.Context) Stats
- func (c *Classifier) Train(ctx context.Context, p *msg.Parsed, sampleJSON string, label, prev string) error
- func (c *Classifier) Weights(ctx context.Context) map[string]float64
- type Input
- type Sample
- type Stats
- type Verdict
Constants ¶
This section is empty.
Variables ¶
var Prior = map[string]float64{
"bias": -3.0,
"spf_pass": -0.3,
"spf_fail": 2.0,
"spf_softfail": 0.8,
"spf_none": 0.4,
"dkim_aligned": -1.5,
"dkim_fail": 0.7,
"dkim_none": 0.3,
"dmarc_pass": -1.0,
"dmarc_fail": 2.5,
"dmarc_none": 0.2,
"dnsbl": 3.5,
"no_ptr": 1.0,
"ptr_unconfirmed": 0.6,
"helo_bad": 1.0,
"known_contact": -3.0,
"own_domain_forged": 5.0,
"no_message_id": 1.0,
"no_date": 0.8,
"date_skew": 0.5,
"subject_empty": 0.4,
"subject_caps": 0.8,
"subject_bait": 1.0,
"scam_phrases": 3.0,
"html_only": 0.4,
"many_links": 0.6,
"link_mismatch": 1.5,
"shortener": 0.6,
"from_spoof": 1.5,
"risky_attachment": 1.5,
"bayes": 4.0,
"rep_sender": 2.5,
"rep_domain": 1.5,
"rep_net": 1.0,
}
Prior are the starting weights; learning moves away from them only as far as the operator's corrections justify.
Functions ¶
func Executable ¶
Executable reports attachments no legitimate mail carries; lfr refuses them outright.
func ReputationKeys ¶
ReputationKeys are the identities whose history counts for a message.
Types ¶
type Classifier ¶
type Classifier struct {
DB *store.DB
Now func() time.Time
// contains filtered or unexported fields
}
Classifier scores and learns.
func (*Classifier) Classify ¶
func (c *Classifier) Classify(ctx context.Context, in Input) Verdict
Classify scores a message.
func (*Classifier) Reset ¶
func (c *Classifier) Reset(ctx context.Context) error
Reset forgets everything learned.
func (*Classifier) Stats ¶
func (c *Classifier) Stats(ctx context.Context) Stats
Stats reports training state.
type Input ¶
type Input struct {
IP net.IP
Helo string
PTR string // first reverse DNS name, "" if none
PTRConfirmed bool // the PTR name resolves back to IP
DNSBL []string
Auth mailauth.Result
Parsed *msg.Parsed
KnownContact bool // the sender is someone lfr sent mail to before
OwnDomain bool // the From domain is one lfr serves, so lfr signed every genuine mail from it
Received time.Time
}
Input is everything known about an arriving message.
type Sample ¶
type Sample struct {
X map[string]float64 `json:"x"`
Keys []string `json:"keys"` // reputation keys
}
Sample is what is stored with each message for later learning.
type Stats ¶
type Stats struct {
Spam int `json:"trained_spam"`
Ham int `json:"trained_ham"`
BayesReady bool `json:"bayes_active"`
Tokens int `json:"tokens"`
Reputation int `json:"reputation_keys"`
}
Stats describes what the filter has learned.
type Verdict ¶
type Verdict struct {
P float64 `json:"p"`
Bayes float64 `json:"bayes,omitempty"` // -1 when not trained enough
Hits []string `json:"hits,omitempty"` // features that pushed the score, strongest first
Sample Sample `json:"-"`
Contrib map[string]float64 `json:"-"`
}
Verdict is the classification of one message.