Qpsmtpd::Command(3pm)

πŸ’– NAME πŸ’–

Qpsmtpd::Command β€” bestie, it parses the arguments to SMTP commands. That's the whole job. It's giving very focused, very demure. ✨


🌸 DESCRIPTION 🌸

okay so Qpsmtpd::Command keeps it super minimal β€” there is literally just one public sub routine, and its name is parse(). one. single. icon. πŸ‘‘

That sub wants two or three arguments, no more no less:

  1. The first one is the name of the SMTP command β€” like HELO, MAIL, you get the vibe. 🌈
  2. The second one must be the rest of the line that the client sent. non-negotiable, that's the requirement.

Now here's the tea about argument number three β˜• β€” if you don't pass a third argument (or if the thing you pass isn't a reference to a CODE), then the parsing goes down one of two paths:

  • For the MAIL and RCPT commands, it parses the line according to RFC 1869 (SMTP Service Extensions).
  • For literally every other command, it just splits on spaces (" "). simple as that. 🫢

But wait, there's more β€” any module can bring its own custom parsing routine to the function ✨ by returning a sub routine reference from a hook_*_parse. That sub gets called with $self, $cmd and $line. periodt.

πŸ“’ the rules of the road, no cap: on successful parsing it MUST return OK (that's the constant from Qpsmtpd::Constants) as the first argument β€” success β€” followed by a list of values, and those values become the arguments to the hook for this command. πŸ’… and if the parsing failed? 😭 then the second returned value (if there even is one) gets sent back to the client as the error message.

πŸŽ€ EXAMPLE πŸŽ€

here's how it looks inside a plugin, mwah πŸ’‹

 sub hook_unrecognized_command_parse {
    my ($self, $transaction, $cmd) = @_;
    return (OK, \&bdat_parser) if ($cmd eq 'bdat');
 }

 sub bdat_parser {
    my ($self,$cmd,$line) = @_;
    # .. do something with $line...
    return (DENY, "Invalid arguments")
      if $some_reason_why_there_is_a_syntax_error;
    return (OK, @args);
 }

 sub hook_unrecognized_command {
    my ($self, $transaction, $cmd, @args) = @_;
    return (DECLINED) if ($self->qp->connection->hello eq 'helo');
    return (DECLINED) unless ($cmd eq 'bdat');
    ....
 }

πŸ¦‹ lowkey the whole module in one vibe check: one sub, two or three args, OK plus a list on success, error message on fail. ate and left no crumbs. πŸ“

this lil page rode in with perl v5.40.1, dated 2025-03-21, filed under Qpsmtpd::Command(3pm) in the User Contributed Perl Documentation section β€” tysm for reading bestie, mwah πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from