| 291 | } |
| 292 | |
| 293 | func (cr *checkRunner) applyResults(hostname string, header *textproto.Header) error { |
| 294 | if cr.mergedRes.Quarantine { |
| 295 | cr.msgMeta.Quarantine = true |
| 296 | } |
| 297 | |
| 298 | if cr.doDMARC { |
| 299 | dmarcRes, policy := cr.dmarcVerify.Apply(cr.mergedRes.AuthResult) |
| 300 | cr.mergedRes.AuthResult = append(cr.mergedRes.AuthResult, &dmarcRes.Authres) |
| 301 | switch policy { |
| 302 | case dmarc.PolicyReject: |
| 303 | code := 550 |
| 304 | enchCode := exterrors.EnhancedCode{5, 7, 1} |
| 305 | if dmarcRes.Authres.Value == authres.ResultTempError { |
| 306 | code = 450 |
| 307 | enchCode[0] = 4 |
| 308 | } |
| 309 | return &exterrors.SMTPError{ |
| 310 | Code: code, |
| 311 | EnhancedCode: enchCode, |
| 312 | Message: "DMARC check failed", |
| 313 | CheckName: "dmarc", |
| 314 | Misc: map[string]interface{}{ |
| 315 | "reason": dmarcRes.Authres.Reason, |
| 316 | "dkim_res": dmarcRes.DKIMResult.Value, |
| 317 | "dkim_domain": dmarcRes.DKIMResult.Domain, |
| 318 | "spf_res": dmarcRes.SPFResult.Value, |
| 319 | "spf_from": dmarcRes.SPFResult.From, |
| 320 | }, |
| 321 | } |
| 322 | case dmarc.PolicyQuarantine: |
| 323 | cr.msgMeta.Quarantine = true |
| 324 | |
| 325 | // Mimick the message structure for regular checks. |
| 326 | cr.log.Msg("quarantined", "reason", dmarcRes.Authres.Reason, "check", "dmarc") |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | // After results for all checks are checked, authRes will be populated with values |
| 331 | // we should put into Authentication-Results header. |
| 332 | if len(cr.mergedRes.AuthResult) != 0 { |
| 333 | header.Add("Authentication-Results", authres.Format(hostname, cr.mergedRes.AuthResult)) |
| 334 | } |
| 335 | |
| 336 | for field := cr.mergedRes.Header.Fields(); field.Next(); { |
| 337 | formatted, err := field.Raw() |
| 338 | if err != nil { |
| 339 | cr.log.Error("malformed header field added by check", err) |
| 340 | } |
| 341 | header.AddRaw(formatted) |
| 342 | } |
| 343 | return nil |
| 344 | } |
| 345 | |
| 346 | func (cr *checkRunner) close() { |
| 347 | if err := cr.dmarcVerify.Close(); err != nil { |