Menu

Vacation Functionality - Details?

Charles
2008-06-30
2013-01-23
1 2 > >> (Page 1 of 2)
  • Charles

    Charles - 2008-06-30

    I just saw a message on the postfix list where someone criticised the postfix-admin vacation message functionlaity because:

    "... it does not use the envelope sender nor the envelope recipient..."

    First, is this true? If so, this is not good...I wish I could tell from reading the code, but I'm not a programmer...

    Also, while I'm on this topic, there's something I've always wanted to understand better.

    Is there a detailed list of the processing that occurs to prevent vacation messages from being sent when they shouldn't be sent? Like, for example, in a thread on the postfix list last year, the following was discussed and these specifics were spelled out as to what constituted 'good' vacation message behavior, and I'm very interested to learn how well the postfix-admin vacation message functionality adheres to these rules. I apologize for the length below, but I think this deserves careful consideration:

    Begin thread copy/paste:

    Original poster:
    >> I know that most people on this list hate vacation/auto-responder type
    >> messages, but I also know that the same people care even more about them
    >> working properly when they are used.
    >>
    >> With that in mind, I'd like comments (criticism, suggestions to make it
    >> better behaved) on the one that works with dovecot. From the wiki:
    >> (http://tinyurl.com/2lxwr8):
    >>
    >> ****************************************
    >>
    >> Vacation auto-reply
    >>
    >> The vacation replies are sent to the envelope sender. Currently this is
    >> taken from the Return-Path: header in the message.

    mouss replied:
    > or from the command line if this is supported.
    >
    > if the envelope sender is not available, no reply should be sent.

    >> The automatic replies shouldn't be sent if any of the following
    >> are true:
    >>
    >>  * Auto-Submitted: header exists with any value except "no"
    >>  * Precedence: header exists with value "junk", "bulk" or "list"
    >>  * The envelope sender
    >>       o begins with "MAILER-DAEMON" (case-insensitive)
    >>       o begins with "LISTSERV" (case-insensitive)
    >>       o begins with "majordomo" (case-insensitive)
    >>       o begins with "owner-" (case-sensitive)

    mouss replied:
    > replace with:
    >    starts with "${token}-" (not case sensitive), where token is
    >    one of: owner, request, bounces
    >
    > It is safer to send nothing than send a risky one.

    >>       o contains the string "-request" anywhere within it (case-
    >>         sensitive)

    mouss replied:
    > replace with
    >        o contains "-${token}@" (not case sensitive), where token
    >          is one of: owner, request, bounces

    >>  * The envelope sender and envelope recipient are the same
    >>  * The envelope recipient is not found in the message To:, Cc: or
    >>    Bcc: fields.

    mouss replied:
    >   * There is a "Sender:" header containing one of the tokens listed
    >     above.
    >   * There is a List-Id or List-Post header
    >   * There is no header suggesting that this is possible spam
    >
    > Unlike delivery, safety here is to not send a reply if the message
    > may be spam. so you don't rely on recipient preferences, and you
    > don't fear flase positives too much (the guy who receives your
    > auto-reply may have a better filter, and besides annoying him, would
    > find you stupid to miss an obvious spam ;-p)

    >> The envelope sender is taken from a Return-Path: header in the
    >> message. The envelope recipient is taken from the recipient user
    >> (-d parameter with virtual user setup). A bare username without a
    >> domain gets canonicalised by the libsieve code to
    > "<username>@unspecified-domain", which means it is highly unlikely to
    > pass the last two tests in the list above.

    mouss replied:
    > the enveleope recipient can also be retrieved in the Delivered-To
    > header if this is available ('D' flag).

     
    • Charles

      Charles - 2008-07-07

      I'm very surprised... is NO ONE ELSE concerned about the inner workings of this script?

      Is no one else concerned about whether or not it responds when it should, but moreimportantly DOES NOT respond when it SHOULDN'T?

      As I said in the initial post, I'm not a programmer, and am unable to tell from simply reading the vacation script, what measures it takes to not respond when it shouldn't.

      I'm most concerned about the claim that it doesn't reply to the envelope FROM, but instead replies to the From HEADER, which is easily forged.

      Please... would someone who knows and understands this script, please respond to the specific details outlined above?

      Thanks,

      Charles

       
    • GingerDog

      GingerDog - 2008-07-08

      Hi, I mean to reply to this; but I've been a bit busy to...

      Yes, it does appear to rely on the headers in the email to handle to/from; I'm not sure why this is - it certainly _seems_ the wrong behaviour.

      Presumably the correct behaviour is to ignore the to/from in any headers, and use the SMTP RCPT TO / FROM fields, which should be passed into the script via $argv?

      David.

       
      • Charles

        Charles - 2008-07-08

        Hi David,

        No worries... its quite a detailed question/issue, so I appreciate that it would take some time to properly address...

        Yes, you are right, it most definitely should use the SMTP MAIL FROM and RCPT TO commands, not the headers.

        I'd also like to see if any of the other checks that were suggested that are not already used could be added (while we're looking at it)...

        Lets make the postfixadmin vacation message something to be used as a reference for those people who like to call vacation auto responders 'evil' - I'd like them to be able to say 'but if you *must* use one, *please* use a sane one like the one used by postfixadmin!'...

        :)

         
    • Charles

      Charles - 2008-07-21

      Just being the squeaky wheel...

      I'd really like to get this aspect of Postfixadmin improved so that the vacation behavior conforms to the 'Best practices' for an auto-responder.

      Please, anyone who knows how to read this code (and maybe even improve it), can you take some time to analyse my initial message and then the vacation script?

      Thanks,

      Charles

       
    • GingerDog

      GingerDog - 2008-07-21

      Thanks for the reminder; I'm keen to improve it - although finding time to seems difficult :-( (I'll try and release postfixadmin 2.2.1 first)

       
      • Charles

        Charles - 2008-07-21

        Oh, no worries... I'm just playing the part of the 'squeaky wheel'... :)

        Thanks!

         
    • Charles

      Charles - 2008-07-31

      With all of the talk of modularizing postfixadmin, which will require a total rewrite of much of the code, I'd like to again make a call to first, BEFORE doing that kind of thing, please, please, please lets get the Vacation functionality fixed up...

      I think it (the ability to easily enable/disable a 'vacation' message) is an extremely important aspect of postfixadmin - in fact, it is one of the main reasons I decided to use it myself - but there are people on the postfix mail list that denigrate postfixadmin solely because of the vacation script functionality 'bugs' - meaning, failure to behave the way a proper vacation script should.

      ... if I was a coder and could do this myself, I wouldn't hesitate ...

       
    • Lux

      Lux - 2008-08-01

      I wrote a (0.0 release, alpha, test) patch to support mouss suggestions. You can find it for some days on http://www.iotti.biz/vacation/vacation.pl.useEnvelope.diff

      I try to do the tests on the email address, stripping all other components from the address fields. It seems right for me, but I can accept other ideas.
      For now, I did not get rid of the previous tests made on header recipient/sender addresses: I agree with mouss that when in doubt it's better to send nothing.

      In master.cf it has to be called this way:
      vacation  unix  -       n       n       -       -       pipe
        flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient}

      The patch is against the version found in PA-2.2.1.1 and contains the 2 patches I submitted 2-3 days ago too (interval notification and CentOS5 DBI compatibility).

      I would like to hear feedback. Be warned that it was only very basically tested on my home server for now.

      Luigi

       
    • GingerDog

      GingerDog - 2008-08-01

      Hi Luigi,

      Nice patch - you've saved me from doing it this weekend!

      I'll try and test it - the patch itself looks fine from a first run through, so thank you!

      David.

       
    • Charles

      Charles - 2008-08-01

      Yay! Luigi is my here of the day!

      Seriously, thanks, this is great...

      Would it be possible for you to list, precisely, but in plain english, what each step of the code does?

      Example:

      1. tests for vacatation enabled

      2. if enabled, tests interval against sender/interval db

      3. performs following checks:

      a) tests for NULL <> sender

      etc... you get the idea...

      I'd really like to understand exactly how it works. Also, once this is officially integrated, I this it should be well documented on, or just off of the home page, complete with a request for additional checks that could be added to make its behavior even safer...

      But regardless... thanks so much to Luigi and GingerDog for making this happen! I'm very excited about upgrading once it is official...

       
    • Lux

      Lux - 2008-08-03

      Hmmm, again the Perpetual Documentation Problem. The code here is particularly self-explaining. Below I'll try to tell what is done in reference to the code chunks. But honestly I think you should try to read the code. It's not that hard, me too am not a pro coder. I think that documentation about this topic would quickly become obsolete when changes are made to the script.

      So on to the code (comments are after the # sign):
      while (<STDIN>) { # reading the message from standard input
      ...

      # if we find the x-spam-flag: or x-spam-status: flag, exit doing nothing; the comparison is not case-sensitive (the /i )
      elsif (/^x-spam-(flag|status):\s+yes/i) { exit (0); }

      # if we find the precedence: header followed by space (\s+) and one of the bulk, list, junk words, exit doing nothing;
      elsif (/^precedence:\s+(bulk|list|junk)/i) { exit (0); }

      # if we find the x-loop: header followed by space (\s+) and the string "postfix admin virtual vacation", exit doing nothing. Hey: we check a x-loop header that we never insert: this will be the object of another patch
      elsif (/^x-loop:\s+postfix\ admin\ virtual\ vacation/i) { exit (0); }

      # if we find Auto-Submitted: no , let's go on
      elsif (/^Auto-Submitted:\s+no/i) { next; }

      # if we find Auto-Submitted: with anything else, exit doing nothing;
      elsif (/^Auto-Submitted:/i) { exit (0); }

      # if we find List-Id: or List-Post header, exit doing nothing
      elsif (/^List-(Id|Post):/i) { exit (0); }
      ...

      # if any of the to, from, messageid header fields, or envelope sender/recipient are not set, then exit. Maybe it can be discussed if, now that we use evelope sender and recipient, it does make sense checking the header from/to. I think the answer is still yes.
      if (!$from || !$to || !$messageid || !$sender || !$recipient) { exit (0); }

      # If the envelope sender begins (the ^) with mailer-daemon or listserv or majordomo or owner- or request- or bounces- , exit doing nothing
      if ( $sender =~ /^(mailer-daemon|listserv|majordomo|owner-|request-|bounces-)/i) { exit (0); }

      # If the envelope sender contains (note the absence of ^) -owner@ or -request@ or -bounces@ , exit doing nothing
      if ( $sender =~ /-(owner|request|bounces)\@/i) { exit (0); }

      # the strip_address sub strips anything but the mail address so in $ss we have the mail address of the envelope sender
      my $ss = strip_address($sender);
      my $sr = strip_address($recipient);
      my $ssh = strip_address($sndrhdr);
      # if the mail address of the evelope sender is the same of the recipient's, then exit
      if ($ss eq $sr) { exit(0); }

      # here we loop over a list made of the recipients found in the to, cc, and bcc header fields
      for (split(/,\s*/, lc($to)), split(/,\s*/, lc($cc)), split(/,\s*/, lc($bcc))) {
              my $destinatario = strip_address($_); # we take only the address of the recipient we're looping on
              if ($ssh eq $destinatario) { exit(0); } # if it's equal to the Sender: header mail address, then exit. Hey! Shouldn't we check $sh too for this?
              if ($sr eq $destinatario) { $recipfound++; } # increment a variable (initially 0) if we found that it was equale to the envelope recipient mail address
      }
      if (!$recipfound) { exit (0); } # if we did not find any to, cc, or bcc header field values matchng the envelope recipient, then exit

      # use a standard module to check if the from header field has a valid dns entry
      if (!Email::Valid->address($from,-mxcheck => 1)) { exit(0); }
      # the same for the envelope sender mail address
      if (!Email::Valid->address($ss,-mxcheck => 1)) { exit(0); }

      # some of the checks performed on the from header value
      if ($from eq "" || $from =~ /^(owner-|-(?:request|owner)\@|^(?:mailer-daemon|postmaster)\@)/i) { exit (0); }

       
    • Lux

      Lux - 2008-08-03

      Correction to my prevous post: the x-loop header is inserted. I missed it.

      For the other thing, I think we should add the line
      if ($ss eq $destinatario) { do_debug("envelope sender $ss contains recipient $destinatario"); exit(0); }
      over or under the one with
      if ($ssh eq $destinatario) { do_debug("sender header $sender contains recipient $destinatario"); exit(0); }
      to theck again if the sender envelope address is contained in the header recipients. Maybe redundant, but "melius est abundare".

       
    • GingerDog

      GingerDog - 2008-08-03

      Hi,

      Patch merged - I'm working on changing the logging used to use log4perl, which should improve things too.

      (*Note: I've not tested the patch, but it's in trunk, which should be warning enough*)

      David.

       
    • Charles

      Charles - 2008-08-03

      Wow!

      This is awesome... very comprehensive, and looks like it contains all of the checks mouss recommended... and I agree with you that we should *also* check the header from/recipients - can't hurt, but I guess the only question (that I cannot answer) is, does it really accomplish anything? Meaning, will it catch anything that the envelope sender/recipient checks won't?

      Do you mind if I invite him to this thread for comments/suggestions?

      Thank you very, very much for taking the time to do this!

       
    • GingerDog

      GingerDog - 2008-08-04

      Anyone is welcome to comment/raise tickets/test/submit patches for the codebase; I'm not fussy! If it's an improvement it'll get in :)

       
    • Lux

      Lux - 2008-08-04

      > does it really accomplish anything?
      > Meaning, will it catch anything that the
      > envelope sender/recipient checks won't?

      At a first glance, I think the answer is no. BUT it's highly likely I'm missing some particular cases. I just wrote in Perl, as good as I can, what mouss told to do. I think that leaving the checks on the from/to headers or removing them should be the object of some discussion. In the meanwhile, leaving them there will not hurt (I think).

       
      • Charles

        Charles - 2008-08-04

        Understood... and again, your efforts are very much appreciated.

        I have invited mouss to come and participate, since he has expressed interest in 'properly functioning vacation messages', so hopefully he will be commenting directly sometime soon...

         
    • GingerDog

      GingerDog - 2008-08-05

      Hi,

      Just a quick note - I've merged Lux's patch and am currently rewriting the logging done by the script to use log4perl (this should make it easier for people to understand what it's doing).

      I'm almost ready to commit it, but am hoping to write a simple 'test' harness or something to help show that it is (or isn't!) working.

      David.

       
    • GingerDog

      GingerDog - 2008-08-06

      vacation.pl updated with better logging etc and crude tests....

       
      • Joseph Cotton

        Joseph Cotton - 2008-08-06

        I tested this new vacation.pl and found a problem. Because my usernames include the domain, the envelope address vacation.pl sees is (sample)   bob#example.com@autoreply.example.com

        It seems that strip_address() "fixes" this to example.com@autoreply.example.com, which is not found in the envelope recipient list, thus:

        2008/08/06 15:56:10 DEBUG> /var/spool/vacation/vacation.pl:475 main:: - smtp envelope recipient example.com@autoreply.example.com not found in the header recipients (therefore they were bcc'ed, so won't send vacation message)

         
        • Lux

          Lux - 2008-08-07

          Here I see two distinct issues.
          If I put the line
          $logger->debug("Examining message $messageid - smtp sender $smtp_sender - smtp recipient $smtp_recipient");
          just after the assignment
          $smtp_recipient = shift || $smtp_recipient || $ENV{"USER"} || "";
          I find in the log a line saying
          Examining message <20080807061344....@...> - smtp sender <lux@ten.biz> - smtp recipient "lux@domain.com"@autoreply.domain.com

          In my case, strip_address strips exactly lux@domain.com , just because there are the '"' and because the "@domain.com" comes before the "@autoreply.domain.com". I use flags=Rq (see the q) in master.cf
          In your case, I think the regexp the result is not what you expected to see because it seems you have a # in the place of the @ in the user name. I don't know why, this depends upon your setup.

          Maybe, we should accept other characters in the local email address part in strip domain (seems that ! # $ * / ? | ^ { } ` ~ & ' + = are legal). But this alone won't solve your issue.
          Maybe we should strip the @autoreply.domain.com part before trying to isolate the recipient email address, just to be sure not to take this into account when we lookfor the recipient address.
          Maybe you could use ${user} instead of ${recipient} in master.cf. This should expand to bob#example.com . Still remains the # issue.

           
    • Lux

      Lux - 2008-08-07

      As detailed in my previous post, I think that in the setup instructions we should recomment to use the command line
      argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${user}
      instead of
      argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient}
      in a purely virtual mailbox setup (as is with vanilla PostfixAdmin).

      And we should add the ! # $ * / ? | ^ { } ` ~ & ' + = characters in the local part of the email address stripped in strip_address.
      Looking at the RFC, we should accept quoted local parts too. Maybe there is a perl module to handle this correctly.

      Comments before patching?

       
      • Joseph Cotton

        Joseph Cotton - 2008-08-07

        Seems to be okay, I get the right debug messages. Other than the "#" vs "@" issue. I thought I recalled this coming up somewhere in the postfix docs, but can't find anything yet.

         
        • Joseph Cotton

          Joseph Cotton - 2008-08-07

          Ah, the "#" replacement is done in postfixadmin; specifically edit-vacation.php:

          $vacation_domain = $CONF['vacation_domain'];
          $vacation_goto = preg_replace('/@/', '#', $fUsername);
          $vacation_goto = $vacation_goto . '@' . $vacation_domain;

          I can't see where this was handled going the other way in vacation.pl in the released version. I guess I'm just looking on the surface...

           
1 2 > >> (Page 1 of 2)

Log in to post a comment.