| 301 | } |
| 302 | |
| 303 | func (s *state) CheckConnection(ctx context.Context) module.CheckResult { |
| 304 | defer trace.StartRegion(ctx, "check.spf/CheckConnection").End() |
| 305 | |
| 306 | if s.msgMeta.Conn == nil { |
| 307 | s.skip = true |
| 308 | s.log.Println("locally generated message, skipping") |
| 309 | return module.CheckResult{} |
| 310 | } |
| 311 | |
| 312 | ip, ok := s.msgMeta.Conn.RemoteAddr.(*net.TCPAddr) |
| 313 | if !ok { |
| 314 | s.skip = true |
| 315 | s.log.Println("non-IP SrcAddr") |
| 316 | return module.CheckResult{} |
| 317 | } |
| 318 | |
| 319 | mailFromOriginal := s.msgMeta.OriginalFrom |
| 320 | if mailFromOriginal == "" { |
| 321 | // RFC 7208 Section 2.4. |
| 322 | // >When the reverse-path is null, this document |
| 323 | // >defines the "MAIL FROM" identity to be the mailbox composed of the |
| 324 | // >local-part "postmaster" and the "HELO" identity (which might or might |
| 325 | // >not have been checked separately before). |
| 326 | mailFromOriginal = "postmaster@" + s.msgMeta.Conn.Hostname |
| 327 | } |
| 328 | |
| 329 | mailFrom, err := prepareMailFrom(mailFromOriginal) |
| 330 | if err != nil { |
| 331 | s.skip = true |
| 332 | return module.CheckResult{ |
| 333 | Reason: err, |
| 334 | Reject: true, |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | if s.c.enforceEarly { |
| 339 | res, err := spf.CheckHostWithSender(ip.IP, |
| 340 | dns.FQDN(s.msgMeta.Conn.Hostname), mailFrom, |
| 341 | spf.WithContext(ctx), spf.WithResolver(s.c.resolver)) |
| 342 | s.log.Debugf("result: %s (%v)", res, err) |
| 343 | return s.spfResult(res, err) |
| 344 | } |
| 345 | |
| 346 | // We start evaluation in parallel to other message processing, |
| 347 | // once we get the body, we fetch DMARC policy and see if it exists |
| 348 | // and not p=none. In that case, we rely on DMARC alignment to define result. |
| 349 | // Otherwise, we take action based on SPF only. |
| 350 | |
| 351 | go func() { |
| 352 | defer func() { |
| 353 | if err := recover(); err != nil { |
| 354 | stack := debug.Stack() |
| 355 | log.Printf("panic during spf.CheckHostWithSender: %v\n%s", err, stack) |
| 356 | close(s.spfFetch) |
| 357 | } |
| 358 | }() |
| 359 | |
| 360 | defer trace.StartRegion(ctx, "check.spf/CheckConnection (Async)").End() |