Email::Received(3pm)

πŸ“¦
version 1.00 Β· 4 versions
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’Œ Email::Received β€” the manual page, but make it a group chat πŸ’Œ

okay bestie, welcome to Email::Received (yes that's Email::Received(3pm), we're being fancy) β€” the module that reads a Received: header and tells you what's actually going on in there. no cap.


✨ NAME ✨

Email::Received β€” parse an email Received: header. that's it. that's the whole vibe. πŸŽ€


✨ SYNOPSIS ✨

here's the whole flow, look how cute it is:

use Email::Received;

for ($mail->header("Received")) {
  my $data = parse_received($_);
  return "SPAM" if rbl_lookup($data->{ip});
}

like. it pulls the header, it parses it, it checks the IP against an RBL, and if that comes back spicy it screams "SPAM". iconic. πŸ’…


✨ DESCRIPTION ✨

so this module is a Perl Email Project rewrite of SpamAssassin's email header parser. the way they did that? the SpamAssassin girlies went and analysed pretty much every possible Received header format in existence 😭 and we wanted that glorious work to be usable in apps that are not SpamAssassin itself. so we yoinked it. respectfully. 🫢

the module gives you exactly one function, parse_received, which takes a single Received line. and then it does one of three things:

  • it produces nothing, if the line is unparsable πŸ’€
  • it gives you a hash reference like this, if the line should be ignored for some good reason:
{ reason => "gateway noise" }
  • or it gives you one like this, if it actually parsed the message ✨:
{ ip => '64.12.136.4', id => '875522', by => 'xxx.com',
  helo => 'imo-m01.mx.aol.com' }

possible keys are, in the original order, no edits:

ip rdns helo ident envfrom auth by id

slay. πŸ’–


✨ RULE FORMAT ✨

so where SpamAssassin used one big static subroutine absolutely stuffed with regular expressions to parse the data, we instead build up a big subroutine full of regular expressions dynamically, from a set of rules. glow up πŸ’…

the rules live at the bottom of this module. iykyk. the basic format for a rule looks like this:

((var=~)?/REGEXP/)? [ACTION; ]+

and the ACTION is one of these four things, exactly:

  • SET variable = $value
  • IGNORE "reason"?
  • UNPARSABLE
  • DONE

there's also one control structure provided, and honestly it's basically just an if statement wearing a little outfit:

GIVEN (NOT)? /REGEXP/ {
    ACTION+
}

✨ EXPORT ✨

parse_received

that's the one, bestie. that's what you get. πŸŽ€


✨ SEE ALSO ✨

  • Mail::SpamAssassin::Message::Metadata::Received β€” from which the rules and some of the IP address matching constants were blatantly stolen. no shame, we said it ourselves. thanks guys, for doing such a comprehensive job! πŸ™ˆπŸ’–

✨ AUTHOR ✨

simon, <simon@> 🫢


Copyright (C) 2006 by simon

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.7 or, at your option, any later version of Perl 5 you may have available.

ok that's the legal bit and we're keeping it exactly as written, because licensing is not the place for creative liberties, bestie. periodt. πŸ’€

and that's the whole page!! this one shipped as perl v5.36.0, dated 2022-12-12 β€” so yeah, a little vintage, but still serving. go parse some headers, you absolute main character. πŸŒˆπŸ‘‘πŸ’œ

πŸ“¦ where this page comes from