procmail
[Top] [All Lists]

Group Mail Forwarding Recipe

1997-07-29 08:29:00
    With the kind help of members of this list, I finally have
my group mail forwarding (a kind of primitive mail reflector)
recipe going.  All it needs is formail (which presumably one
would already have), egrep, and, optionally, gzip.  I am
including it here out of appreciation.  Anyone may have it
freely for any legal use.

    Yes, I know that there are some inefficiencies in this code.
I have left them in _deliberately_ in order to make the code
clearer to me.  This was written for a low-volume discussion
group, and internal efficiencies are less critical.

Paul <pobart(_at_)access(_dot_)digex(_dot_)net>

################################################################
#  Implement a simple, manually-maintained mail forwarder.     #
#  This recipe is only intended for a small, closed group.     #
#  There is no automatic subscribe or unsubscribe function.    #
#  There is no automatic archive retrieval from the backup.    #
#  There are none of the other functions of a mailing list.    #
#                                                              #
#  Group mail must be sent to a specific name at my address.   #
#  Recipients are listed in the file designated by $USERLIST,  #
#  one line for each.  Variables $MY_ADDR, $SPAMFOLDER,        #
#  $VERBOSITY, and $LOGGING are defined earlier in the         #
#  procmailrc hierarchy.  Variables below may be changed       #
#  as appropriate.                                             #
#                                                              #
#  (Note: this code may not be maximally efficient but is      #
#  (structured the way it is for better personal understanding #
#  (and use.  It is presumed that the daily volume will be     #
#  (low, so that efficiency considerations are less crucial.)  #
################################################################

GROUPNAME="glosa"
USERLIST="$HOME/$GROUPNAME/grouplist"
GROUPORG="GREGA_DICE_DE_GLOSA"

FULLNAME="$GROUPNAME <$MY_ADDR>"
MAILFILE="$HOME/$GROUPNAME/$GROUPNAME.archive.gz"

# Control logging for debugging purposes
#VERBOSE=on
#LOGABSTRACT=yes
VERBOSE=$VERBOSITY
LOGABSTRACT=$LOGGING

# If this is a list message, append a compressed copy to
# the archive file.  Then have formail massage the message
# as needed.  Note that $FULLNAME is not used in the
# conditions in order catch different address formats.
# (During testing, one legitimate, unsolicited incoming
# (email triggered the recipe when it should not have due
# (to an unanticipated set of To: headers.  Not using
# (procmail's ^TO or ^TO_ macros is deliberate, based on
# (such experience with incoming mail.)
# Try to preserve essential MIME headers.

# Is it a potentially eligible submission?
:0
* $ (^To:|^Cc:) *$GROUPNAME
* $ ^TO$MY_ADDR
* $ ! ^X-List: *$GROUPNAME
* $ ! ^X-Loop: *$MY_ADDR
{
# It passed the first test for eligibility

    # Find out whom it is from
    # (This gets the canonical email address)
    WHOFROM=`formail -XFrom: | formail -rtz -xTo:`

    # Pick off the subject for reuse
    :0
    * ^Subject: *\/[^ ].*
    { THESUBJ=$MATCH }

    # Is this an eligible sender?  Have egrep see
    # whether the sender is a member of the group
    :0 w
    * ? egrep -is $WHOFROM $USERLIST
    { }

        # ==========================================
        # ===== begin eligible submitter block =====
        # ==========================================
        # Eligible submission: now reflect the mail
        # to all members of the group
        :0 a
        {

            # First append a copy of the message to the backup file
            # (This is optional and could be commented out.  The
            # (use of this file is primarily for tracking and debugging.)
            :0 c:
            | gzip -9fc >> $MAILFILE

            # Get the complete sender's address to turn it around
            :0
            * ^From: *\/[^ ].*
            { SENDER=$MATCH }

            # Get the incoming message-id
            :0
            * ^Message-ID: *\/[^ ].*
            { MID=$MATCH }

            # Get three MIME headers for preservation
            :0
            * ^Mime-Version: *\/[^ ].*
            { MIMEVER=$MATCH }

            :0
            * ^Content-Type: *\/[^ ].*
            { MIMETYPE=$MATCH }

            :0
            * ^Content-Transfer-Encoding: *\/[^ ].*
            { MIMEXFER=$MATCH }

            # Have formail format the message for recipients
            # (We call it  Precedence: list  merely as a convenience)
            :0 fw
            | formail -krz -p ""                         \
              -I "Reply-To: $FULLNAME"                   \
              -I "From: $SENDER"                         \
              -I "Subject: $THESUBJ"                     \
              -I "X-List: $GROUPNAME"                    \
              -I "X-Loop: $MY_ADDR"                      \
              -I "X-Info: Private Discussion Group Only" \
              -I "Precedence: list"                      \
              -I "Message-ID: $MID"                      \
              -I "Mime-Version: $MIMEVER"                \
              -I "Content-Type: $MIMETYPE"               \
              -I "Content-Transfer-Encoding: $MIMEXFER"  \
              -I "Errors-To: $MY_ADDR"                   \
              -I "Resent-From: $FULLNAME"                \
              -I "Resent-Sender: $FULLNAME"              \
              -I "Organization: $GROUPORG"

            # Send the mail out to all
            :0 a
            ! `cat $USERLIST`

            VERBOSE=$VERBOSITY
            LOGABSTRACT=$LOGGING

        }
        # ========================================
        # ===== end eligible submitter block =====
        # ========================================


        # ============================================
        # ===== begin INeligible submitter block =====
        # ============================================

        # If not eligible, send back a nastygram and store a copy
        # for examination, thus terminating the outer recipe
        :0 E
        {

            # When was it mailed?
            :0
            * ^Date: *\/[^ ].*
            { INDATE=$MATCH }

            # Log disposition; splitting "" across lines is deliberate
            LOG="Group rejection: $INDATE $WHOFROM $THESUBJ
"

            :0 c
            | (formail -r -I"Precedence: junk"                          \
                 -I"X-Loop: $MY_ADDR";                                  \
               echo "Your mail dated: $INDATE";                         \
               echo "and concerning Subject: $THESUBJ";                 \
               echo "was submitted to a private discussion group,";     \
               echo "but you are not an eligible member of the group."; \
               echo "--- Paul Bartlett <$MY_ADDR>"                      \
              ) | $SENDMAIL -oi -t

            :0:
            $SPAMFOLDER

            VERBOSE=$VERBOSITY
            LOGABSTRACT=$LOGGING

        }

        # ============================================
        # ====== end INeligible submitter block ======
        # ============================================

}
# ====== End group mail forwarder recipe ======

# Be sure to reset logging in case we fall all the way through
VERBOSE=$VERBOSITY
LOGABSTRACT=$LOGGING

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