karl@godiva.cis.ohio-state.edu (Karl Kleinpaste) (09/23/89)
I get an awful lot of mail. Lately, I've been pushing 300 pieces/day. A lot of that's daemon-generated trash (read it fast and throw it away), a lot of it is non-critical mailing list stuff, and the rest is varyingly-important text intended specifically for myself. The normal mail tools I've found don't cut it for me, to make things manageable so I can read mail and get some Real Work done, too. So a few months back, under GNUS 3.11, I figured out how to convince GNUS to read mail and news in a single incarnation. I posted that scheme here back then. This is the same scheme, updated for GNUS 3.12, with what I hope is a bit more readable procedure for putting it to use. It requires one change to GNUS code proper (a very small change to nnspool.el), a couple of shell scripts, some new .emacs things, and a .forward file to aim your mail into the pseudonews hierarchy. I don't promise that this is trivial to install, or anything like that. Parts of it (especially the pmd [personal mail deliverer] script) are extremely personalized, and how you put it to use depends on how you intend to try to classify your mail. The end result of the mess is highly desirable, however - a lot of mail divvied up into manageable categories that look for all the world like newsgroups. You will find (it was to my own unending joy) that you can use KILL files on your mail - what a neat idea. There is a downside or two to it, as well: [1] The idea of "deleting" a message isn't the same as for a conventional mailer interface; a message is marked `D' but that doesn't mean it disappears, so you have to do some sort of an "expire" from time to time. I do this every couple of weeks, spending half an hour or so trimming down the mass of gobbledygook I've received recently into just the most recent stuff that I really do want to keep around just-in-case. [2] There is a bug in GNUS somewhere which I haven't been able to trace, where replying to a message via mail causes the trailing character of either the originator's address or the subject to be stripped off; this doesn't happen with real newsgroups, nor with all mail, so I suspect it's either POM-dependent or else it depends on some quirky header ordering which GNUS doesn't expect. If anyone gets around to fixing this, please let me know. Have fun, --Karl #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # .emacs # .forward # make-active # nnspool-diff # pmd # This archive created: Sat Sep 23 00:09:16 1989 # By: Karl Kleinpaste (OSU) export PATH; PATH=/bin:$PATH echo shar: extracting "'README'" '(4451 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^KK//' << \GNUSMAIL > 'README' KKThis file documents a scheme whereby GNUS can become one's universal KKnews and mail interface. Use of this scheme depends on the following: KK [a] News-reading using a local news spool; NNTP is not possible. KK [b] Availability of Berkeley symbolic links, to fool GNUS into KK reading news in two places at once. KK [c] Support of .forward files for mail delivery, and in KK particular piped aliases in .forward files. KK [d] GNUS 3.12. KK KKPlease read this entire description (several times) before putting any KKof it to use, to be sure you understand what it is that you are KKaccomplishing along the way. KK KKPROCEDURE: KK KK[1] Build a newsgroup symlink tree. KK mkdir ~/Memos KK cd ~/Memos KK foreach i (/usr/spool/news/*) KK ln -s $i KK end KKNow the variable nnspool-spool-directory can be set to the value KK"~/Memos/" and things would work just like they always have. But of KKcourse we're nowhere near done yet. KK KK[2] Decide on a news directory hierarchy to be placed in parallel with KKnormal news. I use "personal.*" (for personal mail), "list.*" (for KKmailing-list-related things), and "mailer-daemon" (so that bounces KKfrom mailer daemons around the world don't clutter up your Real Mail KKthat you really want to read). Make news-like directories for these. KK mkdir personal list mailer-daemon KK mkdir personal/general personal/special-person-1 personal/s-p-2 KK mkdir list/general list/listname-1 list/listname-2 list/listname-3 KK KK[3] Initialize a pair of counter files for each newsgroup. These will KKbe used for the max and min fields in the fake active file. Also KKcreate "KEY" files, used in mailbox delivery locking. KK foreach i (personal/* list/* mailer-daemon) KK echo 0 > $i/.first KK echo 0 > $i/.last KK touch $i/KEY KK end KK KK[4] Copy the "make-active" script into your private bin directory. KK(_Everyone_ has a private bin directory, right?) Also copy the "pmd" KKscript (personal mail deliverer) to the same place, and edit it for KKwhatever personalizations you wish to give it. I detect my usual KKpseudonewsgroup pattern of personal.*, list.*, and mailer-daemon. KKThis script can be arbitrarily complex; have a blast. BEWARE of the KKfact that certain incarnations of csh are [cough] deficient and cannot KKcope successfully with the long "mailer-daemon" regexp; case in point, KKHP-UX 6.2's csh. KK cp make-active pmd ~/bin KK emacs ~/bin/pmd KK KK[5] Edit the sample .emacs stuff into your own .emacs. Note that a KKnumber of items in there are peculiar to myself. (I never said that KKsetting this up was going to be easy. But neither is it exceptionally KKpainful, just somewhat tedious.) Change function names and variable KKvalues as appropriate to be useful to yourself. KK emacs ~/.emacs KK KK[6] Apply the enclosed patch to nnspool.el, and recompile it. KK patch -d /usr/local/lib/emacs/lisp < nnspool-diff KKThis makes the functions and other stuff you've done to your .emacs KKuseful. The patch causes nnspool to look for a user-defined function KKwhich supplies the name of the active file to the nnspool functions. KKThe nnspool-personal-active-file function builds a new active file KKevery time called, and then returns the name of that file to the KKcalling function. (People within Ohio State Computer Science can skip KKthis patch-&-recompile step, since it's already done.) KK KK[7] SAVE COPIES OF YOUR .newsrc AND RELATED FILES. One never knows KKjust how far one might screw oneself up, and it would be nice to be KKable to recover from disaster, don't you agree? KK KK[8] Install a .forward like the one supplied. Make it look right for KKyour home directory and login name, of course. Send yourself some KKtest mail, and check to see that it gets delivered appropriately in KKyour new pseudonewsgroup hierarchy. KK KK[9] Fire up a fresh Emacs and invoke GNUS. You will observe that KKgetting new news (at the stage "Reading active file...") takes a bit KKlonger, because nnspool-personal-active-file spawns make-active, which KKis hacking up a fresh active file for you. You will also observe that KKyou are magically subscribed to a whole slew of new "newsgroups" which KKdon't really exist. KK KK[10] You know that weird guy that's been writing you mail every other KKday for the last month? The one you never want to hear from again? KKNow you don't have to hear from him - ever. The first time you see KKmail from him (probably in personal.general), do this: KK M-k KK C-c C-k C-a KK C-c C-c KKHe's history as far as mail from him is concerned. KK KKBug reports, improvements, suggestions KKto the scheme => karl@cis.ohio-state.edu. GNUSMAIL if test 4451 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 4451 characters)' fi fi # end of overwriting check echo shar: extracting "'.emacs'" '(1074 characters)' if test -f '.emacs' then echo shar: will not over-write existing file "'.emacs'" else sed 's/^KK//' << \GNUSMAIL > '.emacs' KK; KK; GNUS things: Mail and news in one incantation. KK; Definitely not for the weak of heart. KK; KK(setq gnus-nntp-server "") KK(setq gnus-nntp-service nil) KK(load "gnus") ; I don't see any point in autoloading this. KK(setq gnus-ignored-headers KK (concat gnus-ignored-headers KK "\\|^Errors-To:\\|^Precedence:\\|^Received:\\|^UNIX-From:")) KK(setq nnspool-spool-directory "~/Memos/") ; note trailing `/' KK(defvar karl-active-file-maker "~/bin/make-active" KK "*Personalized active file generator") KK(defvar karl-active-file "~/Memos/active" KK "*Personalized active file") KK(defun nnspool-personal-active-file () KK "Returns a filename string for a personal active file." KK (call-process karl-active-file-maker nil nil nil KK ; remaining stuff is args to the active file maker. KK nnspool-spool-directory KK "personal/general" "personal/bob" "personal/romig" KK "personal/george" "personal/paul" "personal/zwicky" KK "personal/northrup" "personal/uucp" "personal/karl" KK "personal/amanda" KK "list/general" "list/firearms/politics" "list/firearms" KK "mailer-daemon") KK karl-active-file KK ) GNUSMAIL if test 1074 -ne "`wc -c < '.emacs'`" then echo shar: error transmitting "'.emacs'" '(should have been 1074 characters)' fi fi # end of overwriting check echo shar: extracting "'.forward'" '(35 characters)' if test -f '.forward' then echo shar: will not over-write existing file "'.forward'" else sed 's/^KK//' << \GNUSMAIL > '.forward' KK"|/n/dinosaur/0/karl/bin/pmd karl" GNUSMAIL if test 35 -ne "`wc -c < '.forward'`" then echo shar: error transmitting "'.forward'" '(should have been 35 characters)' fi fi # end of overwriting check echo shar: extracting "'make-active'" '(903 characters)' if test -f 'make-active' then echo shar: will not over-write existing file "'make-active'" else sed 's/^KK//' << \GNUSMAIL > 'make-active' KK#!/bin/cshe -f KK# KK# Builds a pseudoactive file which represents personal mail under KK# $1 plus pseudonews in $1/{comp,soc,rec,talk,sci,soc,misc,...}. KK# KKif ($#argv < 2) then KK echo make-active: usage: make-active directory-subdirs... KK exit 87 KKendif KKset dir=$1 KKshift KKset active=$dir/active KKset nactive=/usr/lib/news/active KK# KK# Find directories and their associated .last files. Then take KK# base dirnames, change to newsgroup name format, and build the KK# mail-based active file out of it all. KK# KKcd $dir KKset list=($*) KKset count=$#list KKset nlist=() KKset first=() KKset last=() KKforeach i ($list) KK set first=($first $i/.first) KK set last=($last $i/.last) KK set nlist=($nlist `echo $i | tr / .`) KKend KKcp /dev/null $active KK@ i = 1 KKwhile ($i <= $count) KK echo $nlist[$i] `cat $last[$i]` `cat $first[$i]` n >> $active KK @ i ++ KKend KK# KK## Defunctitude: KK# Now add the whole regular active file. KKcat $nactive >> $active KK# KKexit 0 GNUSMAIL if test 903 -ne "`wc -c < 'make-active'`" then echo shar: error transmitting "'make-active'" '(should have been 903 characters)' fi chmod +x 'make-active' fi # end of overwriting check echo shar: extracting "'nnspool-diff'" '(1043 characters)' if test -f 'nnspool-diff' then echo shar: will not over-write existing file "'nnspool-diff'" else sed 's/^KK//' << \GNUSMAIL > 'nnspool-diff' KKdiff -c nnspool.el~ nnspool.el KK*** nnspool.el~ Thu Jul 6 09:29:59 1989 KK--- nnspool.el Thu Jul 6 11:40:39 1989 KK*************** KK*** 242,248 **** KK (defun nnspool-request-list () KK "List valid newsgoups." KK (save-excursion KK! (nnspool-find-file nnspool-active-file))) KK KK (defun nnspool-request-last () KK "Set current article pointer to the previous article KK--- 242,248 ---- KK (defun nnspool-request-list () KK "List valid newsgoups." KK (save-excursion KK! (nnspool-find-file (nnspool-pick-active-file)))) KK KK (defun nnspool-request-last () KK "Set current article pointer to the previous article KK*************** KK*** 358,360 **** KK--- 358,368 ---- KK (setq idx (1+ idx))) KK string KK )) KK+ KK+ (defun nnspool-pick-active-file () KK+ "Return a filename string for the active file." KK+ ;; If the user has defined his own active file creator, KK+ ;; use it. Otherwise, return the "standard" active file. KK+ (if (fboundp 'nnspool-personal-active-file) KK+ (nnspool-personal-active-file) KK+ nnspool-active-file)) GNUSMAIL if test 1043 -ne "`wc -c < 'nnspool-diff'`" then echo shar: error transmitting "'nnspool-diff'" '(should have been 1043 characters)' fi fi # end of overwriting check echo shar: extracting "'pmd'" '(2129 characters)' if test -f 'pmd' then echo shar: will not over-write existing file "'pmd'" else sed 's/^KK//' << \GNUSMAIL > 'pmd' KK#!/bin/csh -f KK# KK# Configuration. KKumask 077 KKset path=(/usr/local/bin /usr/ucb /bin /usr/bin /etc /usr/etc) KKset dir=/n/dinosaur/0/karl/Memos KKset tmp=/usr/tmp/karl-$$ KK# KK# Save the mail momentarily, and set a Lines: count in it. KKcat - > $tmp KKset totlen=`wc -l < $tmp` KKset lines=(`sed '1,/^$/d' < $tmp | wc -l`) KK@ headerlen = $totlen - $lines KKed - $tmp << EOF >& /dev/null KK$headerlen KKi KKLines: $lines KK. KKw KKq KKEOF KK# KK# Deduce headers appropriately. KKset nonomatch KKset from=(`head -1 $tmp`) KKif ($#from < 2) then KK echo Bogus mail: From_ line has $#from items. KK sed -e 's/^/|/' < $tmp | sed -e '/^$/,$d' KK exit 23 KKendif KKset from=(`echo "$from[2]" | sed -e 's/@.*//' -e 's/\(.*\)!\(.*\)/\2/'`) KKif ("$from" =~ *-[Rr][Ee][Qq][Uu][Ee][Ss][Tt]*) then KK # Mailing list stuff. KK switch ("$from") KK case firearms-request: KK set subdir=list/firearms KK breaksw KK case firearms-politics-request: KK set subdir=list/firearms/politics KK breaksw KK default: KK set subdir=list/general KK breaksw KK endsw KKelse if ("$from" =~ *[Mm][Aa][Ii][Ll][Ee][Rr]-[Dd][Aa][Ee][Mm][Oo][Nn]*) then KK # BEWARE: Some (bad) csh's can't cope with the preceding regexp. KK # Mailer-Daemon bounces. KK set subdir=mailer-daemon KKelse KK # Personal mail KK if ((-e $dir/personal/"$from") && (-d $dir/personal/"$from")) then KK set subdir=personal/"$from" KK else KK set subdir=personal/general KK endif KKendif KKunset nonomatch KK# KK# Now save the mail appropriately. KK# KK# Lock. KKset keyf=$dir/$subdir/KEY KKset seqfile=$dir/$subdir/.last KKset success=no KK@ retry = 0 KKwhile (($retry < 10) && ($success == no)) KK rm $keyf KK if ($status == 0) then KK # The key was there when we wanted it. KK set success=yes KK else KK # The key was not there - someone else KK # had already taken it. Wait and retry. KK sleep 10 KK @ retry ++ KK endif KKend KK# KK# If we fall out to here without success, we failed 10 times to KK# get the key. Result: Who cares? We'll go forward anyway, KK# and re-assert the key when we're done. KK# KK# Get next filenumber. KKset seq=(`cat $seqfile`) KK@ seq ++ KKecho $seq > $seqfile KK# KK# Unlock and save. KKtouch $keyf KKsed -e '1s/^From /UNIX-From: /' < $tmp > $dir/"$subdir"/$seq KK# KK# Clean up and exit. KKrm -f $tmp KKexit 0 GNUSMAIL if test 2129 -ne "`wc -c < 'pmd'`" then echo shar: error transmitting "'pmd'" '(should have been 2129 characters)' fi chmod +x 'pmd' fi # end of overwriting check # End of shell archive exit 0