Article View: gnu.emacs.vm.bug
Article #9135Re: How to use VM with alternative mailboxes?
From: Rich Kaul
Date: Thu, 05 Mar 1992 18:13
Date: Thu, 05 Mar 1992 18:13
388 lines
16367 bytes
16367 bytes
In article <1992Mar5.165633.6233@spool.cs.wisc.edu> jcargill@oka.cs.wisc.edu (Jon Cargille) writes:
My mail filter appends mail directly to the vm folders in my ~/Mail
directory. Some day, this will probably bite me, if mail arrives
precisely when I'm saving a folder. But for me, for the moment, the
risk is worth it.
Then you must be on lower volume mailing lists than I'm on. I have
several that if I take more than 15 minutes to get caught up on,
there'll be a new message and I'll have to problem of an inconsistent
mailbox.
For example, suppose I were to visit folder "some-mailing-list", in my
"~/Mail" directory, and vm-aux-spool-directory was set to
"~/Mail/spool". Then vm would automatically look for a
"~/Mail/spool/some-mailing-list" spool file, and incorporate any new
messages into the folder residing in "~/Mail".
That's almost exactly what I do, with a very small perl file and my
~/.vm file. The modifications are pretty trivial. I won't say
they're clean, but they're trivial :-)
Since more than a few people have asked about the scripts, I thought
I'd post them as they're pretty short. All that's required is the
~/.vm file if you can deliver/sort/whatever your incoming mail to your
"spool" directory (I call mine ~/Mail/incoming). I'll include the
perl script I use for delivering mail (useful in a heterogenous
environment).
-rich
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 1)."
# Contents: .vm ppmd
# Wrapped by kaul@ee.eng.ohio-state.edu on Tue Mar 3 21:41:25 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f '.vm' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'.vm'\"
else
echo shar: Extracting \"'.vm'\" \(5646 characters\)
sed "s/^X//" >'.vm' <<'END_OF_FILE'
X; Rich Kaul's .vm file for customization of the VM emacs mailer
X;
X; Use all you want, however:
X; (a) use at your own risk
X; (b) don't use features you don't understand
X; (c) edit liberally to remove features you can't use
X
X; Quick Summary: Use vm for mail reading since it uses Unix-style mailboxes
X; All these lines serve to set up various functions.
X(autoload 'vm "vm" nil t)
X(autoload 'vm-visit-folder "vm" nil t)
X(setq vm-folder-directory "~/Mail/") ; default mail directory
X(setq vm-crash-box "~/Mail/.crashbox") ; airbag if system crashes ;-)
X(setq vm-flush-interval nil) ; disable timers
X(setq vm-inhibit-startup-message t)
X(setq vm-delete-after-saving t)
X(setq vm-group-by "subject") ; for discussions and mailing lists
X(setq vm-delete-empty-folders t) ; be tidy
X(setq vm-preview-lines nil)
X(setq vm-follow-summary-cursor t)
X(setq vm-startup-with-summary "ok") ; read mail more like news
X(setq vm-reply-subject-prefix "Re: ") ; keep the Re: for people
X;(setq vm-included-text-attribution-format nil)
X(setq vm-strip-reply-headers t)
X(setq vm-primary-inbox (expand-file-name "~/Mail/IMPSTUFF"))
X
X;; Upon startup in vm-mode, I want to bind keys to make getting at
X;; sub-mailboxes easier. This should do it.
X(setq vm-mode-hooks
X '(lambda()
X (make-local-variable 'version-control)
X (setq version-control 'never) ; keep minimal backups
X (local-unset-key "\C-cn") ; set to system mailbox
X (local-set-key "\C-cn" 'vm-normal)
X (local-unset-key "\C-cp") ; keystroke to get to personal mbox
X (local-set-key "\C-cp" 'vm-personal)
X (local-unset-key "\C-c\C-f") ; keystroke to firearms mbox
X (local-set-key "\C-c\C-f" 'vm-firearms)
X (local-unset-key "\C-cc") ; keystroke to connectionists list
X (local-set-key "\C-cc" 'vm-connect)
X (local-unset-key "\C-cs") ; to get to *ugh* system stuff
X (local-set-key "\C-cs" 'vm-system)
X (local-unset-key "\C-cm") ; other mailing lists
X (local-set-key "\C-cm" 'vm-misc)))
X
X(defun vm-normal ()
X "Set up reading from the default mail box"
X (interactive)
X (setq vm-primary-inbox "~/Mail/IMPBOX")
X (setq vm-spool-files (list (expand-file-name "/var/spool/mail/kaul")))
X (vm-visit-folder "~/Mail/IMPBOX"))
X
X(defun vm-personal ()
X "Set up reading of the personal mail buffer"
X (interactive)
X (setq vm-primary-inbox "~/Mail/PBOX")
X (setq vm-spool-files (list (expand-file-name "~/Mail/incoming/personal")))
X (vm-visit-folder "~/Mail/PBOX"))
X
X(defun vm-firearms ()
X "Set up reading of the firearms mail buffer"
X (interactive)
X (setq vm-primary-inbox "~/Mail/FIREBOX")
X (setq vm-spool-files (list (expand-file-name "~/Mail/incoming/firearms")))
X (vm-visit-folder "~/Mail/FIREBOX"))
X
X(defun vm-system ()
X "Set up reading of the systems mail buffer"
X (interactive)
X (setq vm-primary-inbox "~/Mail/SYSBOX")
X (setq vm-spool-files (list (expand-file-name "~/Mail/incoming/system")))
X (vm-visit-folder "~/Mail/SYSBOX"))
X
X(defun vm-connect ()
X "Set up reading of the Connectionist's mail buffer"
X (interactive)
X (setq vm-primary-inbox "~/Mail/CONNECTBOX")
X (setq vm-spool-files (list (expand-file-name "~/Mail/incoming/connect")))
X (vm-visit-folder "~/Mail/CONNECTBOX"))
X
X(defun vm-misc ()
X "Set up reading of the misc mailing lists mail buffer"
X (interactive)
X (setq vm-primary-inbox "~/Mail/MISCBOX")
X (setq vm-spool-files (list (expand-file-name "~/Mail/incoming/misc")))
X (vm-visit-folder "~/Mail/MISCBOX"))
X
X; Try and get the incoming and outgoing stuff done prettily
X;(setq vm-auto-folder-case-fold-search t
X; mail-archive-file-name (concat vm-folder-directory "INBOX"))
X(setq vm-auto-folder-alist
X '(
X ("from"
X ("\\([^<(@%]*\\)" .
X (string-remove-chars
X '(32 9 10 13) ;SPC,TAB,LFD,RET
X (vm-afa-match-format "%s" 1)))
X )
X ("to"
X ("\\([^<(@%]*\\)" .
X (string-remove-chars
X '(32 9 10 13) ;SPC,TAB,LFD,RET
X (vm-afa-match-format "%s" 1)))
X )
X )
X)
X
X;; Some utils:
X(defun string-remove-chars (list-of-chars a-string)
X "Function: Removes the characters in LIST-OF-CHARS from A-STRING"
X (cond ((zerop (length a-string)) a-string)
X (t
X (if (memq (string-to-char a-string) list-of-chars)
X (string-remove-chars list-of-chars (substring a-string 1))
X ;;;ELSE:
X (concat
X (substring a-string 0 1)
X (string-remove-chars
X list-of-chars
X (substring a-string 1)))))));
X
X;;;
X;;; The util below is defined by Noah Friedman (friedman@ai.mit.edu)
X;;;--------------------------------------------------------------------
X(defun vm-afa-match-format (format-str &rest match-values)
X "Creates a string of the format FORMAT-STR by getting
Xbuffer-substrings determined by the &rest values MATCH-VALUES. This
Xfunction is meant to be used when setting vm-auto-folder-alist. It
Xallows you to construct filenames from saved regexp patterns.
X
XExample:
X (setq vm-auto-folder-alist
X '(\"To\"
X (\"fsf-\\\\([^@%]*\\\\)\" . (vm-afa-match-format-format
X\"fsf-%s\" 1))
X (\"foo-\\\\(bar\\\\)@\\\\(baz\\\\)\" . (vm-afa-match-format
X\"foo%s@%s\" 1 2))))
X
XThus, a To: line addressed to fsf-staff@gnu.ai.mit.edu would be saved
Xby
Xdefault in a folder called \"fsf-staff\", and mail addressed to
Xfoo-bar@baz would go in a folder called \"foobar@baz\"."
X (apply 'format format-str
X (mapcar
X (function
X (lambda (match-value)
X (buffer-substring (match-beginning match-value)
X (match-end match-value))))
X match-values)))
X;;;--------------------------------------------------------------------
END_OF_FILE
if test 5646 -ne `wc -c <'.vm'`; then
echo shar: \"'.vm'\" unpacked with wrong size!
fi
# end of '.vm'
fi
if test -f 'ppmd' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ppmd'\"
else
echo shar: Extracting \"'ppmd'\" \(6007 characters\)
sed "s/^X//" >'ppmd' <<'END_OF_FILE'
X#!/usr/local/bin/perl
X
X# A perl mail agent. The basic premise is that mail from certain
X# people demands attention immediately, so it gets put in the normal
X# system mailbox. All other mail is sorted based on who it's from and
X# placed in the appropriate files in a different directory. This is,
X# of course, easily customizable.
X#
X# To use this, create a .forward file like (complete WITH quotes):
X# "|/home4/kaul/bin/ppmd /home4/kaul kaul >> /home4/kaul/.maillog 2>&1"
X# and configure this file in the CONFIGURE HERE section.
X#
X# Author: Rich Kaul (kaul@icarus.eng.ohio-state.edu)
X# Date: 12/2/90
X#
X# The credit where credit is due department: the core of the message
X# parsing is based on Larry Wall's mailagent script.
X
X# These two values are gotten from the second and third arguments on
X# the command line in your ~/.forward file.
X($HOME, $USER) = @ARGV;
X
X# We use file locking to make sure that no more than one process is
X# writing to the mail box at a given time.
X$LOCK_SH = 1; # Values for flock() calls.
X$LOCK_EX = 2;
X$LOCK_NB = 4;
X$LOCK_UN = 8;
X
Xumask(077); # Get a little privacy.
X
X# Now run and get the headers. We have to parse the headers before we
X# can figure out delivery. All headers are available for view; they are
X# prefixed by $H and the header name is set to lower case. For
X# example, valid header references are $Hto, $Hdate, etc.
Xwhile (<stdin>) {
X
X # Do this on the From_ line only. What it does is set $from to
X # the name of the person who sent the mail. It strips everything
X # after the @ in the address and before the ! to find the name.
X if (1 .. 1) {
X if (/^From\s+(\S+)\s+[^\n]*(\w{3}\s+\d+\s+\d+:\d+)/) { $from = $1; }
X $from =~ s/@.*//; # remove trailing @machine
X $from =~ s/%.*//; # remove trailing %machine
X $from = $1 if $from =~ /.*!([^\n]+)/; # remove leading ! paths
X }
X
X # This section operates on the header of the message. We create
X # an array of header keys to work on later.
X if (1 .. /^\s*$/) {
X s/^From: ([^<]*)\s+<(.*)>$/From: $2 ($1)/; # rewrite ugly header
X $header .= $_;
X chop;
X if (/^\s*$/) {
X foreach $key (keys(header)) {
X eval "\$H$key = \$header{'$key'}";
X }
X }
X else {
X if (s/^([-\w]+):\s*//) {
X ($headline = $1) =~ y/A-Z-/a-z_/;
X $header{$headline} .= "\n" if $header{$headline} ne '';
X }
X else {
X s/^\s+/ /;
X }
X $header{$headline} .= $_;
X }
X }
X # And here we make the body of the message.
X else {
X $body .= $_;
X }
X}
X
X###################################################################
X# CONFIGURE HERE
X###################################################################
X#
X# This section does several things. It sets a value $root where I put
X# my incoming mail files. It also sets $box to the default system
X# mail box (where xbiff and the like can find it), an emergency
X# dumping box for cases where delivery to the desired mbox isn't
X# possible. It also sets the default destination $dest to a "generic"
X# mail box. Configure to your own setup.
X$root = "$HOME/Mail/incoming"; # root of personal mail tree.
X$box = "/usr/spool/mail/$USER"; # default mail box.
X$GIVE_UP_BOX = "$box"; # emergency dumping box.
X$dest = "$root/personal"; # where things go by default
X#
X# This is the section that determines where mail is sent. You do this
X# by looking for patterns in the header (or body *shudder*) and
X# setting the variable $dest to the appropriate mail box. In case you
X# don't know, the easiest way to do this in perl is via the
X# =~ /pattern/mod syntax, where pattern is the pattern you're looking
X# for in the header and mod is a modifier. Typically the only
X# modifier you'll want to use is i to make the comparison case
X# insensitive.
X#
X# Order is very important here, since this is one giant if/then/else
X# and the structure is exited upon the first match. Note that if
X# nothing is matched, the mail is delivered to the default mbox set in
X# $dest above.
X#
X# This is a sample section showing how I parse my mail. First, junk
X# to/from the system is routed to the system inbox.
Xif($from =~ /root/ || $from =~ /news/) { $dest = "$root/system";}
Xelsif($Hto =~ /site/i || $Hcc =~/site/i) { $dest = "$root/system";}
X# Now mailer junk
Xelsif($Hfrom =~ /Mailer-Daemon/i) { $dest = "$root/mailer-daemon";}
X# Handle mailing lists. Lower volume ones don't get their own files.
Xelsif($from =~ /firearms/i || $Hcc =~ /firearms/i) {$dest = "$root/firearms";}
Xelsif($Hto =~ /connection/i || $Hcc =~ /connection/i) {
X $dest = "$root/connect";}
Xelsif($from =~ /freemacs/i || $Hcc =~ /freemacs/i) {$dest = "$root/misc";}
Xelsif($Hto =~ /gnuplot/ || $Hcc =~ /gnuplot/) {$dest = "$root/misc";}
Xelsif($Hto =~ /linkers/ || $Hcc =~ /linkers/) {$dest = "$root/linkers";}
X# List the people who can crash into the system mailbox, seting off
X# all my mail flags and getting my immediate attention.
Xelsif($from =~ /alden/ || $from =~ /monty/ || $from=~/yarri/) {$dest = $box;}
Xelsif($from =~ /bibyk/ || $from =~ /adkins/ || $from =~ /zaka/) {$dest = $box;}
Xelsif($from =~ /kaul/) {$dest = $box;}
X###########################################################################
X# END CONFIGURE HERE
X###########################################################################
X
X# Now we do the delivery. It's to a *file*.
X$all = $header . $body;
Xopen(BOX, ">>$dest") || do gag ("Can't open $dest ($< $>): $!");
X
X# Lock the box before we do delivery.
Xdo flocker(BOX,$LOCK_EX);
Xprint BOX $all,"\n\n";
Xdo flocker(BOX,$LOCK_UN);
X
X# File locking subroutine.
Xsub flocker {
X local ($file, $mode) = @_;
X eval 'flock($file,$mode);';
X seek($file, 0, 2); # in case it was appended while we were waiting
X}
X
X# For some reason mail couldn't get delivered. Dump the message in the
X# emergency mailbox and exit.
Xsub gag {
X open(ERR_BOX, ">>$GIVE_UP_BOX") || die "I'm really hosed. I can't even open the emergency box $GIVE_UP_BOX\n";
X
X print @_;
X do flocker(ERR_BOX,$LOCK_EX);
X print ERR_BOX $all,"\n\n";
X do flocker(ERR_BOX,$LOCK_UN);
X exit 1;
X}
X
END_OF_FILE
if test 6007 -ne `wc -c <'ppmd'`; then
echo shar: \"'ppmd'\" unpacked with wrong size!
fi
chmod +x 'ppmd'
# end of 'ppmd'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have the archive.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Rich Kaul | "A NeXT is the only Unix workstation where you
kaul@ee.eng.ohio-state.edu | sit a salesman down and expect him to do any
kaul.2@osu.edu | work." -- a certain MorningStar programmer
Technical Details
Message-ID:
<KAUL.92Mar5131322@nile.ee.eng.ohio-state.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!sample.eng.ohio-state.edu!ee.eng.ohio-state.edu!kaulReferences:
<KAUL.92Mar3194425@amazon.ee.eng.ohio-state.edu> <p0msrINNgsr@hilbert.math.ksu.edu> <9203041537.AA15068@wendy-fate.UU.NET> <1992Mar5.165633.6233@spool.cs.wisc.edu>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: f6829,309a564d2a891328 X-Google-Attributes: gidf6829,public X-Google-ArrivalTime: 1992-03-05 17:09:35 PST Newsgroups: gnu.emacs.vm.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!sample.eng.ohio-state.edu!ee.eng.ohio-state.edu!kaul From: kaul@ee.eng.ohio-state.edu (Rich Kaul) Subject: Re: How to use VM with alternative mailboxes? In-Reply-To: jcargill@oka.cs.wisc.edu's message of Thu, 5 Mar 1992 16:56:33 GMT Message-ID: <KAUL.92Mar5131322@nile.ee.eng.ohio-state.edu> Sender: news@ee.eng.ohio-state.edu Organization: The Ohio State University Dept of Electrical Engineering References: <KAUL.92Mar3194425@amazon.ee.eng.ohio-state.edu> <p0msrINNgsr@hilbert.math.ksu.edu> <9203041537.AA15068@wendy-fate.UU.NET> <1992Mar5.165633.6233@spool.cs.wisc.edu> Date: Thu, 5 Mar 1992 18:13:22 GMT