procmail
[Top] [All Lists]

Ans: Virtual Domain's using procmail

1996-12-03 21:03:15


There have been many questions about using procmail for Virtual Domain's.
I was one of the people that asked, and was always told that "procmail
is not the answer, it is a sendmail thing".

I did have to use some new sendmail features, but as it is asked often
enough I figured I'd post my solution (and I promised several people I 
would).  I'm not an expert (although I'm learning fast), so if there are
any sendmail guru's reading this, I don't mind critisism :)

I wanted procmail to do it rather then sendmail for a couple reasons:

  1)  I want the user to be able to directly edit thier Virtual Domain
      email config file.  Using procmail, they have "real time" access
      to thier .procmailrc file.  All setup is done in the owners home
      directory.

  2)  I want the user to be able to set up thier own utilities.  Such as
      auto-responders, users, lists, whatever.  I have over 300 domains
      and REALLY don't want to administer them all.  BTW  I've had NO
      complaints since I set this up.

This is a long post, so hear goes:

SENDMAIL:

  1)  I'm using sendmail 8.8.x, but I'm sure 8.7.x will work.  Also, I use
      the m4 macro files to generate my sendmail.cf, so that is how
      I'm going to explain these.

  2)  Unless someone knows how to change it in the .mc file, I modified
      the cf/mailer/procmail.m4 file.  You have to remove the 'm' in the
      PROCMAIL_MAILER_FLAGS.  For example it should just say:

        `define(`PROCMAIL_MAILER_FLAGS', `Shu')')

      The reason this is done, is so you will receive one email for
      each recipient the email is addressed to.  I havn't found a way
      to get sendmail to pass multiple recipients to procmail.

  3)  In your host.mc file (or whatever you call it), enable "local_procmail"
      "procmail mailer", and "mailertables".  For example:

        -----------------------------start---------------------------------
        VERSIONID(`@(#)generic-hpux9.mc 8.2 (Berkeley) 8/6/95')
        OSTYPE(hpux10)dnl
        FEATURE(local_procmail)dnl
        FEATURE(mailertable, btree /etc/mail/lib/mailertable.db)dnl
        MAILER(procmail)dnl
        MAILER(local)dnl
        MAILER(smtp)dnl
        ------------------------------end----------------------------------

      To compile use:        m4 ../m4/cf.m4 host.mc > host.cf

      This will create a sendmail.cf file that has all the stuff you need.

  4)  In the file /etc/mail/lib/mailertable add one line for each of
      your virtual domains.  For example:

        -----------------------------start---------------------------------
        domain1.com     procmail:/etc/mail/Ehosts/rc.domain1.com
        domain2.com     procmail:/etc/mail/Ehosts/rc.domain2.com
        domain3.com     procmail:/etc/mail/Ehosts/rc.domain3.com
        domain4.com     procmail:/etc/mail/Ehosts/rc.domain4.com
        domain5.com     procmail:/etc/mail/Ehosts/rc.domain5.com
        ------------------------------end----------------------------------

      To compile use:        makemap btree mailertable < mailertable

      That is a <tab> before "procmail..." not spaces.  Now is where you
      have control of your domain with procmail.

PROCMAIL:

  1)  For each domain, create an "rc" file for them defining specific info
      about that domain.  For example:

        -----------------------------start---------------------------------
        OWNER=someuser(_at_)RealDomain(_dot_)net
        DOMAIN=domain1.com
        LIBDIR=/etc/mail/rc.d
        INCLUDERC=$LIBDIR/rc.ehosts
        ------------------------------end----------------------------------

      Then in the "rc.ehosts" file use something like:

        -----------------------------start---------------------------------
        ADMIN=postmaster(_at_)RealDomain(_dot_)net         # Your E-mail admin
        MAILDIR=/etc/mail
        LIBDIR=${MAILDIR}/rc.d
        SHELL=/bin/sh                           # Avoid surprises
        PATH=/bin:/usr/bin:/usr/local/bin:${MAILDIR}/bin
        COMSAT=no                               # Don't notify Comsat
        ENVELOPE_FROM=$1                        # Envelope sender
        ENVELOPE_TO=$2                          # Envelope recipient

        ### This creates a header "X-Envelope-To" containing the original
        ### recipient of the message.  This works even if the recipient
        ### is a Bcc'd address!!!  And since we took the 'm' out of
        ### the procmail flags in the sendmail.cf, it also works for
        ### multiple recipients.
        :0 fhw
        | formail -I"X-Envelope-To:  $ENVELOPE_TO"

        ### I filter all mail sent to "abuse" so I can catch spammers
        :0
        * $ ENVELOPE_TO ?? abuse@"$DOMAIN"
        ! -f $ENVELOPE_FROM $ADMIN

        ### I filter all mail sent to "postmaster" in case there is a 
        ### problem that only I can fix.
        :0
        * $ ENVELOPE_TO ?? postmaster@"$DOMAIN"
        ! -f $ENVELOPE_FROM $ADMIN

        ### Send all messages to the appropriate owner.
        :0
        ! -f $ENVELOPE_FROM $OWNER
        ------------------------------end----------------------------------

      All control is now passwd to the users .procmailrc file, AND with the
      "X-Envelope-To" header, they can route the email properly without 
      losing Bcc'd mail and multiple recipients.

  2)  Setup the users .procmailrc file.  Here is my default:

        ~/.procmailrc
        -----------------------------start---------------------------------
        PATH=/bin:/usr/bin:/usr/local/bin:$HOME/bin
        MAILDIR=$HOME/mail      # You'd better make sure it exists
        COMSAT=no               # Don't notify for incoming mail.
        LIBDIR=/etc/mail/rc.d   # Location of shared procmail scripts

        ### Initialize the Virtual Email Domain services.
        INCLUDERC=$LIBDIR/rc.init          # Leave this line alone.

        DOMAIN=___ENTER_YOUR_DOMAIN___
        :0
        * $ ENVELOPE_DOMAIN ?? $DOMAIN
        {
          ADDR=__email__  FRWD=__forward__       INCLUDERC=$LIBDIR/rc.deliver
          ADDR=__email__  FRWD=__forward__       INCLUDERC=$LIBDIR/rc.deliver
          ADDR=__email__  FILE=__file__          INCLUDERC=$LIBDIR/rc.deliver
          INCLUDERC=$LIBDIR/rc.term_dom    # Leave this line alone.
        }
        ------------------------------end----------------------------------

      This will even handle multiple domains, if a single user has more
      then one.  Simply create one recipe block for each domain.

        $LIBDIR/rc.init
        -----------------------------start---------------------------------
        ###  Get the Envelope recipient of the message.  The header
        ###  X-Envelope-To must be present to be able to process any
        ###  virtual domain mail.
        ENVELOPE_TO=`formail -zxX-Envelope-To:`

        ###  Grab the domain we are working with.
        :0
        * $ ENVELOPE_TO ?? @\/.*
        { ENVELOPE_DOMAIN=$MATCH }

        ###  Strip the X-Envelope-To header off, to avoid sending any BCC info.
        :0 fhw
        * ! DEBUG ?? .                     # Leave the header there if DEBUGing
        | formail -I"X-Envelope-To:"
        ------------------------------end----------------------------------

        $LIBDIR/rc.deliver
        -----------------------------start---------------------------------
        ###  If the message is addressed to the user defined in ADDR at domain
        ###  DOMAIN, then either forward (FRWD) or file (FILE) the message to
        ###  the appropriate destination.
        :0
        * $ ENVELOPE_TO ?? ^${ADDR}(_at_)${DOMAIN}
        {
          :0 c
          * FRWD ?? .
          ! ${FRWD}

          :0 a
          { FLAG=delivered }

          :0 wc:
          * FILE ?? .
          $FILE

          :0 a
          { FLAG=delivered }
        }

        ###  Clear these so they don't affect the next query
        FRWD
        FILE
        ------------------------------end----------------------------------

        $LIBDIR/rc.term_dom
        -----------------------------start---------------------------------
        OLDSHELL=${SHELL}                  # Just in case
        SHELL=/bin/sh

        ### if the mail was delivered to someone, stop now.  If there
        ### is another recipient, sendmail will send a new email (because
        ### we took out the 'm' procmail flag).
        ### If no matches were found, the mail will just "drop thru" to
        ### the owners mailbox.
        :0
        * FLAG ?? delivered
        { HOST=_stop_now_ }

        SHELL=${OLDSHELL}
        ------------------------------end----------------------------------

      There are other things I include in there, such as some default
      auto-responders, vacation messages, different notifications for
      unknown users, etc.  However, I can't give away ALL my secrets :)
      I also stripped out a lot of my comments, to save space in this
      email.

If you reply to this, please CC me, as I don't always get a chance to 
read all the procmail list messages.

Dan T.

<Prev in Thread] Current Thread [Next in Thread>