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