pax_global_header00006660000000000000000000000064113054751330014514gustar00rootroot0000000000000052 comment=e6d8fcccc8c62584c8ef54c607a85e05f217b01f procmail-lib-2009.1202/000077500000000000000000000000001130547513300144055ustar00rootroot00000000000000procmail-lib-2009.1202/COPYING000066400000000000000000000002401130547513300154340ustar00rootroot00000000000000Procmail Module Library ----------------------- GNU GPL v2 or later. Documentation is dual licenced also under GNU FDL. For more information, see doc/license/ procmail-lib-2009.1202/INSTALL000066400000000000000000000046401130547513300154420ustar00rootroot00000000000000File id Copyright (C) 1997-2009 Jari Aalto License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later (GNU GPL); or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). Procmail is a tool to manipulate mail messages and this library includes many plug-in modules to be used from `~/.procmailrc'. How to install Installation requires GNU make. The default location is /usr/local/share/procmail-lib for modules and /usr/local/share/doc/procmail-lib for documentation. Supply `prefix' and/or `exec_prefix' to make(1) call as needed. Note that the DESTDIR *must* be absolute path, because makefiles are run in their own directories. make prefix=/usr install To install for local account, use: make DESTDIR=$HOME prefix=/. install How to sart using modules Put following near start of `~/.procmailrc': # PM = Procmail, SRC = source files. PMSRC = /absolute/path/to/procmail-lib Any input parameters should be set before calling a module. Consult included documentation or read the comments at the beginning od each module file. Here is an example of using Unsolicited Bulk Email, aka spam, module: INCLUDERC = $PMSRC/pm-javar.rc # Initalize variables INCLUDERC = $RC_UBE # The "\/" records match to log file (if log has been activated) :0: * ERROR ?? ^()\/.+ spam.mbox Examples There are some examples of procmail setup files included under the documentation directory `examples/'. Requirements Procmail Mail Delivery Agent (MDA) is needed before files in this library are useful. The Mail Transport Agent (MTA) must have been configured to support Procmail. Activating procmail for individual accounts may need setting up a `~/.forward' file. For more information, refer to manual pages procmail(1) and procmailrc(5) or contact local system administrator how to activate procmail support. Visit Procmail site for wealth of documentation and the Prcocmail Documentation Project at . End procmail-lib-2009.1202/Makefile000066400000000000000000000022061130547513300160450ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright (C) 1997-2009 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . ifneq (,) This makefile requires GNU Make. endif all: @echo "There is nothing to build. See file INSTALL." clean: $(MAKE) -C lib clean $(MAKE) -C doc clean realclean: clean install: $(MAKE) -C lib install $(MAKE) -C lib-stebbens install $(MAKE) -C doc install install-test: # Rule install-test - for Maintainer only rm -rf tmp make DESTDIR=`pwd`/tmp prefix=/. install @echo "find tmp -type f | less" www: # Rule www - for Maintainer only $(MAKE) -C doc www .PHONY: all clean distclean realclean install www # End of file procmail-lib-2009.1202/README000066400000000000000000000021411130547513300152630ustar00rootroot00000000000000Procmail Module Library - Collection of plug-in modules ------------------------------------------------------- Procmail is a mail processing utility for POSIX operating systems. This is collection of plug-in modules include: parse dates, time, email addresses, mail forward, pop3, Spam detection, Cron, MIME file servers, daemon messages and more. This package contains 2 separate libraries. The original 1995-1997 Alan Stebbens' libraries and ones from Jari Aalto in their separate directories. doc/ Documentation doc/examples/ Procmail startup file examples doc/source/license/ Licensing information lib/ The "code". Plug-in modules lib-stebbens/ Alan Stebben's original modules. Historical; Bug reports are ignored for these. Important files INSTALL Install information lib/ChangeLog Project change records Project contacts Homepage http://freshmeat.net/projects/procmail-lib Reporting bugs See freshmeat page Source code repository See freshmeat page End of file procmail-lib-2009.1202/common.mk000066400000000000000000000030151130547513300162250ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright (C) 1997-2009 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . ifneq (,) This makefile requires GNU Make. endif PACKAGE = procmail-lib DESTDIR = prefix ?= /usr/local exec_prefix ?= $(prefix) bindir ?= $(exec_prefix)/bin sharedir ?= $(prefix)/share ifeq ($(prefix),/usr) man_prefix = $(prefix)/share mandir ?= $(man_prefix)/man else man_prefix ?= $(prefix) mandir ?= $(prefix)/man endif BINDIR ?= $(DESTDIR)$(bindir) DOCDIR ?= $(DESTDIR)$(sharedir)/doc/$(PACKAGE) SHAREDIR ?= $(DESTDIR)$(prefix)/share/$(PACKAGE) LIBDIR ?= $(DESTDIR)$(prefix)/lib/$(PACKAGE) SBINDIR ?= $(DESTDIR)$(exec_prefix)/sbin ETCDIR ?= $(DESTDIR)/etc/$(PACKAGE) # 1 = regular, 5 = conf, 6 = games, 8 = daemons MANDIR ?= $(DESTDIR)$(mandir) MANDIR1 ?= $(MANDIR)/man1 MANDIR5 ?= $(MANDIR)/man5 MANDIR6 ?= $(MANDIR)/man6 MANDIR8 ?= $(MANDIR)/man8 INSTALL ?= install INSTALL_BIN ?= $(INSTALL) -m 755 INSTALL_DATA ?= $(INSTALL) -m 644 distclean: clean clean: -rm -f *[~#] .[~#]* *.tmp # End of file procmail-lib-2009.1202/doc/000077500000000000000000000000001130547513300151525ustar00rootroot00000000000000procmail-lib-2009.1202/doc/ChangeLog000066400000000000000000000154021130547513300167260ustar00rootroot000000000000002008-09-19 Jari Aalto Massive chnages to the doc/ hierarchy. Everything was relocated to new places. New cleaner layout. 2006-08-23 Jari Aalto RELEASE 20070930.1156 * doc/article: (3.2 Advice for the normal account): Spamassassin commands updated. --no-rebuild option has been deprecated. Changed to --no-sync. Option --rebuild has been deprecated. Changed to --sync. 2006-02-16 Jari Aalto * doc/article: (4.1 Advice for the normal account): Changed Bmf, Bogofilter, Bsfilter addresses from sourceforge to freshmeat.net. 2005-08-31 Jari Aalto * doc/article: (1.3.6 Further reading - Some known C-R systems): Added Perl spamresponder to the list. 2005-05-18 Wed Jari Aalto * doc/article: (1.3.6 Further reading - Some known C-R systems): Added qconfirm. (1.3.4 Summary - What are the effects of Challenge-Response systems): Added Adam Shand and his wiki page SpamBlacklistsConsideredHarmful (1.1 Bouncing messages do no good): 1.90 Added www.postini.com/sats picture, added DHA attack and link, added Joe St Sauver Ph.D link and statistics. 2005-02-11 Jari Aalto * doc/article: Small typos fixes all over the document. 2004-12-18 Sat Jari Aalto * doc/article: 1.79 Run Emacs M-x flyspell-buffer and corrected some spelling mistakes. (Challenge-Response is not a doorbell): Explained why 'well behaving C-R' is not any better. Added bullets pass list, block list etc. * announce.txt (Procmail): 1.2 Corrected CC addres (list has moved). Added mailman URL link. 2004-10-10 Sun Jari Aalto * doc/article: 1.72 Added URL to IETF memo by Paul Vixie. 2004-10-11 Jari Aalto * README.txt (3.3 Configuring Bayesian programs): Changed required_hits from 9 to 3, and bayes_auto_learn_threshold_spam from 12 to 9 (1.3 Challenge-Response systems make matters worse): Corrected picture text wording. (3.4 A heavyweight spam catch setup using procmail): Added JA_UBE_BSFILTER_PRG. 2004-10-11 Jari Aalto * README.txt (3.3 Configuring Bayesian programs): Added more bayes_ignore_header values from new interface modules. 2004-10-06 Jari Aalto * README.txt (3.2 Advice for the normal account): Added bsfilter training instructions. (1.4 Spam appearing in your yard - a story): New. 2004-10-03 Jari Aalto * README.txt (1.3 Challenge-Response systems make matters worse): Added third level headings: 2004-10-02 Sat Jari Aalto * README.txt (3.1 Advice for Debian Exim 4 mail system administrator): 1.43 Added URL 'Explanations 3: Theory of numeric Status: codes' (1.1 Bouncing messages do no good): 1.43 Added picture mta-viruses.png and explanation why viruses shoudl be dropped, not bounced. Added URL to David A. Wheeler's paper. * README.txt (3.1 Advice for Debian Exim 4 mail system administrator): Added Teergrubing FAQ. (3.2 Advice for the normal account): Added ifile discussion list URL. (1.3 Challenge-Response systems make matters worse): Added new picture cr-system-authentication.png (3.1 Advice for Debian Exim 4 mail system administrator): 1.43 Added URL 'Explanations 3: Theory of numeric Status: codes' 2004-10-01 Jari Aalto * README.txt (top level): Added many new pictures. Removed procmail code whic demonstrated where bayesian programs could be put. The removal makes 'Heavyweight' setup more clear. 2004-09-30 Thu Jari Aalto * (slides.ppt): Added powerpoint file to demontrate flaw in C-R system. => Exported picture cr-system-joe-job.jpg. 2004-09-29 Jari Aalto jari dot aalto A T cante dt net> * README.txt (3.0 A heavyweight UBE blocking system): Removed lisut of programs mentioned in article by Sam Holden. 2004-09-28 Jari Aalto * README.txt (3.1 Advice for Debian Exim 4 mail system administor): Added link to lwn.net's article: Is Sender ID Dead in the Water? - No MARID Working Group Consensus (Groklaw). Added link to O'Reilly's article: What's New in SpamAssassin 3.0. (3.2 Advice for the normal account): Added instructions for IFILE how to detect multiple message categories. Removed bogofilter's note how to use it to classify different messages. Bogofilter is not desined to that task as ifile. Added OCaml based spamoracle program. Added annoyance filter program. (3.5 Using battery of Bayesian shields from procmail): Use ERROR variable instead of X-Spamifile header to check ifile module's result. Added SHELL setting. 2004-09-25 Sat Jari Aalto * doc/article: 1.23 Added Jonathan de Boyne Pollard's opinion that nothing works. (3.1 Advice for Debian Exim 4 mail system administor): 1.23 Added Murray Watson's comment on SPF: cheese ans mouse chase. 2004-09-23 Jari Aalto * README.txt (3.1 Advice for Debian Exim 4 mail system administor): Spamassassin 3.x was release 2004-09-22 with SPF support. Changed tense from future to present - SPF is there now. (1.3 Challenge-Response systems make matters worse): Many improvements and more user comments added. 2004-09-22 Jari Aalto * README.txt (1.3 Challenge-Response tactics make matters worse): New topic. 2004-09-21 Tue Jari Aalto * README.txt (1.1 Steps to install): 1.23 Removed. This is now documented in top level INSTALL file. (example ~/.procmailrc): Removed. Moved to another file. 2004-09-14 Jari Aalto * README.txt (4.4 A heavyweight spam catch setup using procmail): Removed Plan A, Plan B and replaced them with new 'umrella' solution whcih will take care of the details. 2004-09-11 Jari Aalto * doc/article: Small typos corrected. Changes 'Tips' to 'advice'. (Sample ~/.procmailrc): Added more examples, like using the mailing list module and UBE module. (Thoughts about increasing spam annoyance): Completely new topics written. For Debian admin, lightweight and heavyweight spam protections advice. (Rule based systems are not the solution): Moved 'other related projects' to the end of topic. 2004-08-19 Thu Jari Aalto * README.txt (Steps to install): 1.2 More verbose instruction to the installation section. 2002-01-24 Thu Jari Aalto * manual/: (Description): 1.1 Corrected the 'Addressing' faq URL to point to www.faqs.org. procmail-lib-2009.1202/doc/Makefile000066400000000000000000000042421130547513300166140ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # Visit ifneq (,) This makefile requires GNU Make. endif include ../common.mk INSTALL = install INSTALL_BIN = $(INSTALL) -m 755 INSTALL_DATA = $(INSTALL) -m 644 BASEDIR = $(DOCDIR)/lib-aalto EXDIR = $(BASEDIR)/examples INSTALL_EXAMPLE_OBJS = examples/*.procmailrc INSTALL_LOG_DOC = ChangeLog INSTALL_LOG_LIB = ../lib/ChangeLog all: doc install-examples: $(INSTALL_BIN) -d $(EXDIR) $(INSTALL_DATA) $(INSTALL_EXAMPLE_OBJS) $(EXDIR) install-doc: $(INSTALL_BIN) -d $(BASEDIR) $(BASEDIR)/manual $(BASEDIR)/article $(INSTALL_DATA) *.html $(BASEDIR) $(INSTALL_DATA) manual/*.html $(BASEDIR)/manual $(INSTALL_DATA) article/*.html $(BASEDIR)/article $(INSTALL_DATA) $(INSTALL_LOG_DOC) $(BASEDIR)/ChangeLog.doc $(INSTALL_DATA) $(INSTALL_LOG_LIB) $(BASEDIR)/ChangeLog.lib # Rule: install - install documentation install: install-doc install-examples # Rule: www - copy web pages to ../../-www www: html name=$$(basename $$(cd .. && pwd)); \ to=../../$$name-www; \ echo "Copying to $$to"; \ find . -type f -name "*.html" | \ rsync $${test:+"--dry-run"} \ --files-from=- \ --update \ --progress \ --verbose \ -r \ . \ $$to/ manual: manual/index.txt perl -S t2html.pl --Auto-detect --Out --print-url $< article: article/index.txt perl -S t2html.pl --Auto-detect --Out --print-url $< manual-gen: # Rule gen-manual - Generate documentation from ../lib dir to=manual/index.txt ; \ cp manual/index.src $$to ; \ ripdoc.pl ../lib/*.rc >> $$to html: manual article # Rule: doc - Generate or update documentation doc: html .PHONY: all doc html www # End of file procmail-lib-2009.1202/doc/announce/000077500000000000000000000000001130547513300167605ustar00rootroot00000000000000procmail-lib-2009.1202/doc/announce/announce.txt000066400000000000000000000043651130547513300213370ustar00rootroot00000000000000Newsgroups: comp.mail.misc CC: Procmail mailing list Newsgroups: gmane.mail.procmail, comp.mail.misc Subject: Procmail Module Library released --text follows this line-- Project page: http://freshemat.net/projects/procmail-lib Procmail : http://www.procmail.org/ and http://mailman.rwth-aachen.de/mailman/listinfo/procmail New version of Procmail Module Library has been released. During the past years many new Bayesian programs have appeared to detect Unsolicited Bulk Email (aka Spam) and procmail can be used to integrate those tools to the mail handling chain. Overall the changes are focused in Spam and installation. You may be interested in: - examples directory, which contains procmail snippets. - Pure procmail spam modules: pm-jaube.rc, pm-jaube-keywords.rc - Interface modules to external Bayesian programs. See pm-jaube-prg-runall.rc. This includes support for: * annoyance filter * Bayesian Mail Filter (bmf) * Bogofilter * Bsfilter * Ifile * Spamassassin * Spamoracle * Spamprobe - Mailing list detection module: pm-jalist.rc - And many more are included... There is included document "Thoughts about increasing spam annoyance" which outlines lightweight and heavyweight protection methods. https://savannah.nongnu.org/projects/procmail-lib/article 1.0 Thoughts about increasing spam annoyance 1.1 Bouncing messages do no good 1.2 Rule based systems are not the solution 1.3 Challenge-Response systems make matters worse 1.3.1 Challenge-Response is not a doorbell but a gun shooting decoys 1.3.2 Questioning Challenge-Response system implementations 1.3.3 Summary - What are the effects of Challenge-Response systems 1.4 Spam appearing in your yard - a story 2.0 A lightweight UBE block system with pure procmail 2.1 Suitable for accounts which ... 2.2 Where to put "pure procmail" UBE checks? 2.3 Using Procmail Module Library to fight spam 3.0 A heavyweight UBE blocking system 3.1 Advice for Debian Exim 4 mail system administrator 3.2 Advice for the normal account 3.3 Configuring Bayesian programs 3.4 A heavyweight spam catch setup using procmail Jari procmail-lib-2009.1202/doc/article/000077500000000000000000000000001130547513300165755ustar00rootroot00000000000000procmail-lib-2009.1202/doc/article/index.html000066400000000000000000003603721130547513300206050ustar00rootroot00000000000000 Procmail strategies against spam

1.0 Thoughts about increasing spam annoyance

By Jari Aalto (AT cante net).

License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL).

1.1 Bouncing messages do no good

Note: the bounces referred here concern only messages that are sent from accounts that have already accepted messages. Mail transport layer reject messages are not in this sense bounces, but delivery status notifications (DSNs). The mail server is the only place where rejects may be handled intelligently with SPF and other methods. Individual account holders disencouraged to practice bouncing or other message replying tactics.

In today's Internet, where message count has increased sky high, the sender's address no longer reveal the spammer behind it. Using a procmail recipe or other auto-responder program which would bounce the message back does nothing but harm because the bulk spammers use other people's email addresses. The programs are not replying to the real originator of the messages, but to poor individuals whose addresses had been hijacked by collecting them form Usenet newsgroups, web pages, mailing lists etc.

[Picture 1.  pic/address-harvest.png]
Picture 1. In addition to "fake addresses" spammers also collect valid addresses which are then used in forgeries. A reply to Unsolicited Bulk Email message will not reach the real originator, but a innocent individual, whose email address has been abused.

In the "Winning the War on Spam" (2003) Joe St Sauver Ph.D. addressed the amazing figures that spam covers around 70 % of the total messages delivered. The big ISPs like according to Senderbase and Sauver handle vast amount of messages: Yahoo 841, Hotmal 532 and 331 AOL million/day. Those volumes explain a number of things.

[Picture 2.  pic/postini.com-stats.png]
Picture 2. Spam statistics reported by www.postini.com/sats as of 2005-05-18. According to finer statistics page link "More Spam statistics" in picture, the amount of bulk email was 97 % and during six months 102 terabytes of spam were fallen into traps.

New kind of attacks (see Stopping the "New" Spam: Directory-Harvest Attacks) have also been serious threat to attempt to gain access to normal email addresses. With DHA if the spammer has a few addresses at company which shows their email format appears to follow FIRST_NAME LAST_NAME @example.com scheme, then they can try generating messages based on people's names mentioned in the company's web pages. The other harvesting methods were described in comp.mail.misc thread 2004-12-03:

UBE senders generally harvest mailbox names from Usenet by using the "XOVER" NNTP extension (RFC 2980). An article overview comprises the subject, author, date, message-id, references, byte count, and line count of an article. In particular: Because it doesn't comprise the "Reply-To:" field, mailboxes that occur only in "Reply-To:" fields are rarely harvested; and because it does comprise the "Message-ID:" field, UBE can often be seen sent to bizarrely named mailboxes that are actually the message IDs of articles. UBE senders rarely download entire articles and harvest them. Parsing overview information is easy (It's designed to be machine parseable.), whereas scanning article bodies is a lot harder. Mailbox names in message bodies are rarely harvested. Generally the actual cause of mailbox names being harvested from message bodies is when a UBE sender's web crawler follows a hyperlink to a message published by a company providing a web interface to Usenet. (Notice that, as of today, Google Groups no longer handily converts mailbox names into "mailto:" hyperlinks - which are also easy to harvest. However, this is not true of all web interfaces to Usenet.) --Jonathan de Boyne Pollard

The bounces or auto-replies sent today from various sources are amplifying the traffic problem. One particular issue is the handling of message that carry a virus. Many sites have integrated virus scanners to their mail servers (MTA; Mail Transfer Agent) to check all incoming messages, so that their internal computers are not infected. But many do not know that the de facto response to "reject" a message containing Unsolicited Bulk Email or virus is very bad strategy. Some sites may enable a feature which sends "friendly notifications" to warn that the message contained a virus. The idea may have been to help make the sender aware of the problem and have him check his environment. It can be easily seen how these rejects and auto-replies from virus and spam scanners are spreading the problem.

[Picture 3.  pic/mta-viruses.png]
Picture 3. Virus messages are so special, that the normal mail server reject is COMPLETELY improper action to take. In 99.99% of the virus messages, it will not be the RCPT FROM: who is sending the virus. The address is a lie and when message is rejected, it will simply be forwarded to some other person who later finds it from his mailbox. This is also example of a "Joe-Job" (See later).

How would the mail server react, when it notices questionable message which is flagged as spam or which is carrying a virus? It could:

  • accept and drop the message
  • reject, causing previous mail server to raise a DSN
  • accept and send onward
  • accept, strip, and send onward
  • or don't look, so it is unwittingly accepted and send onward.

There are strong arguments that all the last four are wrong, and are likely to cause an innocent person to be affected. The only sensible action is the first one. There is really no place where messages could be sent. A quarantine or dev/null are the only reasonable valid destination. It would be good if every mail server would perform a checks so that end user's wouldn't need to worry. The mail server level checking is scalable and incrementally beneficial. Spam and virii do exist - in large numbers and every ail server that rejects them potentially causes a Delivery Status Notification (DSN) to go to an innocent.

These bad bounce scripts or other auto-responders fill many innocent persons' mailboxes and after a while those people's accounts are effectively made unusable. Imagine a bounce-bombing to persons who are technically illiterate and who have no means to stop receiving "bounces". The bounces are perfect missiles to take off people's control of their mail management. Here is the one comment dated 2004-04-06 from a discussion of comp.mail.misc how it feels like getting bounces:

About 5 times per day I get bounce messages from mail servers rejecting e-mail that I did not send. Obviously somebody (and probably more than one entity) is regularly forging my address as their "From" address.

Better yet, every six months or so I'll get spam from a really clever spammer who makes sure the "To" and "From" addresses match. Since I'm not in the habit of trying to sell anything to myself, I'm quite sure that a spammer has forged the "From" address of that!

I know I'm not the only one either. Plenty of people I know have had the same thing happen to them. And that is precisely the reason why the experts tell you to never, ever bounce spam. The challenge from your system would be at least as much of a problem as the bogus bounce messages --John-Paul Stewart

And in another comp.mail.mic thread 2004-10-04 the experiences were even worse:

Last year (in 12 months), I directly received about 8,000 spam. So far this year, it has reached 28,000 (which I can easily filter) and there are still 3 months to go. I am now receiving bounced spam caused by the bastards now using my email domain in the From: field of their spam. Based on the exponential growth of the spam messages from last year, I can expect a similar exponential growth in the bounced spam and so my email addresses are going to become totally unusable towards the ends of next year cause by the MTAs bouncing the spam sent to them to me.

This I would definitely call an abuse by the ISPs - their MTAs are bouncing to the easily forged From: field as opposed to tracing the email to its correct originating address (via slightly, but not very much, harder to forge fields). The only solution I have to this is to simply bounce the spam back to them under exactly the same conditions it was sent to me: the To: field doesn't contain a valid email address.

The next result of this is a three-fold increase in spam at no further cost to the original spammer: their original spam, the bounce to a non-existent address, followed by a bounce back to the original bouncer - is this REALLY a sensible state of affairs? --Robert Newson

It is better to be a intelligent Net citizen and a) refuse to use any bounce or auto-reply tactics b) contact the developers who might use or consider using code that include mail shooting practises and explain why it is not good a idea; and c) boycott any such solution and point people to better alternatives, like Bayesian filters (see later).

Speaking of auto-responses or bounces in procmail world, this means that whatever project is chosen, it should pass the following test. If there are any lines where HOST is undefined (or set) near setting the EXITCODE, that solution should be alarming, whatever it was. Contact the author who may not be aware of the unnecessary and harmful bounces that the scripts may produce.

      $ cd root/of/project/of/procmail/scripts
      $ find . -type f | xargs egrep -n "HOST|EXITCODE"    

Further reading

Related software

  • "...Address harvesting web crawlers are about as intelligent as the spammers who use and/or develop them, which is to say not very. The majority of these programs can be easily fooled into accepting lots and lots of completely fake and useless e-mail addresses, so long as the bogus addresses in question appear to reside on ordinary nondescript web pages. That is where Wpoison comes in." <http://www.monkeys.com/wpoison/>

1.2 Rule based systems are not the solution

A lot has been said about procmail and its wonderful mail handling capabilities. Most of them are true and it is the Swiss army knife to messages. But it is also true that Procmail's syntax is scaring and all it can do, is to match according to regular expressions. It is a false assumption that mere procmail recipes can filter all incoming Unsolicited Bulk Email – they cannot. Whatever procmail based filters are announced to solve the Unsolicited Bulk Email (UBE) problem, they all sell thin air. These include procmail solutions like:

Be skeptic and and don't believe possibly claimed high accuracy rates. Every person's UBE signature – type of UBE received – is different, so no generic filter program can have that wide of spectrum of rules to cut them all. One person's spam may be other person's normal mail.

There is no drama here. The statement "thin air" was a bit exaggerated but one era of spam fighting – rule based – has finished and another – statistical one – has begun. Procmail can no longer be seriously considered as being the king of UBE filtering. No rule based solution cannot achieve the high enough confidence level to sort out what messages can be considered good and what bad. There are too many bulk mail distributors, message contents change all the time and Internet's bandwidth increases will open highway to many new "Lease an account, shoot & run" undertakings . It's a never ending arms race to keep rule based filter up to mutable UBE. The manual work to keep such filters even remotely in a good shape might be possible only for a few. To spend several hours analyzing mail logs in order to fine tune "slipping" rules is task that is unrealistic. You've probably heard what happened to wonderful UBE detection program Spamassassin? It added a statistical Bayesian analysis option after concluding that even it had to raise hands up; too many false positives by using solely rule based detection. The Freshmeat article later referred in this document demonstrates well the deficiency in Spamassassin when no Bayesian feature is enabled.

After this introduction, it should be clear why hand written rules are not the solution to stop UBE. While the true Unsolicited Bulk Email Filtering race has been lost with procmail only solutions, procmail continues to have a firm place in the mail system. For serious unwanted mail filtering the plan is to integrate other programs to procmail. The glue doesn't necessarily have to be procmail, it might as well be sieve or any other mail server supported language. Injecting messages to Bayesian statistical tools for analysis give the best defense there is now.

There are couple of approaches how the procmail setup can be arranged to integrate external analysis programs. In some cases and in some environments it may be feasible to still use "pure procmail only" system. But seriously, the heavyweight suggestion presented in this document gives the best fruits and a maintenance free system. Examine which one is in within your reach or which one you would like to prefer.

Other related procmail projects:

1.3 Challenge-Response systems make matters worse

1.3.1 Challenge-Response is not a doorbell but a gun shooting decoys

The word on the street has whispered that challenge-response strategy, authorized-senders-only policy or a Email-password system (where password is mailed back to the sender), would completely eliminate spam. Many consider this to be the ultimate strategy to make the sender take actions to verify that he exists. Usually the challenge consists in solving a captcha (cf. Wikipedia). Captchas are tasks that are trivial for humans but highly complex and expensive to solve for computers. The idea is that for each message a challenge is returned. It may be a simple task such as returning an answer to well known fact like "what circulates around the earth?" or filling out a form or returning message which was modified to includes a unique hash-key typically in Subject: line. Presumably, spammers won't bother. Some challenge-response system may even warn that it is going to automatically blacklist the email address if the message is not responded to.

The reason why C-R systems is so deceptive to end users is that they are faced with a simple problem: how to reduce unwanted messages? And a C-R promises to cure exactly that by comparing itself to house and a doorbell. The famous analogy is that "You don't come in without knocking first in real life, so why should you be allowed to do that with email?". The email doorbell is so easily installed (a sent C-R bounce), that implementing it e.g. with procmail takes no time at all. Fast and cheap solution to the end user – just what they asked for.

[Picture 4.  pic/cr-system-authentication.png]
Picture 4. The concept "you must authenticate yourself before mail is accepted" is simple. Each side use white lists where email addresses are stored so that no further challenges are needed in future correspondents. The system is intriguing and the problems are not obvious at first. The basic assumption in the C-R system is that the sender can be identified. The identification id used is a EMAIL address which is stored in while lists. The problem at points (A) and (B) is that the EMAIL address is not reliable authentication id because it can be forged without efforts. Messages coming in the name of "bar@from.com" in the future (after address is in white lists) can come from a abuser who uses this innocent person's email address. It's quite easy and nothing can prevent that. It is a known fact that white listing people by their email address is not effective because the incoming email address cannot prove the sender's identity. The problems at point (B) are discussed further in picture where sending challenge causes a "Joe-Job".

Sounds like a good strategy? To a single end user a C-R system would solve all problems, but deployed "en masse" would cause serious and long reaching consequences.

First of all the analogy about the house and doorbell is wrong. Internet is not built on permanent houses but temporary and changing email addresses. New Internet service providers pop up every day and people can change they accounts and email addresses like they change their shirts. The "house" in Internet is a moving target and we all know what happens if a moving target is tried to shoot at. It won't succeed at first shot and not at second either. In the end the target may not be shot down at all even after many rounds. The bird was just too high or the aim angle was wrong etc. No problem, better luck next time? Right? Wrong. Those ammunitions, C-R challenges, eventually reach a target. If they do not hit the bird, they hit trees, ground and innocent bystanders. The more shots, the more damage they do.

The irony here is that the shooter (C-R system deployer; end user) never sees the damage the C-R system is causing to all over the Internet. The other irony here is that the bird (spammer) was never there at all. He used a decoy which tricked load of ammunitions to get shot - shot somewhere and the decoy wouldn't care less. But how happy are the bystanders who were shot? It can be imagined that after a joe-job resulted from using C-R system, there is a bounty offered on the deployer.

[Picture 5.  pic/cr-system-joe-job.png]
Picture 5. Challenge-Response system and its fundamental flaw. It is not possible to know the sender's address, so any challenges being sent are possibly returned to innocent third parties, whose email addresses have been hijacked. Spammers may collect addresses and pretent to be someone else by forging the identity at SMTP RCPT MAIL FROM time. All C-R system where the abusers inject the false addresses shoot back in the dark and the innocent victims are under attack of so called "Joe-Job".

1.3.2 Modern C-R systems are no better

It is often heard that the C-R system is used only after all other checks have been made, thus reducing the number of sent challenges. A word 'modern C-R system' is often described consisting of:

  1. Pass-List (known contacts are taken off the top)
  2. Block-List (broadly tuned-conventional-spam-filter that dumps all the obvious spam + any address or domain you choose to block)
  3. Challenge-Response (for the tiny percentage that remain)

This is good practice and better than treating every mail hostile by default. However, the basic assumption still stays: C-R system believes that it can use valid address. This is not correct assumption. The addresses cannot be reliable used for white/pass listing, black/block listing or destinations where to send a challenges. Relying on addresses is source of many problems, due to email forgeries. This also raises question what is the use of a challenge-response system if it cannot be used unless most of the email messages has been filtered away? What is left for the challenge-response system to filter out? The flaw in even 'modern' C-R systems is:

If one knows that the message is NOT spam per one's filter, why does it need to be challenged in the first place?

The 'modern' systems with strong pre-filtering and with more published SPF record may reduce chances of misdirected challenge but both reduce gains offered by C-R systems. If the intention is to keep the spammers out of the mailbox, the C-R system does not work towards that goal, but rather keeping people out of communicating each other by locking everyone behind their accounts. C-R can be used to implement some kind of priority treatment in situations when auto-replies are sent anyway (e.g. accepting reports to abuse@*) with challenges "included" in auto-reply (as URL link or VERP sender).

What about Microsoft proposed domain key or other pre-measures? This was discussed in comp.mail.misc thread 'Welcome to Comp Mail Misc' 2005-01-04

Using domain keys one already knows that the sender really was the sender, so can be the challenge would serve no purpose. Either the message is known to be spam and discarded (or other action) or it is not spam (as determined by one's filter) and should be delivered. In the case it's "missed spam", it should still be delivered in order to inform the filter maintainer that the filter needs adjustment. That will not do anything to eliminate "authenticated spam". Nor will that prevent spam from hijacked accounts (mailboxes). All it will do is reject (at best) messages which have the sender faked. Not all spammers do that. --D. Stussy

[ in same thread but earlier 2005-01-24] The problem is that ANY C/R message is spam amplification. ONE is too many. The fact that some spam slips through means ADJUST THE FILTER. It is not a license to spam others via C-R. --D. Stussy

1.3.3 Questioning Challenge-Response system implementations

If we think it a little further we find that there are several deficiencies in C-R:

  • First message from unknown sender must be initially confirmed. To contact 100 people all over the world another 100 challenges are returned. There is no guarantees that once a message has been confirmed no further confirmations will never be needed. What if the confirmation database gets lost or deleted? Disk breakdown?
  • A C-R system cannot tell whether an address is the real sender or a forged address. Sending challenges to forged or unknown address is same as sending message to innocent third party. This is called Joe Job. See article "Clueless virus filters spam innocent third parties" for more information. The forged "From" addresses are not a minority. Spammers don't put their address into either the From or other fields on their e-mail. They never get C-Rs at all. If your email address is hijacked, refer to this article.
  • Spammers can run their own mail servers and have the capability to reject anything sent to them. That's why sending a C-R to a claimed spammer address is useless. C-R messages in reality harass normal people, who do not send spam in the first place. The victims of C-R are the previously mentioned third parties, whose addresses spammers use.
  • If challenge is lost, the original sender may get blacklisted (depends on the receiving end) and he may not be able to cannot contact the other party never again.
  • Joe sends message to A who is running C-R, but forwards the message to company helpdesk at B which also uses C-R. Later B responds to Joe, but Joe has had no prior communication with B. It is unclear if Joe must again go through C-R with B or if B's C-R system is intelligent enough to white list Joe automatically. if A and B are in discrete locations, they may be running different C-R systems.
  • If both parties use C-R, the receiver returns a challenge, but in order to accept it, sender's C-R software responds with challenge ... and the loop is ready. Who is going to verify what? Who is going to return the first challenge in sign of trust?
  • When A uses N email addresses, to send message to B, how many challenges A has to to respond to? A simple math: A (uses 10 different email addresses) sends to B (10 persons who all use C-R), then in worst case A must return 10 * 10 challenges to authorize all his 10 different addresses to be accepted by B. So, for 10 messages, 100 times of work does not sound reasonable.
  • How does A know that B's challenge is genuine? I.e. that by responding to it he is not responding to a spammer who is gathering email addresses?
  • Once the spammer get's through the challenge, he has a open highway to send as much Unsolicited Bulk Email as he can before it is noticed. Any spammer can use robots to auto-reply to C-R's, allowing them to instantly access the addresses.
  • What about mailing list messages? Or other automatic messages? It would require artificial intelligence to check which messages look like "human" and which don't and when to send challenge and when not. No C-R system to date include sufficient AI to send challenges intelligently.
  • What about different mail server's reject messages that are not consistent enough (user's mailbox is full etc.) or wide variety of other bounce messages?
  • Worse even, the automatic replies of C-R spam filters can be easily abused. In a concerted action (it need not even be an attack), spam can be sent "from" a certain address to thousands of C-R enabled email addresses. The victim address will be bombarded by thousands of challenging messages immediately and have at least their mailbox clogged.

Scenarios to consider:

      a)

      [1]  <A> uses a C-R system
      [2]  <B> uses a C-R system
      [3]  <A> sends an email to <B>
      [4]  By sending that email, <A> whitelists <B>
      [5]  <B>'s C-R intercepts <A>'s email
      [6]  <B>'s C-R sends a challenge to <A>
      [7]  <A>'s C-R passes <B>'s challenge onto <A>
      [8]  <A> sends the password response to <B>
      [9]  <B> accepts <A>'s password
      [10] <B> reads <A>'s original message
      [11] <B> responds to <A> from work, with his work email address
      [12] <A>'s C-R intercepts <B>'s email
      [13] <A>'s C-R does not recognize <B>'s work address
      [14] <A>'s C-R sends a challenge to <B> . . .

      b)

      If A writes to B from work, but sets Reply-to: to A's
      home address, which address gets the C-R email? The
      (incorrect) work address or the (correct) home address?
      Which email address is the C-R expecting a reply from?    

The workstations are not the only media that is used to handle mail. A very valid point regarding the used technology was raised in comp.mail.mic thread 2004-10-04

Some people have email-only accounts or may be reading their email on cell-phones that provide only email support. They can't respond to C-R "click here". Some people are behind company firewalls that allow email to pass through but block http access. They can't "click here". Some people may be using company machines that, by company policy, have email software installed and no browser at all. They can't "click here". That doesn't mean that they are "dumb". I even hear about systems where email can be read to you over the telephone with text-to-speech converters. People using such a system can't "click here". Such people may be physically blind but are probably not dumb. – Norman L. DeForest

A C-R system may look like a solution, but it only make things more difficult, more messages are send back and forth and people begin to be seriously tired of confirmations. Challenges may get lost (mailbox full) and mail is sometimes trashed (filtering in the receiving end). A C-R system is a perfect tool to make Internet mail based communication to die completely.

1.3.4 Summary - What are the effects of Challenge-Response systems

The bottom line is that C-R increases enormously mail traffic by tripling the bandwidth (or more), because for the message, there's:

  • The message itself
  • The challenge
  • The response (if ever issued)

It also takes people's time off communicating due to double work. C-R can be considered in essence another kind of Unsolicited Bulk Email which sender never asked for. Not only is the challenge annoying and can be perceived as rude, a lot of people will also not be sure what to do. The impression they get is that the recipient's email system is broken in some way and that they can't send mail. It can also be questioned if it is ethically correct that by design C-R offloads the filtering of spam from the user to previously-uninvolved third parties.

The problems presented here concerning Challenge-Response systems are not in no unique to it. The original SMTP design couldn't see the situation faced now, where address forging is the norm. Any program, any auto-responder, like the ages old Unix vacation program, can be tricked into being a device to be used in denial of service attacks (Joe-Jobs) against third parties. This is similar to anti virus systems which send bogus notifications to forgery victims. It is arguable that until there is plans to revise the SMTP protocol or to add some kind of strong authentication mechanisms between the sender and the mail server, these problems persists for all auto-responder tools – including C-R systems – and therefore these "open spam relays" should not be used.

Here is comment from personal web log titled TMDA Users Can Blow Me that expresses how it feels like getting in touch with a C-R system:

This is freaking stupid.

First of all, I never respond to anti-spam e-mail "challenges" whether they are from TMDA, SpamArrest, or anyone else. Ever. On my personal e-mail account, I have a procmail rule that ensures I almost never see them (unless they're heavily customized and my rule misses, of course).

A reader (of the book) just e-mailed me (at my work address for some reason) to ask a question. I spent the time to answer his question only to be rewarded with a message (via his TMDA install) that he's not going to read my message unless I jump through another fucking hoop. Screw that! You know why?

HE CONTACTED ME FIRST!

If these systems are so brain-dead as to not bother adding my address to the whitelist when the user sends me e-mail, I have serious trouble understanding why anyone is using them. Is it just me? Is this too hard to figure out? Anyway, there's another 5 minutes I'll never get back. It's too bad there's no mail header to warn me that "this message is from a TMDA user", because then I'd be able to procmail 'em right to /dev/null where they belong. Ugh.

This bullshit is not going to "solve" the spam problem, people. If that's your solution, please let me opt out. Forever. --Jeremy Zawodny's blog

And the situation can go really serious after email hijacks:

> As former victim of such a harvested email address being used
> as sender for spam, I can only strongly affirm that the damage
> is very real. I received about 2000-3000 "replies" on the first days
> going from "user unknown" (usually from MS Exchange mailers) to real
> insults directed to me personally (which must have been taken a
> considerable amount of time of the writers too).
> Even weeks after the event, I still received back scatter emails.

.. and I am victim since around 2 years. At least one time per week I get such DOS on my <linux4michelle> and then I get between 500 and 34.000 Messages a day. Currently I get around 14.000 per day and 95% of them on <linux4michelle>. Because I am Debian-Consultant and working seriously, I do not change my E-Mail each week, but SPAM is the price. --Michelle Konzack in Procmail mailing list 2005-07-27 <http://article.gmane.org/gmane.mail.procmail/14662>

In the US some big Internet Service Providers (See Washington Post article 2003-04-07 "EarthLink to Offer Anti-Spam E-Mail System") started to offer C-R system to end users. But his has proven to be only a short term solution. Later 2004 large ISPs announced joint effort (See "Digital signature technology to eliminate spam?") to move to digital signature based message authentication technology as outlined by Yahoo in their DomainKeys. Others have commented the issue and have reservations towards DomainKey solution and believe SPF to implement the same concept much better. Here is one experience from using one of the ISPs services posted in comp.mail.misc thread 2004-10-02:

When my Earthlink email address finally was closed some six months ago, C/R was strictly opt-in, under the control of the user. If that's still the case, anyone who opted into it should be capable of opting out of it. There's no need to ask Earthlink staff to do it. I tried their C/R for a while, but as I got nothing at that address except dictionary-attack spam that slid through the prior layer of spam detection, all the challenges were either vanishing or harassing innocent third parties, so I shut it off. --David W. Tamkin

And what really happens if C-R systems are more widely taken was discussed in Politics & technology mailing list.

No, it's worse than that. The collateral damage from widely used C/R systems, even with implementations that avoid the stupid bugs, will destroy usable e-mail.

Challenge systems have effects a lot like spam. In both cases, if only a few people use them they're annoying because they unfairly offload the perpetrator's costs on other people, but in small quantities it's not a big hassle to deal with. As the amount of each goes up, the hassle factor rapidly escalates and it becomes harder and harder for everyone else to use e-mail at all.

(...)

But the real damage from challenge systems will come when spammers start attacking them. Challenge systems all have user white lists so that each correspondent only gets one challenge, then mail goes through directly. So spammers will start trying to send spam with forged sender addresses that are on the recipients' white lists. That's not so hard, sign up for a mailing list, scrape addresses from the list traffic, then send NxN copies of spam, to each list address from each list address. Similarly with addresses scraped in groups from web pages, Usenet groups, and anywhere else scrapage happens.

You won't be able to trust that mail from your friends is actually from your friends, since an increasing fraction will be spam leaking through your challenge system. What will people do? Given the basic principle of challenge systems, which is that it's someone else's job to solve your spam problem, people will dump their white lists and start challenging every message. At this point, it's possible to automate much of the work, most challenge systems are scriptable, so that for example I have a few lines in my mail sorting filters that catch the per-message challenges from submissions to Dan Bernstein's mailing lists and automatically send confirmations. But of course, if I can send responses from scripts, spammers can and will too, so challenge systems will increasingly include "prove you're human" features like showing you a picture and asking you how many kittens are in it. Now we'll have challenge systems duelling to the death, since everyone will be insisting that everyone else confirm first. There should be ways to mitigate the damage, by using a mechanism other than e-mail for the challenge traffic, but I don't see anyone deploying them or even thinking about what a world where everyone challenges e-mail will be like.

So anyway, you heard it here first, challenge systems will destroy e-mail as we know it. Yeah, this sounds apocalyptic, but the pieces are all falling into place, and spam problems consistently get worse faster than anyone expects. How many people would have predicted even a year ago that by now there'd be more spam than real mail on the net? Yet that's the reality already, and the challenge juggernaut is gearing up fast. – John Levine, primary perpetrator of book "The Internet for Dummies"

As it is shown that any address based authentication, blacklist or white list, does not work, many concur with it from personal experience. Here typical conclusion from Adam Shand. You should read his story by following the link.

Just personal experience/preferences as a long time email admin. Blacklists are evil and I LOATH them, please don't ever use them or encourage anyone else to use them. Unless you are AOL (who recieves something like a terabyte of spam a day) blacklists cause more problems and cost more money (in support and trouble shooting) then spam.

In that vein things like TMDA can be useful personal tools but i don't like them as general policies. In other words, use them to sort things into folders but don't bounce messages based on it. I also consider them rude, if I get a message from someone I tried to email with a message that says "XXX uses TMDA and you have to respond within X hours with X code blah", I just delete the message and don't bother emailing them. Why should the onus of communication be on the sender?

Personally I only use statistical systems and I've been very happy. My combination of razor and mozilla's bayesian filters catches about 99% of my spam. Razor alone cathes about 40-60% of my spam which was enough to make my spam bearable ... mozilla has made spam mostly disappear.

Razor occasionally catches a mailing list message as spam (it's happened maybe 3 or 4 times in the last 8 months) but i can live with that. Mozilla has only ever tag's things as spam that I mistakenly tag as spam, and usually that's cron messages

(...)

Everytime we have an employee complain about mail prolems we have to go through the dance of finding out if we've been blocked somewhere and getting ourselves unlisted. These days, one of the troubleshooting steps you have to go through when you have mail problems is trying to figure out if anyone is blocking you cause they think your a spammer. Way to create centralized points of brokeness for a decetralized service Batman!

From a users point of view I don't like blacklists because false positives are inevitable, that the false positives are indescriminate. For example, with razor I do get occasional false positives but it'll never be a message sent directly to me, because no one has ever seen that message before. You only get false positives on messages sent to lists.

Blacklists are actually more likely to block users emails then list email because popular lists are generally on up and up servers while lots of people have legitimate, but dodgy, mail servers.

(...)

Date: Sat, 17 May 2003 16:29:29 -0700
To: politech@politechbot.com
From: Bob K bk@msgbase.com
Subject: A "Nice Blacklist?" No such thing.

Our ISP has been plagued by SPAM. I don't know of any ISP that hasn't been. But we recently shut off our use of Realtime Blackhole systems in favor of in-house SPAM-control. Instead of an effectiveness of 60% or so, we are now trapping more than 90% of unwanted mails, and in a way that our end users have total control.

We shut off the RBLs because we incurred a huge costs as a result of our support for them. When the RBLs began to support the blocking of entire Autonomous Systems instead of targeting SPAMmers directly, they lost my support. I had a carrier whose AS numbers were put into the RBL. Like a good anti-SPAMmer I rejected the carrier and moved to another. My ISP is fairly large, and including customer support costs the carrier change cost my company around $35,000. (...)

Some of the RBL operators have become so obsessed with their tools that they have started to create more harm to Internet users than the SPAMmers they want to protect those users from. A SPAMmer clots mailboxes. An agenda operated RBL takes the mailbox away. Plus, I have run out of choices for carriers. My area only has a few that support it, and all of them are AS-wide being blocked. So I tend now to view RBLs with disdain and disrespect. (...)

All of the anti-SPAM efforts have created a lost perspective I think. That is, people should control their own mailbox. A system that makes arbitrary decisions about what content should and shouldn't be permitted is a loss of freedom of choice. So, there is no such thing as a nice RBL. They are more harmful than helpful, they are less efficient than internal methods, and they take freedom of choice away from ISPs and more importantly, their customers. As long as legitimate RBLs maintain their support for those RBLS that have gone rogue, or are completely inept, they are more criminal or problematic than SPAM. (...)

– Adam Shand's wiki page SpamBlacklistsConsideredHarmful

The consequences of C-R system are not the what the designers may have originally intended. How the C-R notification is treated by the end users was described in comp.mail.misc thread 2005-05-31 "Re: Anti-C/R Nut grey dmiyu.org"

People who are harassed by C-R systems will DISCARD them or feed them to their own SPAM filters as spam. Thus, in the long run, these abusive challenges will NEVER BE SEEN and will cause legitimate mail to be erroneously discarded. This breaks the basic premise of anti-spam systems: To maximize spam elimination while minimizing the impact on legitimate e-mail. C-R systems MAXIMIZE the impact on legitimate e-mail, by causing it to be discarded as if it were spam since a response to the challenge will never be made. --D. Stussy

C-R will probably kill legitimate mail and in the worst case with no white listed mailboxes and no-one ever responds to a challege => 100% of the legitimate mail will also be auto-killed by the system. The goal of any anti-spam system is to maximize the elimination of spam while simultaneously minimizing collateral damage to legitimate mail (i.e. false positives). An improperly designed C-R system maximizes both. A properly designed C-R system doesn't minimize collateral damage and could devolve into maximizing it depending on response (or lack thereof) by the challenged. A well known spam reporting site Spamcop has takeng the stance that false C-R messages are regarded as UBE:

Heading "Messages which may be reported:" However, these messages have become a big enough problem that we now allow them to be reported as the spam that they technically are (...) Misdirected challenges from challenge/response spam filtering systems

In a nutshell in comp.mail.misc thread 2004-04-06 "Challenges from challenge-response systems qualify as unsolicited" was described how futile a C-R system is and how it falsely cradles oneself into belief of imagined security. And unlike a broken arm, which is only problem of an individual, the C-R makes the problem worse for everybody.

C-R is like taking opiates for a broken arm. It does not cure the problem, it only makes it feel better for a little while, and in the long run it will result in even more serious problems. --Scott Dorsey

Is there anything that would accomplish the same as C-R? Yes there is. A GPG/PGP signed message would prove sender's identity much better than any C-R system which cannot say anything about the validity of the email address. Taking cryptographic tools into mail messaging would be much better road. Another new policy using greylisting has proven to be very effective mail server level counter measure. Greylisting is non-intrusive unlike C-R and implements the same concepts without C-R's flaws.

1.3.5 Further reading - Mail, C-R systems, Spam

1.3.6 Further reading - Some known C-R systems

Challenge-response systems do not return spam to the sender, but rather assists the spammer in victimizing additional recipients. There is no method to reliably return messages to their real senders. Forged sender address cannot be detected from message. Some known challenge-response systems include:

1.4 Spam appearing in your yard - a story

The following nice analogy appeared in comp.mail.mic thread 2003-10-05. It describes well how various techniques work in the spam game:

DOGS POPPING IN YOUR YARD

For example, in this analogy, I would compare spam assassin type filters to a helper that runs around the yard putting little flags on the piles of poop, so that you know where they are. Then you can choose to walk around them (in your fancy shoes, or your boots, or whatever). And sometimes your helper misses a pile of poop, or sometimes he flags your morning newspaper. But, the point is, spam assassin doesn't keep dogs from pooping in your yard.

If, instead of something like spam assassin, you mean something like simple procmail rules that sort spam out of your way, then that's more like a little helper who runs around your yard scooping up things you told it are spam (either things your other helper flagged, or using other criteria), and throwing them away for you. Periodically, you open the poop trash can and be sure your morning newspaper didn't get thrown in there by accident. (thankfully, cleaning out the spam trashcan is more sanitary than fishing your newspaper out of the poop trashcan). Procmail, and other "sorting filters", doesn't keep dogs from pooping in your yard at all. It just tries to clean up the poop it finds.

I agree that filters like DNSBL's (because they ARE a sort of filter ... well, not the DNSBL, but the mechanism by which you are integrating the DNSBL into your MTA) are like having a gated fence. The filter is in deciding which dogs get let through the gate, and which don't. The helper (the DNSBL) that acts as your doorman/gate-sentry may or may not be very accurate about which dogs he lets through. He might be good at only letting in the dog that fetched your morning newspaper, or he might be letting in dogs that just want to poop in your yard. Hopefully he's not blocking the dog that is fetching your morning newspaper, though.

Milters are ... well, milters depend upon what type of underlying filter they use, as to what type of role they play in the metaphor. A spam assassin milter basically lets in all dogs, and then kicks them out as soon as it sees them squatting to poop in the yard. That may or may not be useful, and to a certain extent, the dog did get into your yard (wasting some of your CPU).

A C-R system kicks the dog, so it goes back to its claimed home to bring back some form of proof about itself. Hopefully, the dog doesn't just run to the neighbor and bite him (as C-R systems are prone to causing), nor just choose to run away and get lost (due to being dropped or blocked by the original sender). And, of course, it does nothing to stop a poop-bearing dog that just happens to also have a pedigree certificate (a legit sender address that is willing and able to reply to the challenge, and is also a spammer). --John Rudd


2.0 A lightweight UBE block system with pure procmail

2.1 Suitable for accounts which ...

  • receive only a few messages a day: around max. 50.
  • prefer simple and easy solution
  • do not have much spare disk space (quota limits)
  • have no possibilities to get or install new programs. System administrator doesn't have time or the mail server may be is running at separate server which is not to be modified.

The value of 50 excludes all messages from mailing lists, because they can easily identified by procmail recipes. The remaining messages that slip through are those that need checking. If any of the above conditions are met, the "pure procmail only" solution may work. Picking any projects out there and installing it may well meet the expectations to stop Unsolicited Bulk Email. Some known procmail projects in this category include:

The instructions given here apply only to features found from modules in Procmail module library (pm-lib), which this document is part of but you're encourages to evaluate other to test what is best for your needs.

2.2 Where to put "pure procmail" UBE checks?

Where you put Unsolicited Bulk Email handling lines in your ~/.procmailrc is extremely import for all rule based solutions.

          # ~/.procmailrc

          <define variables>
          <detect mailing lists and save messages>
          <detect work email and save messages>
          <detect other important messages: cron, daemon etc.>
          ... whatever you can reliable check
          <write message to backup.mbox at this point>
          <what's left is supect. PUT RULE BASED SPAM FILTER CALLS HERE>

          # End of file    

Why are the UBE rules put towards the end? Because rule based filters will make mistakes and classify valid messages as Unsolicited Bulk Email. There is nothing that can be done to this fact of life. The more messages they handle the more mistakes they do. The less messages they receive the less mistakes they do. That's why the goal is to detect as many messages as possible at the beginning and file them to appropriate folders. The chance of of losing important mail decreases if the rule based UBE solutions are near the bottom.

Did you notice a small detail above? There is a reference to backup.mbox whose use is strongly encouraged for the first few weeks or months during fine tuning of recipes. Resist temptation to send detected UBE messages to /dev/null for long enough period until the recipes stabilize. Cautious persons never use /dev/null with rule based solutions because some important messages may have been misclassified. After gaining experience, some messages can be sent to /dev/null. Like the real positives where message includes a *.exe attachment, invalid character sets (Chinese, Korean) etc.

2.3 Using Procmail Module Library to fight spam

Ok, enough theory. Here is the section to be added near the bottom of ~/.procmailrc file. Make sure the variable PMSRC points to directory where libraries modules are located as described in the INSTALL file.

      enabled = "yes"     # Set to "no" to disable this whole block

      :0
      * enabled ?? "yes"
      {
          saved   = $VERBOSE  # Do not record this to logs
          VERBOSE = "off"

              JA_UBE_ATTACHMENT_ILLEGAL_KILL = "yes"
              JA_UBE_VALID_ADDR = "(me@example.com|another@example.com)"
              INCLUDERC         = $PMSRC/pm-jaube.rc

              #  If ERROR is empty, it means the previous module
              #  did not see anything special. Try another
              #  spam detection module: search bad keywords

              :0
              * ERROR ?? ^^^^
              {
                  INCLUDERC = $PMSRC/pm-jaube-keywords.rc
              }

          VERBOSE = $saved

          #   If ERROR was set, the message was classified as UBE.
          #   The "\/" records reason to Procmail's log file

          :0 :
          * ERROR ?? ()\/.+
          spam.mbox
      }    


3.0 A heavyweight UBE blocking system

If you have the resources to install programs (or get them installed), you're doing the best service to yourself. After this section is put to action, any account will practically be a UBE free zone. Few statistical programs are needed to analyze incoming messages. They work like binary: either they classify message in category A (usually the "good") or in category B (the "bad"). There are a few exceptions like ifile which can be used for classifying messages into many categories. The catch here is that these programs need time to set up. Their effectiveness is directly dependent on patience spent on training. Without a good training they may be no better than average rule based solutions. An excellent article 2003-08-23 on the subject is at <http://freshmeat.net/articles/view/964/> titled Spam Filters by Sam Holden.

Due to different algorithms used in various programs, there is no single program that would be a universal UBE filter. Therefore the best strategy is to combine several programs in chain. If one classifies a message as "good" or "unsure" it can be sent to another program which may have another opinion. The installation of these programs is not teached here, because it is assumed that you have the needed expertise and knowledge already if you plan to jump into "heavyweight" UBE protection.

3.1 Advice for Debian Exim 4 mail system administrator

Before introducing end user means to prevent Unsolicited bulk email with procmail, a few words to a system administrator who is in charge of the local Mail Transport Agent aka the mail server. The advice given here is for Debian Exim 4 only, so google (that's a verb) few pages in the Net to find integration instructions to other mail servers. There is no other place in the system that can as effectively protect against Unsolicited Bulk Email as the mail transport layer; the beating MTA.

[Picture 6.  pic/mta-ube.png]
Picture 6. Mail Transport Agent (Exim, Sendmail, Postfix, Qmail etc.) include ways to check the message at SMTP RCPT time. E.g Exim includes ACL lists (1-3) which can check for incorrect SMTP sequences like trying to send DATA before HELO/missing HELO; forged HELO/reverse-dns combinations; to check sender against locally blocked domains; to check invalid characters in sender's email address etc. There are several possibilities. After these "fast" checks (4) external networks can be consulted. This could include checking IP against known block lists. If IP x.x.x.x is using a dynamic address space, the message is rejected immediately. Other checks may include comparing the message content against checksums (e.g. DCC service). If a match was found it would indicate that same message is being circulated. In addition to these the mail server may (5) call external processes to evaluate the message further with virus scanners and other analysis programs. The net result from any of these checks is to (6) make decision whether message is blocked or accepted. The SMTP connection is still open while all these checks are being run. Instead of reject code 5xx some mail server administrators may have even arranged to use 'teergrube' technique to hold the mail connection open for a long enough time in order to arrange a "tar pit" for the abuser.

  • install Exim 4, it's superior to Exim 3, because v4 can use ACL and other hooks before message is ever accepted. In Debian there are several Exim 4 packages, so make sure you use apt-get install exim4-daemon-heavy. The light version does not contain extended features. During the installation select split configuration files – in the long run it will pay off. Also read update-exim4.conf(8) manual page after installation. After changing configuration, restart exim with invoke-rc.d exim4 restart (or use "reload").
  • The easy part: install Debian package sa-exim (Spamassassin integrated to Exim 4's RCPT) and enable it from /etc/exim4/sa-exim.conf by setting SAEximRunCond:1. With few tweaks with the threshold values it can alone make 70 % of the UBE disappear from the system. The spam messages are blocked and those that are accepted, contain headers, which can be easily checked by user:

      X-Spam-Checker-Version: SpamAssassin 2.64 (2004-01-11) on example.com
      X-Spam-Status: Yes, hits=10.0 required=9.0 tests=AWL,BAYES_99,
          BLANK_LINES_70_80,CLICK_BELOW,MSGID_SPAM_CAPS,REMOVE_PAGE
          autolearn=no version=2.64    

  • Install Debian package greylistd. It has to be configured manually for Exim4 (as of 2004-08-21). Read and follow instructions in directory /usr/share/doc/greylistd. After greylistd is running and integrated to Exim, all messages are temporarily bounced back. This works because well behaving a mail servers will return them back. In the second time they will be accepted. The message have turned from grey to white, so to speak. Rapid spammers usually will not sit there waiting to resend the same messages, so the system is saved from many invalid messages.
  • The above solutions most likely gives 80-90 % shield against UBE. If you are hosting a large user base or receive even higher volume of corporate mail, that may not be enough. Have a look at method called SPF which is based on published DNS records. Microsoft's has proposed competing Sender Id proposal. Sender Policy Framework is directed at domain owners to encourage them to publish lists of servers that are permitted to originate email for the domain. SPF support is easily added to Exim. The instructions can be round from section titled "A.7. Adding SPF Checks". If separate Exim 4 SPF setup looks difficult, you can use spamassassin's built-in SPF support. See O'Reilly's article 2004-09-09 What's New in SpamAssassin 3.0 by Alan Schwartz.

[Picture 7.  pic/spf-system.png]
Picture 7. Sender Policy Framework utilizes existing Domain Name Service TXT record feature. The TXT record publishes Mail Exhangers (MXs) or routes through which domain's mail must be sent. Any attemp to circumvent this route will get caught. Here the intruder tries (1) to send message to to.com by pretending to send message in behalf of from.com. The mail server that receives the incoming SMTP connection stalls the transaction while (2) performing a SPF query to read remote site's DNS record to verify if sender is using valid MX routing. (3) Results were negative. This sender pretended to be someone else as indicated by SPF query result and the (4) SMTP connection terminates at source with a reject code. Message was returned to the sender.

Speaking of SPF it is worth to mention that it is not a method designed to prevent spam, but make the mail transportation route more transparent so that it cannot be that easily abused. SPF will stop messages which uses certain forms of address forgery. This is good for the targeted systems, and also good for the domains whose names are being forged into spam. SPF will not, by itself, stop spam which uses the spammer's own domain name. It's part of the methods that help force spammers to operate in even more tighter space in the Internet as discussed in comp.mail.misc thread 2004-09-24. Catching spammers is like cat and mouse game:

The mouse now has to run a little further and harder to get to the mouse hole in the wall. There's a little more cost to acquiring that cheese. After you do that enough, the mouse says, it's not worth the effort unless it's a big chunk of cheese. What it boils down to is similar to the premise security system phenomenon. If a burglar sees a security system sign in front of a house, unless they're after something really special to them, they'll go to the next neighbor and the first guy on the street that doesn't have a sign is the one that gets burgled. --Murray Watson

Further reading for system administrators:

Other opinions:

3.2 Advice for the normal account

Note: Save classified message directories or mailboxes until you reach about 1000 messages in every category. After that it is safe to turn on auto learn options in presented programs. Warning: in training, do not use messages that are over 6 months old because programs may think that old time stamps are indication of spam.

You know how to compile programs or you run a distribution for which you can get presented packages easily. You have the disk space and you have the time (reserve a week) to hand sort your mailbox to individual messages. If you do not have the patience, it would be better if you never tried the Bayesian programs, because their accuracy depends on the quality of a comprehensive message base. Patience pays and the results are well worth it. Below are few programs that are supported by Procmail Module Library. You do not need all these programs, but the best results can be achieved only if you add more of them to the the message recognition chain.

Other program that might be of interest:

Examine mailboxes and manually sort your messages to at least three categories: good, bad, other. The "other" category includes auto responder messages e.g. from mail servers who return undeliverable email and report other transport errors. It can also include cron job and other automatically generated messages like virus indication bounces that badly informed sites send. The minimum count of messages in each folder is somewhere 200. The more the better and with 1000 messages the reliability is pretty good. It is also known that inserting messages more than twice or three times can actually decrease precision.

The rule of thumb is that the ratio between good/bad should be kept somewhere 30:70 meaning that if the total count of messages is 1000, there must be at minimum of 300 (30%) good messages and 700 (70%) bad messages. If more messages are added to the bad category – say in ratio shifts to 10:90 – the used Bayesian filter will skew and will eventually start classifying messages in wrong category. It is said that the Bayesian works best if it is kept balanced 50:50, but there are indications that better results can be achieved with ratio 40:60 (good/bad). Can't point you to any specific pages that would back up that claim though. Some programs may work better 50:50 and some with 30:70, so 40:70 seems to be a safe bet.

Note: the following instructions are for "one message per file" format (a la MH). If you have stored messages in standard Berkeley styled mailbox (.mbox) format, please examine the manual pages for correct options.

To train bogofilter: (C language)

      $ rm -f ~/.bogofilter/*.db
      $ bogofilter -B -n good.msg ...
      $ bogofilter -B -s spam.msg ...    

To train Bayesian Mail filter: (C language)

      $ rm -f ~/.bmf/*db*
      $ ls good/*.msg | xargs -n 1 bmf -n    # feed individual messages
      $ ls spam/*.msg | xargs -n 1 bmf -s    # feed individual messages    

To train spamprobe: (C++ language)

      $ rm -f ~/.spamprobe/*
      $ spamprobe -8 good good.msg ...
      $ spamprobe -8 spam spam.msg ...    

To train annoyance filter: (C++ language)

      $ mkdir ~/.annoyance
      $ rm -f ~/.annoyance/*.bin
      $ DB=$HOME/.annoyance/dict.bin; DB2=$HOME/.annoyance/fdict.bin
      $ annoyance-filter --mail single.msg --prune --write $DB # INIT
      $ annoyance-filter --phrasemax 2 \
        --read  $DB  \
        --mail dir/to/good/messages \
        --junk dir/to/bad/messages \
        --prune --write $DB
      $ annoyance-filter -v --read $DB --prune --fwrite $DB2    

To train spamoracle: (OCaml language)

      $ rm -f ~/.spamoracle.db
      $ spamoracle add -v -good good.msg ...
      $ spamoracle add -v -spam spam.msg ...    

To train bsfilter: (Ruby language)

      $ rm -f ~/.bsfilter/*.{dir,pag,lock}
      $ bsfilter --add-clean good.msg ...
      $ bsfilter --add-spam  spam.msg ...    

To train spamassassin: (Perl language)

      $ rm -f ~/.spamassassin/bayes*
      $ sa-learn --local --no-sync --ham  good.msg ...
      $ sa-learn --local --no-sync --spam spam.msg ...
      $ sa-learn --sync    

To train ifile: it is a little different. You can train it to use detect any category. The third directory other where you were asked to save the daemon messages previously is used for this purpose. Here it is trained with the other mailbox in addition to standard spam and good messages. Other viable training categories could include virus, bug (reports and answers) and work. Just sort messages in finer categories and repeat the procedure.

      $ rm ~/.idata
      $ echo herbalife | ifile --insert=spam    # initialize database
      $ ifile --reset-data                      # OR use this
      $ ifile --strip-header --insert=good   good.msg ...
      $ ifile --strip-header --insert=spam   spam.msg ...
      $ ifile --strip-header --insert=daemon daemon.msg ...    

The strategy to improve these programs after first 200+200 (good/bad) messages is to put them in action and examine what messages slip through. Collect all unfiltered messages and add them to existing ~/tmp/mail/train/{good,bad,other}/ directories or mailboxes. After few weeks some the logs may show 10-100 new unsure or misclassified message. Add these to to the pristine training directories. When it's time to refresh the databases with the newly added messages, it is important to start from fresh. Delete all programs' databases, as shown by the rm commands above, and repeat the training procedures.

Many of the Bayesian programs have options or commands to put them in auto learn mode while called from ~/.procmailrc, but it should not be used at start. Only when the programs have been trained with a sufficient message base of (best 1000+1000 good/bad), the auto learn option could be considered. The motivation is that using auto learn is dangerous. If auto learn is tuned on when initial message base small, the programs will eventually classify messages into wrong categories and in time "learn" option will cause the statistics to skew bit by bit. The reliability of the filter will suffer and confidence to detect "real" Unsolicited Bulk Email will decrease. So be patient and collect enough messages and hand train each program.

3.3 Configuring Bayesian programs

Most of the programs do not need any special configuration, but some do. With Bayesian programs, if strict bounds are used to classify messages into good/bad categories, message back ups can mostly be forgotten. A well trained filters usually don't make mistakes and messages can be sent to /dev/null. A UBE probability value for a good message is typically 0.1 and 0.9 for bad messages. For Spamassassin the values are different; a good initial setting to discriminate good/bad bar is between 5-10 (safe) and 3-5 (probably safe).

      # ~/.spamassassin/user_prefs

      required_hits                    3.0       # Default was 5.00
      bayes_auto_learn                 1
      bayes_auto_learn_threshold_spam  9.0       # Default was 12.0
      report_safe                      0
      ok_languages                     en

      #  headers may provide inappropriate cues to the
      #  Bayesian classifiers

      bayes_ignore_header X-Bogosity
      bayes_ignore_header X-Spam-Status
      bayes_ignore_header X-Spam-Flag
      bayes_ignore_header X-Spam-Annoyance-Status
      bayes_ignore_header X-Spam-Annoyance-Classification
      bayes_ignore_header X-Spam-Annoyance-Probability
      bayes_ignore_header X-Spam-Bogofilter-Status
      bayes_ignore_header X-Spam-Bmf-Flag
      bayes_ignore_header X-Spam-Bmf-Status
      bayes_ignore_header X-Spam-Bsfilter-Flag
      bayes_ignore_header X-Spam-Bsfilter-Status
      bayes_ignore_header X-Spam-Bsfilter-Version
      bayes_ignore_header X-Spam-Ifile-Status
      bayes_ignore_header X-Spam-Spamoracle-Status
      bayes_ignore_header X-Spam-Spamoracle-Score
      bayes_ignore_header X-Spam-Spamoracle-Details
      bayes_ignore_header X-Spam-Spamoracle-Attachments
      bayes_ignore_header X-Spam-Spamprobe-Status
      bayes_ignore_header X-Spam-Jaube
      bayes_ignore_header X-Spam-JaubeKwd

      # End of file    

For the ~/.bogofilter.cf you would need these values uncommented:

      ham_cutoff  = 0.2       # or 0.1 if you have well trained database
      spam_cutoff = 0.9    

3.4 A heavyweight spam catch setup using procmail

[Picture 8.  pic/procmail-bayesian.png]
Picture 8. Procmail can process and examine mail only with regular expression rules. E.g. it is possible to write a static rule that matches "viagra" and file message to spam mailbox. But the possibilities are too many for any static rule based content checking and thus statistical analysis yields better results for mutable messages. Each statictical - usually "Bayesian" - program use slightly different algorithms to detect Unsolicited Bulk email. Therefore consulting many statistical programs makes a better shield than using a single program.

Several interface modules to various Bayesian programs have been included in the Procmail Module Library. To make using those modules easier, there is one umbrella module pma-jaube-prg-runall.rc which will take care of the details. What's left to do, is to define what programs are available in the system and which have been trained. The umbrella module tries every defined program one by one until some of them thinks the message is Spam. Bogofilter is a special case, because it returns value "unsure" if message is somewhere between spam and ham.

      SHELL       = /bin/sh
      PMSRC       = $HOME/procmail/pm-lib/lib
      INCLUDERC   = $PMSRC/pm-javar.rc    # Define variables

      #   If you do not have one of these programs installed,
      #   simply *comment* *out* the line and it will
      #   automatically disable any recipes using it.
      #
      #   For spamassassin daemon version, use "spamc"

      JA_UBE_ANNOYANCE_PRG    = "/usr/bin/annoyance-filter"
      JA_UBE_BMF_PRG          = "/usr/bin/bmf" # Bayesian Mail Filter
      JA_UBE_BSFILTER_PRG     = "/usr/bin/bsfilter"
      JA_UBE_BOGOFILTER_PRG   = "/usr/bin/bogofilter"
      JA_UBE_IFILE_PRG        = "/usr/bin/ifile"
      JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/spamassassin"
      JA_UBE_SPAMORACLE_PRG   = "/usr/bin/spamoracle"
      JA_UBE_SPAMPROBE_PRG    = "/usr/bin/spamprobe"

      # ... filter mailing lists, etc. HERE, before spam detection ...

      #  This module is "umbrella" for all Bayesian programs.
      #  Variable ERROR is set if any of the programs classified
      #  the message as spam.

      INCLUDERC = $PMSRC/pm-jaube-prg-runall.rc

      :0 :
      * ERROR ?? ^()\/.+
      spam.mbox

      #   ifile is special. It can be trained to detect several kinds
      #   of messages.

      INCLUDERC = $PMSRC/pm-jaube-prg-ifile.rc

      :0 :
      * ERROR ?? \/[a-z]+
      $MATCH.mbox    

This setup may be best suitable for a accounts that receive high volume of mail Unsolicited Bulk Email. Keep in mind that any Perl, Python, Ruby and other high-level language solution does not suit well for heavy mail handling. These interpreters' initial startup time is costly for both CPU and memory. Firing up such programs in rapid succession for many small messages causes strain to system resources. If CPU consumption must be considered for the overall server performance, disabling all calls to Perl and Python based spam solutions could improve server's performance. Concentrating on solely on natively compiled programs helps to squeeze speed out procmail recipes. The less external calls are there, the faster and more system friendly the procmail setup is.


Html date: 2008-09-20 02:15
procmail-lib-2009.1202/doc/article/index.txt000066400000000000000000002610451130547513300204550ustar00rootroot00000000000000 #T2HTML-TITLE Procmail strategies against spam #T2HTML-METAKEYWORDS Procmail, pm-lib, spam, UBE, Exim 4, bogofilter, Bayesian, Spamassassin #T2HTML-OPTION --css-code-bg #T2HTML-OPTION --css-code-note #T2HTML-OPTION Note: #T2HTML-OPTION --simple 1.0 Thoughts about increasing spam annoyance By Jari Aalto (AT cante net). License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). 1.1 Bouncing messages do no good Note: the bounces referred here concern only messages that are sent from _accounts_ that *have* *already* *accepted* messages. Mail transport layer reject messages are not in this sense bounces, but delivery status notifications (#URL). The mail server is the only place where rejects may be handled intelligently with SPF and other methods. Individual account holders disencouraged to practice bouncing or other message replying tactics. In today's #URL, where message count has increased sky high, the sender's address no longer reveal the spammer behind it. Using a procmail recipe or other auto-responder program which would bounce the message back does nothing but harm because the bulk spammers use _other_ _people's_ email addresses. The programs are not replying to the real originator of the messages, but to *poor* *individuals* whose addresses had been hijacked by collecting them form Usenet newsgroups, web pages, mailing lists etc. #PIC pic/address-harvest.png # In addition to "fake addresses" spammers also collect valid addresses which are then used in forgeries. A reply to Unsolicited Bulk Email message will not reach the real originator, but a innocent individual, whose email address has been abused. ### In the #URL<"Winning the War on Spam" (2003)> Joe St Sauver Ph.D. addressed the amazing figures that spam covers around #URL<70 %> of the total messages delivered. The big ISPs like according to #URL and Sauver handle vast amount of messages: Yahoo 841, Hotmal 532 and 331 AOL million/day. Those volumes explain a number of things. #PIC pic/postini.com-stats.png # Spam statistics reported by www.postini.com/sats as of 2005-05-18. According to finer statistics page link "More Spam statistics" in picture, the amount of bulk email was 97 % and during six months 102 terabytes of spam were fallen into traps. ### New kind of attacks (see #URL) have also been serious threat to attempt to gain access to normal email addresses. With DHA if the spammer has a few addresses at company which shows their email format appears to follow FIRST_NAME LAST_NAME @example.com scheme, then they can try generating messages based on people's names mentioned in the company's web pages. The other harvesting methods were described in comp.mail.misc #URL: UBE senders generally harvest mailbox names from Usenet by using the "XOVER" NNTP extension (RFC 2980). An article overview comprises the subject, author, date, message-id, references, byte count, and line count of an article. In particular: Because it *doesn't* comprise the "Reply-To:" field, mailboxes that occur only in "Reply-To:" fields are rarely harvested; and because it *does* comprise the "Message-ID:" field, UBE can often be seen sent to bizarrely named mailboxes that are actually the message IDs of articles. UBE senders rarely download entire articles and harvest them. Parsing overview information is easy (It's designed to be machine parseable.), whereas scanning article bodies is a lot harder. Mailbox names in message bodies are rarely harvested. Generally the actual cause of mailbox names being harvested from message bodies is when a UBE sender's web crawler follows a hyperlink to a message published by a company providing a web interface to Usenet. (Notice that, as of today, Google Groups no longer handily converts mailbox names into "mailto:" hyperlinks - which are also easy to harvest. However, this is not true of all web interfaces to Usenet.) --Jonathan de Boyne Pollard The bounces or auto-replies sent today from various sources are amplifying the traffic problem. One particular issue is the handling of message that carry a virus. Many sites have integrated virus scanners to their mail servers (MTA; Mail Transfer Agent) to check all incoming messages, so that their internal computers are not infected. But many do not know that the de facto response to "reject" a message containing Unsolicited Bulk Email or virus is very bad strategy. Some sites may enable a feature which sends "friendly notifications" to warn that the message contained a virus. The idea may have been to help make the sender aware of the problem and have him check his environment. It can be easily seen how these rejects and auto-replies from virus and spam scanners are spreading the problem. #PIC pic/mta-viruses.png # Virus messages are so special, that the normal mail server reject is COMPLETELY improper action to take. In 99.99% of the virus messages, it will not be the RCPT FROM: who is sending the virus. The address is a lie and when message is rejected, it will simply be forwarded to some other person who later finds it from his mailbox. This is also example of a "Joe-Job" (See later). ### How would the mail server react, when it notices questionable message which is flagged as spam or which is carrying a virus? It could: o _accept_ _and_ _drop_ _the_ _message_ o reject, causing previous mail server to raise a DSN o accept and send onward o accept, strip, and send onward o or don't look, so it is unwittingly accepted and send onward. There are strong arguments that *all* the last four are wrong, and are likely to _cause_ _an_ _innocent_ _person_ _to_ _be_ _affected._ The only sensible action is the first one. There is really no place where messages could be sent. A quarantine or `dev/null' are the only reasonable valid destination. It would be good if every mail server would perform a checks so that end user's wouldn't need to worry. The mail server level checking is scalable and incrementally beneficial. Spam and virii do exist - in large numbers and every ail server that rejects them potentially causes a Delivery Status Notification (DSN) to go to an innocent. These bad bounce scripts or other auto-responders fill many innocent persons' mailboxes and after a while those people's accounts are effectively made unusable. Imagine a bounce-bombing to persons who are technically illiterate and who have no means to stop receiving "bounces". The bounces are perfect missiles to take off people's control of their mail management. Here is the one comment dated 2004-04-06 from a discussion of #URL how it feels like getting bounces: About 5 times per day I get bounce messages from mail servers rejecting e-mail that I did *not* send. Obviously somebody (and probably more than one entity) is regularly forging my address as their "From" address. Better yet, every six months or so I'll get spam from a really clever spammer who makes sure the "To" and "From" addresses match. Since I'm not in the habit of trying to sell anything to myself, I'm quite sure that a spammer has forged the "From" address of that! I know I'm not the only one either. Plenty of people I know have had the same thing happen to them. And that is precisely the reason why the experts tell you to never, ever bounce spam. The challenge from your system would be at least as much of a problem as the bogus bounce messages --John-Paul Stewart And in another comp.mail.mic #URL the experiences were even worse: Last year (in 12 months), I directly received about 8,000 spam. So far this year, it has reached 28,000 (which I can easily filter) and there are still 3 months to go. I am now receiving bounced spam caused by the bastards now using my email domain in the From: field of their spam. Based on the exponential growth of the spam messages from last year, I can expect a similar exponential growth in the bounced spam and so my email addresses are going to become totally unusable towards the ends of next year cause by the MTAs bouncing the spam sent to them to me. This I would definitely call an abuse by the ISPs - their MTAs are bouncing to the easily forged From: field as opposed to tracing the email to its correct originating address (via slightly, but not very much, harder to forge fields). The only solution I have to this is to simply bounce the spam back to them under exactly the same conditions it was sent to me: the To: field doesn't contain a valid email address. The next result of this is a three-fold increase in spam at no further cost to the original spammer: their original spam, the bounce to a non-existent address, followed by a bounce back to the original bouncer - is this REALLY a sensible state of affairs? --Robert Newson It is better to be a intelligent Net citizen and _a)_ refuse to use any bounce or auto-reply tactics _b)_ contact the developers who might use or consider using code that include mail shooting practises and explain why it is not good a idea; and _c)_ boycott any such solution and point people to better alternatives, like Bayesian filters (see later). Speaking of auto-responses or bounces in procmail world, this means that whatever project is chosen, it should pass the following test. If there are any lines where HOST is undefined (or set) near setting the EXITCODE, that solution should be alarming, whatever it was. Contact the author who may not be aware of the unnecessary and harmful bounces that the scripts may produce. $ cd root/of/project/of/procmail/scripts $ find . -type f | xargs egrep -n "HOST|EXITCODE" Further reading o *Rejecting* *or* *Bouncing* *Back* *a* *Message* by Nancy McCough. From there you can find more articles and strong arguments why bouncing strategies should be avoided. http://ii.best.vwh.net/internet/robots/procmail/qs/#reject o *Bounce* *Messages.* "... The concept of sending fake bounces can be very seductive to those who don't understand the consequences." http://spamlinks.net/filter-bounce.htm o *A* *Plan* *for* *Spam* by paul Graham who was behind the the idea of statistical Bayesian filters. http://www.paulgraham.com/spam.html Related software o "...Address harvesting web crawlers are about as intelligent as the spammers who use and/or develop them, which is to say not very. The majority of these programs can be easily fooled into accepting lots and lots of completely fake and useless e-mail addresses, so long as the bogus addresses in question appear to reside on ordinary nondescript web pages. That is where Wpoison comes in." 1.2 Rule based systems are not the solution A lot has been said about procmail and its wonderful mail handling capabilities. Most of them are true and it is the Swiss army knife to messages. But it is also true that Procmail's syntax is scaring and all it can do, is to match according to *regular* *expressions*. It is a false assumption that mere procmail recipes can filter all incoming Unsolicited Bulk Email -- they cannot. Whatever procmail based filters are announced to solve the Unsolicited Bulk Email (UBE) problem, they all sell thin air. These include procmail solutions like: o SPASTIC http://www.sf.net/projects/spastic o Spambouncer http://www.spambouncer.org o JunkFilter http://www.sf.net/projects/junkfilter o Procmail Module Library's UBE handling modules (pm-jaube.rc, pm-jaube-keyword.rc) Be skeptic and and don't believe possibly claimed high accuracy rates. Every person's UBE signature -- type of UBE received -- is different, so no generic filter program can have that wide of spectrum of rules to cut them all. One person's spam may be other person's normal mail. There is no drama here. The statement "thin air" was a bit exaggerated but one era of spam fighting -- rule based -- has finished and another -- statistical one -- has begun. Procmail can no longer be seriously considered as being the king of UBE filtering. No rule based solution cannot achieve the high enough confidence level to sort out what messages can be considered good and what bad. There are too many bulk mail distributors, message contents change all the time and Internet's bandwidth increases will open highway to many new "Lease an account, shoot & run" undertakings . It's a never ending arms race to keep rule based filter up to mutable UBE. The manual work to keep such filters even remotely in a good shape might be possible only for a few. To spend several hours analyzing mail logs in order to fine tune "slipping" rules is task that is unrealistic. You've probably heard what happened to wonderful UBE detection program Spamassassin? It added a statistical Bayesian analysis option after concluding that even it had to raise hands up; too many false positives by using solely rule based detection. The Freshmeat article later referred in this document demonstrates well the deficiency in Spamassassin when no Bayesian feature is enabled. After this introduction, it should be clear why hand written rules are not the solution to stop UBE. While the true Unsolicited Bulk Email Filtering race has been lost with procmail only solutions, procmail continues to have a firm place in the mail system. For serious unwanted mail filtering the plan is _to_ _integrate_ *other* *programs* to procmail. The glue doesn't necessarily have to be procmail, it might as well be `sieve' or any other mail server supported language. Injecting messages to Bayesian statistical tools for analysis give the best defense there is now. There are couple of approaches how the procmail setup can be arranged to integrate external analysis programs. In some cases and in some environments it *may* be feasible to still use "pure procmail only" system. But seriously, the heavyweight suggestion presented in this document gives the best fruits and a maintenance free system. Examine which one is in within your reach or which one you would like to prefer. Other related procmail projects: o Virus snagger http://vsnag.spamless.us/ o E-mail sanitizer. Tool for preventing attacks on your computer's security via email messages http://www.impsec.org/email-tools/procmail-security.html 1.3 Challenge-Response systems make matters worse 1.3.1 Challenge-Response is not a doorbell but a gun shooting decoys The word on the street has whispered that challenge-response strategy, authorized-senders-only policy or a Email-password system (where password is mailed back to the sender), would completely eliminate spam. Many consider this to be the ultimate strategy to make the sender take actions to verify that he exists. Usually the challenge consists in solving a captcha (cf. #URL). #URL are tasks that are trivial for humans but highly complex and expensive to solve for computers. The idea is that for each message a challenge is returned. It may be a simple task such as returning an answer to well known fact like "what circulates around the earth?" or filling out a form or returning message which was modified to includes a unique hash-key typically in `Subject:' line. Presumably, spammers won't bother. Some challenge-response system may even warn that it is going to automatically blacklist the email address if the message is not responded to. The reason why C-R systems is so deceptive to end users is that they are faced with a simple problem: how to reduce unwanted messages? And a C-R promises to cure exactly that by comparing itself to house and a doorbell. The famous analogy is that "You don't come in without knocking first in real life, so why should you be allowed to do that with email?". The email doorbell is so easily installed (a sent C-R bounce), that implementing it e.g. with procmail takes no time at all. Fast and cheap solution to the end user -- just what they asked for. #PIC pic/cr-system-authentication.png # The concept "you must authenticate yourself before mail is accepted" is simple. Each side use white lists where email addresses are stored so that no further challenges are needed in future correspondents. The system is intriguing and the problems are not obvious at first. The basic assumption in the C-R system is that the sender can be identified. The identification id used is a EMAIL address which is stored in while lists. The problem at points (A) and (B) is that the EMAIL address is not reliable authentication id because it can be forged without efforts. Messages coming in the name of "bar@from.com" in the future (after address is in white lists) can come from a abuser who uses this innocent person's email address. It's quite easy and nothing can prevent that. It is a known fact that white listing people by their email address is not effective because the incoming email address cannot prove the sender's identity. The problems at point (B) are discussed further in picture where sending challenge causes a "Joe-Job". ### Sounds like a good strategy? To a single end user a C-R system would solve all problems, but deployed "en masse" would cause serious and long reaching consequences. First of all the analogy about the house and doorbell is wrong. Internet is not built on permanent houses but temporary and changing email addresses. New Internet service providers pop up every day and people can change they accounts and email addresses like they change their shirts. The "house" in Internet is a moving target and we all know what happens if a moving target is tried to shoot at. It won't succeed at first shot and not at second either. In the end the target may not be shot down at all even after many rounds. The bird was just too high or the aim angle was wrong etc. No problem, better luck next time? Right? Wrong. Those ammunitions, C-R challenges, eventually reach a target. If they do not hit the bird, they hit trees, ground and innocent bystanders. The more shots, the more damage they do. The irony here is that the shooter (C-R system deployer; end user) never sees the damage the C-R system is causing to all over the Internet. The other irony here is that the bird (spammer) was never there at all. He used a decoy which tricked load of ammunitions to get shot - shot somewhere and the decoy wouldn't care less. But how happy are the bystanders who were shot? It can be imagined that after a joe-job resulted from using C-R system, there is a bounty offered on the deployer. #PIC pic/cr-system-joe-job.png # Challenge-Response system and its fundamental flaw. It is not possible to know the sender's address, so any challenges being sent are possibly returned to innocent third parties, whose email addresses have been hijacked. Spammers may collect addresses and pretent to be someone else by forging the identity at SMTP RCPT MAIL FROM time. All C-R system where the abusers inject the false addresses shoot back in the dark and the innocent victims are under attack of so called "Joe-Job". ### 1.3.2 Modern C-R systems are no better It is often heard that the C-R system is used only _after_ all other checks have been made, thus reducing the number of sent challenges. A word 'modern C-R system' is often described consisting of: . Pass-List (known contacts are taken off the top) . Block-List (broadly tuned-conventional-spam-filter that dumps all the obvious spam + any address or domain you choose to block) . Challenge-Response (for the tiny percentage that remain) This is good practice and better than treating every mail hostile by default. However, the basic assumption still stays: C-R system _believes_ that it can use valid address. This is not correct assumption. The *addresses* _cannot_ _be_ _reliable_ _used_ for white/pass listing, black/block listing or destinations where to send a challenges. Relying on addresses is source of many problems, due to email forgeries. This also raises question what is the use of a challenge-response system if it cannot be used unless most of the email messages has been filtered away? What is left for the challenge-response system to filter out? The flaw in even 'modern' C-R systems is: If one knows that the message is NOT spam per one's filter, why does it need to be challenged in the first place? The 'modern' systems with strong pre-filtering and with more published SPF record may reduce chances of misdirected challenge _but_ both reduce gains offered by C-R systems. If the intention is to keep the spammers out of the mailbox, the C-R system does not work towards that goal, but rather keeping people out of communicating each other by locking everyone behind their accounts. C-R can be used to implement some kind of priority treatment in situations when auto-replies are sent anyway (e.g. accepting reports to abuse@*) with challenges "included" in auto-reply (as URL link or VERP sender). What about Microsoft proposed domain key or other pre-measures? This was discussed in comp.mail.misc #URL Using domain keys one already knows that the sender really was the sender, so can be the challenge would serve no purpose. Either the message is known to be spam and discarded (or other action) or it is not spam (as determined by one's filter) and should be delivered. In the case it's "missed spam", it should still be delivered in order to inform the filter maintainer that the filter needs adjustment. That will not do anything to eliminate "authenticated spam". Nor will that prevent spam from hijacked accounts (mailboxes). All it will do is reject (at best) messages which have the sender faked. Not all spammers do that. --D. Stussy [ in same thread but earlier 2005-01-24] The problem is that ANY C/R message is spam amplification. ONE is too many. The fact that some spam slips through means ADJUST THE FILTER. It is not a license to spam others via C-R. --D. Stussy 1.3.3 Questioning Challenge-Response system implementations If we think it a little further we find that there are several deficiencies in C-R: o *First* message from unknown sender must be initially confirmed. To contact 100 people all over the world another 100 challenges are returned. There is no guarantees that once a message has been confirmed no further confirmations will never be needed. What if the confirmation database gets lost or deleted? Disk breakdown? o A C-R system cannot tell whether an address is the real sender or a forged address. Sending challenges to forged or unknown address is same as sending message to *innocent* *third* *party*. This is called #URL. See article #URL<"Clueless virus filters spam innocent third parties"> for more information. The #URL "From" addresses are not a minority. Spammers don't put their address into either the `From' or other fields on their e-mail. They never get C-Rs at all. If your email address is hijacked, refer to #URL. o Spammers can run their own mail servers and have the capability to reject anything sent to them. That's why sending a C-R to a claimed spammer address is useless. C-R messages in reality harass normal people, who _do_ _not_ send spam in the first place. The victims of C-R are the previously mentioned third parties, whose addresses spammers use. o If challenge is lost, the original sender may get blacklisted (depends on the receiving end) and he may not be able to cannot contact the other party never again. o Joe sends message to A who is running C-R, but forwards the message to company helpdesk at B which also uses C-R. Later B responds to Joe, but Joe has had no prior communication with B. It is unclear if Joe must again go through C-R with B or if B's C-R system is intelligent enough to white list Joe automatically. if A and B are in discrete locations, they may be running different C-R systems. o If both parties use C-R, the _receiver_ returns a challenge, but in order to accept it, _sender's_ C-R software responds with challenge ... and the loop is ready. Who is going to verify what? Who is going to return the first challenge in sign of trust? o When A uses N email addresses, to send message to B, how many challenges A has to to respond to? A simple math: A (uses 10 different email addresses) sends to B (10 persons who all use C-R), then in worst case A must return 10 * 10 challenges to authorize all his 10 different addresses to be accepted by B. So, for 10 messages, 100 times of work does not sound reasonable. o How does A know that B's challenge is genuine? I.e. that by responding to it he is not responding to a spammer who is gathering email addresses? o Once the spammer get's through the challenge, he has a open highway to send as much Unsolicited Bulk Email as he can before it is noticed. Any spammer can use robots to auto-reply to C-R's, allowing them to instantly access the addresses. o What about mailing list messages? Or other automatic messages? It would require artificial intelligence to check which messages look like "human" and which don't and when to send challenge and when not. No C-R system to date include sufficient AI to send challenges intelligently. o What about different mail server's reject messages that are not consistent enough (user's mailbox is full etc.) or wide variety of other bounce messages? o Worse even, the automatic replies of C-R spam filters can be easily abused. In a concerted action (it need not even be an attack), spam can be sent "from" a certain address to thousands of C-R enabled email addresses. The victim address will be bombarded by thousands of challenging messages immediately and have at least their mailbox clogged. Scenarios to consider: a) [1] uses a C-R system [2] uses a C-R system [3] sends an email to [4] By sending that email, whitelists [5] 's C-R intercepts 's email [6] 's C-R sends a challenge to [7] 's C-R passes 's challenge onto [8] sends the password response to [9] accepts 's password [10] reads 's original message [11] responds to from work, with his work email address [12] 's C-R intercepts 's email [13] 's C-R does not recognize 's work address [14] 's C-R sends a challenge to . . . b) If A writes to B from work, but sets Reply-to: to A's home address, which address gets the C-R email? The (incorrect) work address or the (correct) home address? Which email address is the C-R expecting a reply from? The workstations are not the only media that is used to handle mail. A very valid point regarding the used technology was raised in comp.mail.mic #URL Some people have email-only accounts or may be reading their email on cell-phones that provide only email support. They can't respond to C-R "click here". Some people are behind company firewalls that allow email to pass through but block http access. They can't "click here". Some people may be using company machines that, by company policy, have email software installed and no browser at all. They can't "click here". That doesn't mean that they are "dumb". I even hear about systems where email can be read to you over the telephone with text-to-speech converters. People using such a system can't "click here". Such people may be physically blind but are probably not dumb. -- Norman L. DeForest A C-R system may look like a solution, but it only make things more difficult, more messages are send back and forth and people begin to be seriously tired of confirmations. Challenges may get lost (mailbox full) and mail is sometimes trashed (filtering in the receiving end). A C-R system is a perfect tool to make Internet mail based communication to die completely. 1.3.4 Summary - What are the effects of Challenge-Response systems The bottom line is that C-R increases enormously mail traffic by tripling the bandwidth (or more), because for the message, there's: o The message itself o The challenge o The response (if ever issued) It also takes people's time off communicating due to double work. C-R can be considered in essence another kind of Unsolicited Bulk Email which sender never asked for. Not only is the challenge annoying and can be perceived as rude, a lot of people will also not be sure what to do. The impression they get is that the recipient's email system is broken in some way and that they can't send mail. It can also be questioned if it is ethically correct that by design C-R offloads the filtering of spam from the user to previously-uninvolved third parties. The problems presented here concerning Challenge-Response systems are not in no unique to it. The original SMTP design couldn't see the situation faced now, where address forging is the norm. Any program, any auto-responder, like the ages old Unix vacation program, can be tricked into being a device to be used in denial of service attacks (Joe-Jobs) against third parties. This is similar to anti virus systems which send bogus notifications to forgery victims. It is arguable that until there is plans to revise the SMTP protocol or to add some kind of strong authentication mechanisms between the sender and the mail server, these problems persists for all auto-responder tools -- including C-R systems -- and therefore these "open spam relays" should not be used. Here is comment from personal web log titled #URL that expresses how it feels like getting in touch with a C-R system: This is freaking stupid. First of all, I never respond to anti-spam e-mail "challenges" whether they are from TMDA, SpamArrest, or anyone else. Ever. On my personal e-mail account, I have a procmail rule that ensures I almost never see them (unless they're heavily customized and my rule misses, of course). A reader (of the book) just e-mailed me (at my work address for some reason) to ask a question. I spent the time to answer his question only to be rewarded with a message (via his TMDA install) that he's not going to read my message unless I jump through another fucking hoop. Screw that! You know why? HE CONTACTED ME FIRST! If these systems are so brain-dead as to not bother adding my address to the whitelist when the user sends me e-mail, I have serious trouble understanding why anyone is using them. Is it just me? Is this too hard to figure out? Anyway, there's another 5 minutes I'll never get back. It's too bad there's no mail header to warn me that "this message is from a TMDA user", because then I'd be able to procmail 'em right to /dev/null where they belong. Ugh. This bullshit is not going to "solve" the spam problem, people. If that's your solution, please let me opt out. Forever. --Jeremy Zawodny's blog And the situation can go really serious after email hijacks: .> As former victim of such a harvested email address being used .> as sender for spam, I can only strongly affirm that the damage .> is very real. I received about 2000-3000 "replies" on the first days .> going from "user unknown" (usually from MS Exchange mailers) to real .> insults directed to me personally (which must have been taken a .> considerable amount of time of the writers too). .> Even weeks after the event, I still received back scatter emails. .. and I am victim since around 2 years. At least one time per week I get such DOS on my and then I get between 500 and 34.000 Messages a day. Currently I get around 14.000 per day and 95% of them on . Because I am Debian-Consultant and working seriously, I do not change my E-Mail each week, but SPAM is the price. --Michelle Konzack in Procmail mailing list 2005-07-27 In the US some big Internet Service Providers (See Washington Post article 2003-04-07 #URL<"EarthLink to Offer Anti-Spam E-Mail System">) started to offer C-R system to end users. But his has proven to be only a short term solution. Later 2004 large ISPs announced joint effort (See #URL<"Digital signature technology to eliminate spam?">) to move to digital signature based message authentication technology as outlined by Yahoo in their #URL. Others have #URL the issue and have reservations towards DomainKey solution and believe #URL to implement the same concept much better. Here is one experience from using one of the ISPs services posted in comp.mail.misc #URL: When my Earthlink email address finally was closed some six months ago, C/R was strictly opt-in, under the control of the user. If that's still the case, anyone who opted into it should be capable of opting out of it. There's no need to ask Earthlink staff to do it. I tried their C/R for a while, but as I got nothing at that address except dictionary-attack spam that slid through the prior layer of spam detection, all the challenges were either vanishing or harassing innocent third parties, so I shut it off. --David W. Tamkin And what really happens if C-R systems are more widely taken was discussed in #URL mailing list. No, it's worse than that. The collateral damage from widely used C/R systems, even with implementations that avoid the stupid bugs, will destroy usable e-mail. Challenge systems have effects a lot like spam. In both cases, if only a few people use them they're annoying because they unfairly offload the perpetrator's costs on other people, but in small quantities it's not a big hassle to deal with. As the amount of each goes up, the hassle factor rapidly escalates and it becomes harder and harder for everyone else to use e-mail at all. (...) But the real damage from challenge systems will come when spammers start attacking them. Challenge systems all have user white lists so that each correspondent only gets one challenge, then mail goes through directly. So spammers will start trying to send spam with forged sender addresses that are on the recipients' white lists. That's not so hard, sign up for a mailing list, scrape addresses from the list traffic, then send NxN copies of spam, to each list address from each list address. Similarly with addresses scraped in groups from web pages, Usenet groups, and anywhere else scrapage happens. You won't be able to trust that mail from your friends is actually from your friends, since an increasing fraction will be spam leaking through your challenge system. What will people do? Given the basic principle of challenge systems, which is that it's someone else's job to solve your spam problem, people will dump their white lists and start challenging every message. At this point, it's possible to automate much of the work, most challenge systems are scriptable, so that for example I have a few lines in my mail sorting filters that catch the per-message challenges from submissions to Dan Bernstein's mailing lists and automatically send confirmations. But of course, if I can send responses from scripts, spammers can and will too, so challenge systems will increasingly include "prove you're human" features like showing you a picture and asking you how many kittens are in it. Now we'll have challenge systems duelling to the death, since everyone will be insisting that everyone else confirm first. There should be ways to mitigate the damage, by using a mechanism other than e-mail for the challenge traffic, but I don't see anyone deploying them or even thinking about what a world where everyone challenges e-mail will be like. So anyway, you heard it here first, challenge systems will destroy e-mail as we know it. Yeah, this sounds apocalyptic, but the pieces are all falling into place, and spam problems consistently get worse faster than anyone expects. How many people would have predicted even a year ago that by now there'd be more spam than real mail on the net? Yet that's the reality already, and the challenge juggernaut is gearing up fast. -- John Levine, primary perpetrator of book "The Internet for Dummies" As it is shown that any address based authentication, blacklist or white list, does not work, many concur with it from personal experience. Here typical conclusion from #URL. You should read his story by following the link. Just personal experience/preferences as a long time email admin. Blacklists are evil and I *LOATH* them, please don't ever use them or encourage anyone else to use them. Unless you are AOL (who recieves something like a terabyte of spam a day) blacklists cause more problems and cost more money (in support and trouble shooting) then spam. In that vein things like TMDA can be useful personal tools but i don't like them as general policies. In other words, use them to sort things into folders but don't bounce messages based on it. I also consider them rude, if I get a message from someone I tried to email with a message that says "XXX uses TMDA and you have to respond within X hours with X code blah", I just delete the message and don't bother emailing them. Why should the onus of communication be on the sender? Personally I *only* use statistical systems and I've been very happy. My combination of razor and mozilla's bayesian filters catches about 99% of my spam. Razor alone cathes about 40-60% of my spam which was enough to make my spam bearable ... mozilla has made spam mostly disappear. Razor occasionally catches a mailing list message as spam (it's happened maybe 3 or 4 times in the last 8 months) but i can live with that. Mozilla has only ever tag's things as spam that I mistakenly tag as spam, and usually that's cron messages (...) Everytime we have an employee complain about mail prolems we have to go through the dance of finding out if we've been blocked somewhere and getting ourselves unlisted. These days, one of the troubleshooting steps you have to go through when you have mail problems is trying to figure out if anyone is blocking you cause they think your a spammer. Way to create centralized points of brokeness for a decetralized service Batman! From a users point of view I don't like blacklists because false positives are inevitable, that the false positives are indescriminate. For example, with razor I do get occasional false positives but it'll never be a message sent directly to me, because no one has ever seen that message before. You only get false positives on messages sent to lists. Blacklists are actually more likely to block users emails then list email because popular lists are generally on up and up servers while lots of people have legitimate, but dodgy, mail servers. (...) .Date: Sat, 17 May 2003 16:29:29 -0700 .To: politech@politechbot.com .From: Bob K - .Subject: A "Nice Blacklist?" No such thing. Our ISP has been plagued by SPAM. I don't know of any ISP that hasn't been. But we recently shut off our use of Realtime Blackhole systems in favor of in-house SPAM-control. Instead of an effectiveness of 60% or so, we are now trapping more than 90% of unwanted mails, and in a way that our end users have total control. We shut off the RBLs because we incurred a huge costs as a result of our support for them. When the RBLs began to support the blocking of entire Autonomous Systems instead of targeting SPAMmers directly, they lost my support. I had a carrier whose AS numbers were put into the RBL. Like a good anti-SPAMmer I rejected the carrier and moved to another. My ISP is fairly large, and including customer support costs the carrier change cost my company around $35,000. (...) Some of the RBL operators have become so obsessed with their tools that they have started to create more harm to Internet users than the SPAMmers they want to protect those users from. A SPAMmer clots mailboxes. An agenda operated RBL takes the mailbox away. Plus, I have run out of choices for carriers. My area only has a few that support it, and all of them are AS-wide being blocked. So I tend now to view RBLs with disdain and disrespect. (...) All of the anti-SPAM efforts have created a lost perspective I think. That is, people should control their own mailbox. A system that makes arbitrary decisions about what content should and shouldn't be permitted is a loss of freedom of choice. So, there is no such thing as a nice RBL. They are more harmful than helpful, they are less efficient than internal methods, and they take freedom of choice away from ISPs and more importantly, their customers. As long as legitimate RBLs maintain their support for those RBLS that have gone rogue, or are completely inept, they are more criminal or problematic than SPAM. (...) -- Adam Shand's wiki page SpamBlacklistsConsideredHarmful The consequences of C-R system are not the what the designers may have originally intended. How the C-R notification is treated by the end users was described in comp.mail.misc #URL People who are harassed by C-R systems will DISCARD them or feed them to their own SPAM filters as spam. Thus, in the long run, these abusive challenges will NEVER BE SEEN and will cause legitimate mail to be erroneously discarded. This breaks the basic premise of anti-spam systems: To maximize spam elimination while minimizing the impact on legitimate e-mail. C-R systems MAXIMIZE the impact on legitimate e-mail, by causing it to be discarded as if it were spam since a response to the challenge will never be made. --D. Stussy C-R will probably kill legitimate mail and in the worst case with no white listed mailboxes and no-one ever responds to a challege => 100% of the legitimate mail will also be auto-killed by the system. The goal of any anti-spam system is to maximize the elimination of spam while simultaneously minimizing collateral damage to legitimate mail (i.e. false positives). An improperly designed C-R system maximizes both. A properly designed C-R system doesn't minimize collateral damage and could devolve into maximizing it depending on response (or lack thereof) by the challenged. A well known spam reporting site Spamcop has takeng the #URL that false C-R messages #URL: Heading "Messages which may be reported:" However, these messages have become a big enough problem that we now allow them to be reported as the spam that they technically are (...) Misdirected challenges from challenge/response spam filtering systems In a nutshell in comp.mail.misc #URL was described how futile a C-R system is and how it falsely cradles oneself into belief of imagined security. And unlike a broken arm, which is only problem of an individual, the C-R makes the problem worse for everybody. C-R is like taking opiates for a broken arm. It does not cure the problem, it only makes it feel better for a little while, and in the long run it will result in even more serious problems. --Scott Dorsey Is there anything that would accomplish the same as C-R? Yes there is. A *GPG/PGP* *signed* *message* would prove sender's _identity_ much better than any C-R system which cannot say anything about the validity of the email address. Taking #URL into mail messaging would be much better road. Another new policy using #URL has proven to be very effective mail server level counter measure. Greylisting is non-intrusive unlike C-R and implements the same concepts without C-R's flaws. 1.3.5 Further reading - Mail, C-R systems, Spam o IETF experimental memo by Paul Vixie: "...Simply put, there is no cause for ANY confidence in the proposition 'this e-mail came from where it says it came from.'" See also #URL about proposed MAIL-FROM DNS resource record. o *Challenge-Response* *Anti-Spam* *Systems* *Considered* *Harmful* by Karsten M. Self http://kmself.home.netcom.com/Rants/challenge-response.html o *Countering* *Spam* *with* *Ham-Authenticated* *Email* *and* *the* *Guarded* *Email* *Protocol* by David A. Wheeler. A paper contains good summary and overview of the present situation and methods in spam fighting. http://www.dwheeler.com/guarded-email/guarded-email.html o *Challenge-Response* *Anti-Spam* *Systems* *Considered* *Harmful* by Karsten M. Self. http://kmself.home.netcom.com/Rants/challenge-response.html o *A* *Challenging* *Response* *to* *Challenge-Response* by Anick Jesdanun 2003-06-08 http://www.freedom-to-tinker.com/archives/000389.html o *Why* *Challenge-Response* *is* *a* *Bad* *Idea* http://tardigrade.net/challengeresponse.html o *Challenge-response* *systems* *are* *as* *harmful* *as* *spam*. "..." http://www.politechbot.com/p-04746.html o *Challenge-response* *anti-spam* *technology* *faces* *challenges* By Anick Jesdanun. "... Nicholas Graham says AOL won't adopt challenge-response because sending two billion challenges a day would tax the system and create unacceptable delays for subscribers ... difficulties because it doesn't work well with Yahoo Groups and other services where multiple list members post ... Amazon.com and other e-commerce sites also create problems: because they are automated, they won't respond to challenges." http://www.canoe.ca/CNEWS/TechNews/2003/06/08/106782-ap.html o The case of *Alan* *Connor* who advocated C-R in debian-user mailing list and comp.mail.misc E.g. follow thread "Re: Challenge-response mail filters considered harmful" for a while at His procmail based program was 2004-09-21 available at o *SpamArrest* *is* *Spamming* and o *SpamArrest* *Is* *A* *Spammer!* "... sending to abuse@spamarrest.com results in a sender verification request email, asking you to go through the Spam Arrest verification process, which will put you on the Spam Arrest Spam Mailing List to receive future spams!" o ...and finally Jonathan de Boyne Pollard sees that nothing works. There is fundamental flaw in whole Internet which make email abuse possible. You may want to study his opinion at http://homepages.tesco.net./~J.deBoynePollard/FGA/smtp-anti-ubm-dont-work.html 1.3.6 Further reading - Some known C-R systems Challenge-response systems do not return spam to the sender, but rather assists the spammer in victimizing additional recipients. There is _no_ method to reliably return messages to their real senders. Forged sender address cannot be detected from message. Some known challenge-response systems include: o Open Source *TMDA*. Tagged Message Delivery Agent based on #URL for al unknown senders . o *qconfirm*. Qmail based add-on program, that sends confirmation request message to the envelope sender asking for a reply to confirm delivery. Similar to TMDA. http://smarden.org/qconfirm/ o Active Spam Killer (ASK) http://freshmeat.net/projects/ask/ and http://www.paganini.net/ask/ by Marco Paganini o Commercial http://www.spamarrest.com/ o Timo Salmi's procmail based email password system http://www.uwasa.fi/~ts/info/spamfoil.html#comments o Alan Clifford's procmail based MARP - Mundungus Autoresponder Requests a Password. http://www.clifford.ac/software.html o Perl based challenge/response system with dns-validation http://www.thinknerd.org/~ssc/wiki/doku.php?id=spamresponder 1.4 Spam appearing in your yard - a story The following nice analogy appeared in comp.mail.mic #URL. It describes well how various techniques work in the spam game: DOGS POPPING IN YOUR YARD For example, in this analogy, I would compare #URL type filters to a helper that runs around the yard putting little flags on the piles of poop, so that you know where they are. Then you can choose to walk around them (in your fancy shoes, or your boots, or whatever). And sometimes your helper misses a pile of poop, or sometimes he flags your morning newspaper. But, the point is, spam assassin doesn't keep dogs from pooping in your yard. If, instead of something like spam assassin, you mean something like simple procmail rules that sort spam out of your way, then that's more like a little helper who runs around your yard scooping up things you told it are spam (either things your other helper flagged, or using other criteria), and throwing them away for you. Periodically, you open the poop trash can and be sure your morning newspaper didn't get thrown in there by accident. (thankfully, cleaning out the spam trashcan is more sanitary than fishing your newspaper out of the poop trashcan). Procmail, and other "sorting filters", doesn't keep dogs from pooping in your yard at all. It just tries to clean up the poop it finds. I agree that filters like #URL's (because they ARE a sort of filter ... well, not the DNSBL, but the mechanism by which you are integrating the DNSBL into your MTA) are like having a gated fence. The filter is in deciding which dogs get let through the gate, and which don't. The helper (the DNSBL) that acts as your doorman/gate-sentry may or may not be very accurate about which dogs he lets through. He might be good at only letting in the dog that fetched your morning newspaper, or he might be letting in dogs that just want to poop in your yard. Hopefully he's not blocking the dog that is fetching your morning newspaper, though. #URL are ... well, milters depend upon what type of underlying filter they use, as to what type of role they play in the metaphor. A spam assassin milter basically lets in all dogs, and then kicks them out as soon as it sees them squatting to poop in the yard. That may or may not be useful, and to a certain extent, the dog did get into your yard (wasting some of your CPU). A C-R system kicks the dog, so it goes back to its claimed home to bring back some form of proof about itself. Hopefully, the dog doesn't just run to the neighbor and bite him (as C-R systems are prone to causing), nor just choose to run away and get lost (due to being dropped or blocked by the original sender). And, of course, it does nothing to stop a poop-bearing dog that just happens to also have a pedigree certificate (a legit sender address that is willing and able to reply to the challenge, and is also a spammer). --John Rudd 2.0 A lightweight UBE block system with pure procmail 2.1 Suitable for accounts which ... o receive only a few messages a day: around max. 50. o prefer simple and easy solution o do not have much spare disk space (quota limits) o have no possibilities to get or install new programs. System administrator doesn't have time or the mail server may be is running at separate server which is not to be modified. The value of 50 excludes all messages from mailing lists, because they can easily identified by procmail recipes. The remaining messages that slip through are those that need checking. If any of the above conditions are met, the "pure procmail only" solution may work. Picking any projects out there and installing it may well meet the expectations to stop Unsolicited Bulk Email. Some known procmail projects in this category include: o Spambouncer o SPASTIC , o Procmail module library The instructions given here apply only to features found from modules in Procmail module library (pm-lib), which this document is part of but you're encourages to evaluate other to test what is best for your needs. 2.2 Where to put "pure procmail" UBE checks? Where you put Unsolicited Bulk Email handling lines in your `~/.procmailrc' is extremely import for all *rule* *based* solutions. # ~/.procmailrc ... whatever you can reliable check # End of file Why are the UBE rules put towards the end? Because rule based filters will make mistakes and classify valid messages as Unsolicited Bulk Email. There is nothing that can be done to this fact of life. The more messages they handle the more mistakes they do. The less messages they receive the less mistakes they do. That's why the goal is to detect as many messages as possible at the beginning and file them to appropriate folders. The chance of of losing important mail decreases if the rule based UBE solutions are near the bottom. Did you notice a small detail above? There is a reference to `backup.mbox' whose use is strongly encouraged for the first few weeks or months during fine tuning of recipes. Resist temptation to send detected UBE messages to `/dev/null' for long enough period until the recipes stabilize. Cautious persons never use `/dev/null' with rule based solutions because some important messages may have been misclassified. After gaining experience, some messages can be sent to `/dev/null'. Like the real positives where message includes a `*.exe' attachment, invalid character sets (Chinese, Korean) etc. 2.3 Using Procmail Module Library to fight spam Ok, enough theory. Here is the section to be added near the bottom of `~/.procmailrc' file. Make sure the variable `PMSRC' points to directory where libraries modules are located as described in the INSTALL file. enabled = "yes" # Set to "no" to disable this whole block :0 * enabled ?? "yes" { saved = $VERBOSE # Do not record this to logs VERBOSE = "off" JA_UBE_ATTACHMENT_ILLEGAL_KILL = "yes" JA_UBE_VALID_ADDR = "(me@example.com|another@example.com)" INCLUDERC = $PMSRC/pm-jaube.rc # If ERROR is empty, it means the previous module # did not see anything special. Try another # spam detection module: search bad keywords :0 * ERROR ?? ^^^^ { INCLUDERC = $PMSRC/pm-jaube-keywords.rc } VERBOSE = $saved # If ERROR was set, the message was classified as UBE. # The "\/" records reason to Procmail's log file :0 : * ERROR ?? ()\/.+ spam.mbox } 3.0 A heavyweight UBE blocking system If you have the resources to install programs (or get them installed), you're doing the best service to yourself. After this section is put to action, any account will practically be a UBE free zone. Few statistical programs are needed to analyze incoming messages. They work like binary: either they classify message in category A (usually the "good") or in category B (the "bad"). There are a few exceptions like *ifile* which can be used for classifying messages into many categories. The catch here is that these programs need time to set up. Their effectiveness is directly dependent on patience spent on training. Without a good training they may be no better than average rule based solutions. An excellent article 2003-08-23 on the subject is at titled *Spam* *Filters* by Sam Holden. Due to different algorithms used in various programs, there is no single program that would be a universal UBE filter. Therefore the best strategy is to combine several programs in chain. If one classifies a message as "good" or "unsure" it can be sent to another program which may have another opinion. The installation of these programs is not teached here, because it is assumed that you have the needed expertise and knowledge already if you plan to jump into "heavyweight" UBE protection. 3.1 Advice for Debian Exim 4 mail system administrator Before introducing end user means to prevent Unsolicited bulk email with procmail, a few words to a system administrator who is in charge of the local Mail Transport Agent aka the mail server. The advice given here is for *Debian* *Exim* *4* only, so google (that's a verb) few pages in the Net to find integration instructions to other mail servers. There is no other place in the system that can as effectively protect against Unsolicited Bulk Email as the mail transport layer; the beating MTA. #PIC pic/mta-ube.png # Mail Transport Agent (Exim, Sendmail, Postfix, Qmail etc.) include ways to check the message at SMTP RCPT time. E.g Exim includes ACL lists (1-3) which can check for incorrect SMTP sequences like trying to send DATA before HELO/missing HELO; forged HELO/reverse-dns combinations; to check sender against locally blocked domains; to check invalid characters in sender's email address etc. There are several possibilities. After these "fast" checks (4) external networks can be consulted. This could include checking IP against known block lists. If IP x.x.x.x is using a dynamic address space, the message is rejected immediately. Other checks may include comparing the message content against checksums (e.g. DCC service). If a match was found it would indicate that same message is being circulated. In addition to these the mail server may (5) call external processes to evaluate the message further with virus scanners and other analysis programs. The net result from any of these checks is to (6) make decision whether message is blocked or accepted. The SMTP connection is still open while all these checks are being run. Instead of reject code 5xx some mail server administrators may have even arranged to use 'teergrube' technique to hold the mail connection open for a long enough time in order to arrange a "tar pit" for the abuser. ### o install Exim 4, it's superior to Exim 3, because v4 can use ACL and other hooks before message is ever accepted. In Debian there are several Exim 4 packages, so make sure you use _apt-get_ _install_ _exim4-daemon-heavy_. The light version does not contain extended features. During the installation select *split* configuration files -- in the long run it will pay off. Also read `update-exim4.conf(8)' manual page after installation. After changing configuration, restart exim with _invoke-rc.d_ _exim4_ _restart_ (or use "reload"). o The easy part: install Debian package *sa-exim* (Spamassassin integrated to Exim 4's RCPT) and enable it from `/etc/exim4/sa-exim.conf' by setting `SAEximRunCond:1'. With few tweaks with the threshold values it can alone make 70 % of the UBE disappear from the system. The spam messages are blocked and those that are accepted, contain headers, which can be easily checked by user: #t2html::td:class=color-white:table:cellpadding=0 X-Spam-Checker-Version: SpamAssassin 2.64 (2004-01-11) on example.com X-Spam-Status: Yes, hits=10.0 required=9.0 tests=AWL,BAYES_99, BLANK_LINES_70_80,CLICK_BELOW,MSGID_SPAM_CAPS,REMOVE_PAGE autolearn=no version=2.64 o Install Debian package *greylistd*. It has to be configured manually for Exim4 (as of 2004-08-21). Read and follow instructions in directory `/usr/share/doc/greylistd'. After greylistd is running and integrated to Exim, _all_ messages are temporarily bounced back. This works because well behaving a mail servers will return them back. In the second time they will be accepted. The message have turned from grey to white, so to speak. Rapid spammers usually will not sit there waiting to resend the same messages, so the system is saved from many invalid messages. o The above solutions most likely gives 80-90 % shield against UBE. If you are hosting a large user base or receive even higher volume of corporate mail, that may not be enough. Have a look at method called #URL which is based on published DNS records. Microsoft's has proposed #URL #URL. Sender Policy Framework is directed at domain owners to encourage them to publish lists of servers that are permitted to originate email for the domain. SPF support is easily added to Exim. The instructions can be round from section titled #URL<"A.7. Adding SPF Checks">. If separate Exim 4 SPF setup looks difficult, you can use spamassassin's built-in SPF support. See O'Reilly's article 2004-09-09 #URL by Alan Schwartz. #PIC pic/spf-system.png # Sender Policy Framework utilizes existing Domain Name Service TXT record feature. The TXT record publishes Mail Exhangers (MXs) or routes through which domain's mail must be sent. Any attemp to circumvent this route will get caught. Here the intruder tries (1) to send message to to.com by pretending to send message in behalf of from.com. The mail server that receives the incoming SMTP connection stalls the transaction while (2) performing a SPF query to read remote site's DNS record to verify if sender is using valid MX routing. (3) Results were negative. This sender pretended to be someone else as indicated by SPF query result and the (4) SMTP connection terminates at source with a reject code. Message was returned to the sender. ### Speaking of SPF it is worth to mention that it is not a method designed to prevent spam, but make the mail transportation route more transparent so that it cannot be that easily abused. SPF will stop messages which uses certain forms of address forgery. This is good for the targeted systems, and also good for the domains whose names are being forged into spam. SPF will not, by itself, stop spam which uses the spammer's own domain name. It's part of the methods that help force spammers to operate in even more tighter space in the Internet as discussed in comp.mail.misc #URL 2004-09-24. Catching spammers is like cat and mouse game: The mouse now has to run a little further and harder to get to the mouse hole in the wall. There's a little more cost to acquiring that cheese. After you do that enough, the mouse says, it's not worth the effort unless it's a big chunk of cheese. What it boils down to is similar to the premise security system phenomenon. If a burglar sees a security system sign in front of a house, unless they're after something really special to them, they'll go to the next neighbor and the first guy on the street that doesn't have a sign is the one that gets burgled. --Murray Watson Further reading for system administrators: o *Greylisting* - The Next Step in the Spam Control War by Evan Harris . o *Spam* *Filtering* *for* *Mail* *Exchangers* by Tor Slettnes. Pour high-octane fuel for Exim from this page at . o *Teergrubing* *FAQ* http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html o "Explanations 3: Theory of numeric ``Status:'' codes" in Z-mailer's manual presents good overview of mail server's return codes at http://www.zmailer.org/reports-en.html o *DSPAM*. Beyond the statistical filters. http://www.nuclearelephant.com/projects/dspam/ Other opinions: o Why you shouldn't jump on the SPF bandwagon http://david.woodhou.se/why-not-spf.html 3.2 Advice for the normal account Note: Save classified message directories or mailboxes until you reach about 1000 messages in every category. After that it is safe to turn on *auto* *learn* options in presented programs. _Warning:_ in training, do not use messages that are over 6 months old because programs may think that old time stamps are indication of spam. You know how to compile programs or you run a distribution for which you can get presented packages easily. You have the disk space and you have the time (reserve a week) to hand sort your mailbox to individual messages. If you do not have the patience, it would be better if you never tried the Bayesian programs, because their accuracy depends on the quality of a comprehensive message base. Patience pays and the results are well worth it. Below are few programs that are supported by Procmail Module Library. You do not need all these programs, but the best results can be achieved only if you add more of them to the the message recognition chain. o *Bogofilter.* Well known and actively developed. http://freshmeat.net/projects/bogofilter o *Bayesian* *Mail* *Filter.* Very, very accurate, while development activity is unknown. http://freshmeat.net/projects/bmf o *Spamprobe.* Another very accurate Bayesian program. http://freshmeat.net/projects/spamprobe o *Ifile.* Yet another classification program, but this one can be trained to detect different classes of messages. Instead of two category separation into spam and ham, this program can be trained for any number of messages type: spam, ham, daemon, virus, bugs, work etc. Ifile is not well suited for pure spam, ham separation, because it does not detect HTML or MIME. The project page is at and low volume discussion list at o *Annoyance* *filter* . Development activity is unknown. http://sourceforge.net/projects/annoyancefilter/ o *Bsfilter* Ruby based Japanese aware filter. Development activity is unknown. http://freshmeat.net/projects/bsfilter o *Spamoracle* OCaml based bayesian filtering. Development activity is unknown. http://freshmeat.net/projects/spamoracle Other program that might be of interest: o *Spamassassin.* This a bit difficult is you do not know Perl and how to install Perl modules privately. http://www.spamassassin.org/ o *Spambayes.* Python based solution. Like bogofilter it classifies messages into categories spam, ham and unsure. http://spambayes.sourceforge.net/ o *Popfile*. There is one unique feature in this program. It can act as a IMAP client and watch each IMAP folder. It knows if things are movew. Thus, when message is moved out of Spam folder into your Ham folder, it learns that it made a mistake (and vice versa). http://sourceforge.net/projects/popfile/ o *A* *digramic* *Bayesian* *classifier*. http://sourceforge.net/projects/dbacl o *Controllable* *Regex* *Mutilator* Python based solution. A complete programming language, which can be used for spam filtering as well. http://crm114.sf.net/ o *MailWasher* server-side spam filtering program. http://sourceforge.net/projects/mailwasher Examine mailboxes and manually sort your messages to at least three categories: *good*, *bad*, *other*. The "other" category includes auto responder messages e.g. from mail servers who return undeliverable email and report other transport errors. It can also include cron job and other automatically generated messages like virus indication bounces that badly informed sites send. The minimum count of messages in each folder is somewhere 200. The more the better and with 1000 messages the reliability is pretty good. It is also known that inserting messages more than twice or three times can actually decrease precision. The rule of thumb is that the ratio between good/bad should be kept somewhere 30:70 meaning that if the total count of messages is 1000, there must be at minimum of 300 (30%) good messages and 700 (70%) bad messages. If more messages are added to the bad category -- say in ratio shifts to 10:90 -- the used Bayesian filter will skew and will eventually start classifying messages in wrong category. It is said that the Bayesian works best if it is kept balanced 50:50, but there are indications that better results can be achieved with ratio 40:60 (good/bad). Can't point you to any specific pages that would back up that claim though. Some programs may work better 50:50 and some with 30:70, so 40:70 seems to be a safe bet. Note: the following instructions are for "one message per file" format (a la MH). If you have stored messages in standard Berkeley styled mailbox (.mbox) format, please examine the manual pages for correct options. To train _bogofilter:_ (C language) $ rm -f ~/.bogofilter/*.db $ bogofilter -B -n good.msg ... $ bogofilter -B -s spam.msg ... To train _Bayesian_ _Mail_ _filter:_ (C language) $ rm -f ~/.bmf/*db* $ ls good/*.msg | xargs -n 1 bmf -n # feed individual messages $ ls spam/*.msg | xargs -n 1 bmf -s # feed individual messages To train _spamprobe:_ (C++ language) $ rm -f ~/.spamprobe/* $ spamprobe -8 good good.msg ... $ spamprobe -8 spam spam.msg ... To train _annoyance_ _filter:_ (C++ language) $ mkdir ~/.annoyance $ rm -f ~/.annoyance/*.bin $ DB=$HOME/.annoyance/dict.bin; DB2=$HOME/.annoyance/fdict.bin $ annoyance-filter --mail single.msg --prune --write $DB # INIT $ annoyance-filter --phrasemax 2 \ --read $DB \ --mail dir/to/good/messages \ --junk dir/to/bad/messages \ --prune --write $DB $ annoyance-filter -v --read $DB --prune --fwrite $DB2 To train _spamoracle:_ (OCaml language) $ rm -f ~/.spamoracle.db $ spamoracle add -v -good good.msg ... $ spamoracle add -v -spam spam.msg ... To train _bsfilter:_ (Ruby language) $ rm -f ~/.bsfilter/*.{dir,pag,lock} $ bsfilter --add-clean good.msg ... $ bsfilter --add-spam spam.msg ... To train _spamassassin:_ (Perl language) $ rm -f ~/.spamassassin/bayes* $ sa-learn --local --no-sync --ham good.msg ... $ sa-learn --local --no-sync --spam spam.msg ... $ sa-learn --sync To train _ifile:_ it is a little different. You can train it to use detect any category. The third directory *other* where you were asked to save the daemon messages previously is used for this purpose. Here it is trained with the *other* mailbox in addition to standard spam and good messages. Other viable training categories could include virus, bug (reports and answers) and work. Just sort messages in finer categories and repeat the procedure. $ rm ~/.idata $ echo herbalife | ifile --insert=spam # initialize database $ ifile --reset-data # OR use this $ ifile --strip-header --insert=good good.msg ... $ ifile --strip-header --insert=spam spam.msg ... $ ifile --strip-header --insert=daemon daemon.msg ... The strategy to improve these programs after first 200+200 (good/bad) messages is to put them in action and examine what messages slip through. Collect all unfiltered messages and add them to existing `~/tmp/mail/train/{good,bad,other}/' directories or mailboxes. After few weeks some the logs may show 10-100 new unsure or misclassified message. Add these to to the _pristine_ training directories. When it's time to refresh the databases with the newly added messages, it is important to start from fresh. _Delete_ all programs' databases, as shown by the `rm' commands above, and repeat the training procedures. Many of the Bayesian programs have options or commands to put them in *auto* *learn* mode while called from `~/.procmailrc', but it should not be used at start. Only when the programs have been trained with a sufficient message base of (best 1000+1000 good/bad), the auto learn option could be considered. The motivation is that using auto learn is dangerous. If auto learn is tuned on when initial message base small, the programs will eventually classify messages into wrong categories and in time "learn" option will cause the statistics to skew bit by bit. The reliability of the filter will suffer and confidence to detect "real" Unsolicited Bulk Email will decrease. So be patient and _collect_ _enough_ _messages_ and hand train each program. 3.3 Configuring Bayesian programs Most of the programs do not need any special configuration, but some do. With Bayesian programs, if strict bounds are used to classify messages into good/bad categories, message back ups can mostly be forgotten. A well trained filters usually don't make mistakes and messages can be sent to `/dev/null'. A UBE probability value for a good message is typically _0.1_ and _0.9_ for bad messages. For Spamassassin the values are different; a good initial setting to discriminate good/bad bar is between 5-10 (safe) and 3-5 (probably safe). # ~/.spamassassin/user_prefs required_hits 3.0 # Default was 5.00 bayes_auto_learn 1 bayes_auto_learn_threshold_spam 9.0 # Default was 12.0 report_safe 0 ok_languages en # headers may provide inappropriate cues to the # Bayesian classifiers bayes_ignore_header X-Bogosity bayes_ignore_header X-Spam-Status bayes_ignore_header X-Spam-Flag bayes_ignore_header X-Spam-Annoyance-Status bayes_ignore_header X-Spam-Annoyance-Classification bayes_ignore_header X-Spam-Annoyance-Probability bayes_ignore_header X-Spam-Bogofilter-Status bayes_ignore_header X-Spam-Bmf-Flag bayes_ignore_header X-Spam-Bmf-Status bayes_ignore_header X-Spam-Bsfilter-Flag bayes_ignore_header X-Spam-Bsfilter-Status bayes_ignore_header X-Spam-Bsfilter-Version bayes_ignore_header X-Spam-Ifile-Status bayes_ignore_header X-Spam-Spamoracle-Status bayes_ignore_header X-Spam-Spamoracle-Score bayes_ignore_header X-Spam-Spamoracle-Details bayes_ignore_header X-Spam-Spamoracle-Attachments bayes_ignore_header X-Spam-Spamprobe-Status bayes_ignore_header X-Spam-Jaube bayes_ignore_header X-Spam-JaubeKwd # End of file For the `~/.bogofilter.cf' you would need these values uncommented: ham_cutoff = 0.2 # or 0.1 if you have well trained database spam_cutoff = 0.9 3.4 A heavyweight spam catch setup using procmail #PIC pic/procmail-bayesian.png # Procmail can process and examine mail only with regular expression rules. E.g. it is possible to write a static rule that matches "viagra" and file message to spam mailbox. But the possibilities are too many for any static rule based content checking and thus statistical analysis yields better results for mutable messages. Each statictical - usually "Bayesian" - program use slightly different algorithms to detect Unsolicited Bulk email. Therefore consulting many statistical programs makes a better shield than using a single program. ### Several interface modules to various Bayesian programs have been included in the Procmail Module Library. To make using those modules easier, there is one umbrella module *pma-jaube-prg-runall.rc* which will take care of the details. What's left to do, is to define what programs are available in the system and which have been trained. The umbrella module tries every defined program one by one until some of them thinks the message is Spam. Bogofilter is a special case, because it returns value "unsure" if message is somewhere between spam and ham. SHELL = /bin/sh PMSRC = $HOME/procmail/pm-lib/lib INCLUDERC = $PMSRC/pm-javar.rc # Define variables # If you do not have one of these programs installed, # simply *comment* *out* the line and it will # automatically disable any recipes using it. # # For spamassassin daemon version, use "spamc" JA_UBE_ANNOYANCE_PRG = "/usr/bin/annoyance-filter" JA_UBE_BMF_PRG = "/usr/bin/bmf" # Bayesian Mail Filter JA_UBE_BSFILTER_PRG = "/usr/bin/bsfilter" JA_UBE_BOGOFILTER_PRG = "/usr/bin/bogofilter" JA_UBE_IFILE_PRG = "/usr/bin/ifile" JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/spamassassin" JA_UBE_SPAMORACLE_PRG = "/usr/bin/spamoracle" JA_UBE_SPAMPROBE_PRG = "/usr/bin/spamprobe" # ... filter mailing lists, etc. HERE, before spam detection ... # This module is "umbrella" for all Bayesian programs. # Variable ERROR is set if any of the programs classified # the message as spam. INCLUDERC = $PMSRC/pm-jaube-prg-runall.rc :0 : * ERROR ?? ^()\/.+ spam.mbox # ifile is special. It can be trained to detect several kinds # of messages. INCLUDERC = $PMSRC/pm-jaube-prg-ifile.rc :0 : * ERROR ?? \/[a-z]+ $MATCH.mbox This setup may be best suitable for a accounts that receive high volume of mail Unsolicited Bulk Email. Keep in mind that any Perl, Python, Ruby and other high-level language solution does not suit well for heavy mail handling. These interpreters' initial startup time is costly for both CPU and memory. Firing up such programs in rapid succession for many small messages causes strain to system resources. If CPU consumption must be considered for the overall server performance, disabling all calls to Perl and Python based spam solutions could improve server's performance. Concentrating on solely on natively compiled programs helps to squeeze speed out procmail recipes. The less external calls are there, the faster and more system friendly the procmail setup is. End procmail-lib-2009.1202/doc/article/pic/000077500000000000000000000000001130547513300173505ustar00rootroot00000000000000procmail-lib-2009.1202/doc/article/pic/address-harvest.png000066400000000000000000000766071130547513300231750ustar00rootroot00000000000000‰PNG  IHDR|ØàVÅgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEÒÒÒddʨ¨§íÿí%Íœ(Dƒv—ÈãããÔÐÈÌÿÌvvvòòÿ£éÕ·ðáëëÿ.q‹áÆÌšggg††ÖËËÊããÿøÿøƒ¤ƒ9Ï¡†¨ÕÍÍÿà‘2’ãÊÎãýõÿõ«Ö«¤»Ø£ÆëŽFFFg‡º–»–½½½VVVÃÂÂúúúÑÑÿöööµµæÑÿѳîÞÌ™ÝÿÝ{ݽ²²²€€€éé镹âçÿ眶Ô;;;ñññlÙµÑh êѺ£Ì£[Õ®Wv¬ÛÛÿòÿòÙÿÙAФîîîSÔ«sÛ¹·ä·šššÔÿÔƒ›º’’’ßßßüÿüÅßýºÔòÖÖÿ(((žèÒÚÙÙØ­žƒßÁ&@^œÃœ’ªÉ¨ÂßùùÿÏÏÏÏÿÏ9U‘!!± Ì™ÜØÒEa›ÌÒØaÖ°Ki¡ÙÞé¯Êçiz¨ðîí¨ë×™æÎâÿâm„¦}”µ¥Ä±Ý±ÉÉÇüüüb{›z˜zÃÄëHÒ¦\t•­ìÛœÀèXk™°q‰ªII¿Me‡¯íÜÎØæââö0Ο^~³ûûÿçñýްÜÇüóñïãáÜ££¡ÚÚòG_€AX}ÎÎÊ‹Ÿ¿¤ÈïéíóµÐîÑÑðyŠ´Qo¦fسÿÿÿNÓ¨—°Î´±ªgŸAAAw®‹'~ Î½¹²bba”‘ŒQk‰áÞØÇÆÅééøúüÿØÕÎ]]]¾Ù÷ÞäîÁÛùЉ‰š”âïýôôô+Ê®­¬Â¿·ëéåqqqîìé r¯’ކööÿyyÑmllRRQŸžž¥®Ë»Ã×MMM¹µ®ÍÒâÉÝõÄÞû¾Øô††…îï÷ýþþ…Š‘VpÃÝüóòðU§Õøøø}¾â÷÷÷4NlJUbæææ–––mt{ëëë33Ëþÿþê÷Ö¤{þþþªëÙýýÿüüûòüÝÕœ‚ûûûþþýÿÿþ101¸¸¸åéñð³K_jxýýý|¾^¿oÁ.OÝjCHÈáþêêíòôúCy ‰˜ƒBÑ×××}|{V‚ÔÙæ×ØßÛÛÛÝÝÝÿþþ“™¡~}z IDATxÚb˜> FÁ€b ‚Q0P €Fß(0@£‰o  ÑÄ7  Ðhâh4ñ‚4šøFÁ€€M|£`À@&¾Q0` €Fß(0@£‰o  aŸø˜™ñq)1Š&î&S à J%€Î¦ØPÜ\JŒìI„FÎ¥* AUò!µ‚n°—|t+ó! ÑÄ7@±É<šø¦ÐhâM|h4ñ Ll2&¾éÓh4ñ Hl2&>  ¡ø_( ÞFïÒ¡òÁ<„2j ªéP!fL6’“˜Ñ6Ùf\}±Áh¨&¾éØRåIVâ#ü0›¡ÌØSXSº™ÄÌŒ/ñM'2ñQob›6 €†\â›­À’öȨvñÀaöv ·ùð'>ô.þćÍuèžÇ_òa”ìƒ*ñÐM|hµ –zψ já…ÚÇú°VØnãQ;8sŽE=˜ž'ÐæÔ© €†ÌP r¿y:µŠñ̘½Dr²ËP\ÏŒ{8o/‹Ñ¸¬Àìí¢8¸@ µq>lÍ&ŒhDuE­í˜±›†>*‹Í\‰_âCkFœ&ÔáÀÙŸÂQ#`- ™ñ4"ЙáÀÒœŽµ7Š6ÇŒ:ÍÅ<­Ö›Ž1‚:B ÍÇÌŒOátŒ%²Ó±ÌzaM|Ì8ÖÓbíqc—@ÉvØœ9à €†ÂJff|M/,½]mheæ¼RrE.Y°®‚F™[EX‡9†¦m:¦™È}˜fãL}8ÆQÇ-±8—y0övhtÑ ÌXXÃÐhâÜioX'>€M|ƒ1íÄ@£‰oP&>æéƒqh„Ú €Fß M}ÔÚ<:˜@&¾Áœú†¹/h4ñ‚4šøFÁ€€M|£`À@&¾Q0` €Fß(0@£‰o  ÑÄ7  Ðhâh4ñ‚„5ñq&Ž‚!–,éì丼e˶Ì3tÎi=|ùèöÐJ|„5ñ%jeŽ‚A:::Μ&; ç´´“Þã!VòöÄ—É9 =X±b°ôëì¼ ,ú¬6èhiÝ{yûö*ûWâ+îÅz°€:< Š(GÅ äb5è` *˜ yØ7Ð ò±€H 0 °ÀŠØ@ŽLš4) àèáÇW¯~6±õóçÑË—ŸZ‰ €p%¾^0`+ÎeûñB€\ÀF"ˆ#’p€T408 ƒfl@+xƒر€ùX€&hÃÌ0@%P‚‚ P0 Ž]sô£ÜêÕë[[wî\¾|ùÝ¡Õè ܉/üÁ““o^Ÿzþ|÷hâL‰OîÂ(ÐÑ aºìj[|À*÷ñm­¡•ø_â{þ<ÔdþùóWÈO}°4•—DLÒ«òNòÎÅ“ðòóF(ñ-A´ùö2¹¼tiÌwßËÛ6ÜÓb‰ €p'¾ÏŸ?ðãË·³g¿>—`Û·o_?,Myç‰~ È>¶}å@nÒ¾8¸}U@I"ñ%MÏCKg‘Þ 4©˜‹$´Ï»úÔûaIm*°´ÏAÑ‘øö§õOM|Xß•+]Æš1® ¹Ä@¸߃ç22Ϲ·¿Ú¸qöóçáqÓûã&æCÓTÚ!ü‰ Á6ýY•À¯ŒéUIÓkª¦÷']è'"ñMÔégck˜‰$45%ñåNߗᔑ„H|Z‡F«]ì‰/Ä—Ã4Óuè%>€ÂSòÉÈØø¹}û«W=22qÓsØîö³úµº_ íܯŒýÇÁ©Kç¸Vrâ˸­È¶?mµ"[ܳ´gylŸ§¯&>ϑҞM¼Ûßðlzd\ZڳȸCiÏ´&î‡$¾}i«÷'_þÔÔ)ZSV§å÷§>[=12IK§?uõê‰û’žJRÔJM|ðÄj93ô@áN|l€©o¡Í¥íÛ…ŸCŸÀôþ}Ó ¬ Tò[UÛþògÓ‘_dÆç¼þéS¼§O94Q ozRË~¶ýZÀÄ—ü9cßô*`!˜‘QL|iIiÓ%MÜ?mÊô `œVõ9’ø¦äKY`âKÛ¯8eú”ÕŸ÷O9¤3eÿô `É·ÿnÐäý«ó5Œ&¾¡Ÿø⓱ùpi{¯ÌóX_\Ãô¸ýÅ‘ßþþ)ýÓ#ûû“Ðß…þþþ8`§¢¿ (ñ±Uå'Á_œâ¯©lÐÄ—±zŸ"$ñåÅÅ_Z\Ü!-`[2žøRNÌ­v‡~â ܉ïíïmóAó»wïT`‰¯ËX]ô»¯ëK|„o†cÞ¼y Ägó‚`É7:ÈLíÄ·bóæÍíííK—öíeÚö§ó²é6`ÑwîáPK|„/ñ…¿&¿yžPøöMM|ÔN|Q&»woåæ69¦ì©ÎôTS”á‡©ë† C,ñ¹Ý·@ 0:·;¨_äܹUÞýùûö)îߟü;mõ§ã.œ+Z ˆ@⣌&>š,,€//XµÆ_NNn}këP\Õ@¸ßRMÁRºƒBQj€>Úƒ˜†+Cþúr\ÞrÍÔäzëùht1éèbÒ4šøF߀€M|£‰oÀ@&¾ÑÄ7` €ˆJ|›Ûq>9ÊÀ‚Bb„0@ûf|²ûFß „?ñ‚ö½Â;0½¾(3 Hï^»¨½ ]®sÖ¬ux Ps¦è¦cÇ!q0a¨PÙ„-ù]‚ä@n ³€]1ÍrÁhâ4 €ð'¾ïvïÞ½y¶Äg¹p÷n&pâ3a:€&7ç çîc¸ß" ©ë0…·ªìÞ}ŒôÄ·`÷“=Üx÷  G@â{4´@îêa Ãp2÷ë^¡¢WxÅ)–Lp€f¢ÅM€h²¤É¯0=—ÀL#)u+$hðŸ{Ÿäû‚×äœ:|­âÌvvÃÆôŽ/Žø ¢Áï=\´=ã‚éðIV”E$+¾ …Ù“e„›¸©Øt]Å» ®JÎp”:á³<>ás¬‚Ò¿â»ÿ¾§ìÖ¡ Ã0PÉE‘¡W0È&·Æm’),t€ÈàlЀ‹"Yr,µ$tcãÀ–º¥ýôøÀÿ‚¬Uæ>·øSçFš®(ÜÛ[ŠèmaÇ\XZœ·¦6kgíàík‹¯"кÓëH1Ýf·¨ã4å ó&êfuv6Z>ñÍž‚¢ŒÔ™Ú#*+bõ}`yãkhÿø~!ODDÉ7 ˜øÞ=yò„ ³ä{²XíaT»œAÀäödH(åa&¾9A{º`U!JÉ·pg×PjZy ¨‹Xæq®\·îÉ“w]AÀj7ˆ‰óÇ“EL˜‰ï °¸ Z»›³0È„{¥åºƒXJ>• 'OŽYnztöhâ €ˆL|Àˆß»€øÄ' LGO65¯]°P˜i÷Öc(²] 8בø˜.‚&> õ{À‰oÓJ` »ò þÄÇÙ>g%¶Ä·‰sÓðN|C¬Ã@D&¾c{öìFK|öìÙ»cÏž µA›wïAkEµƒbxÁÖ=ÀŽÀZa`‚@ ¶®•{,5ö®Ü³µ©¸õ 0ÕåVî]˜Ú·AŸÉž=’oЮ=‹0ßá={Ö;L¸·¢ I|ëVîYL|ïöìÙ*:šøÀÛ ƒ0)ô±~Ò+<ä¦,y \Àg5é–H= X ÿâ»ò™òW(`Y´ JSıŽŠqTºx›ÞF°ålJbI&]”‰‡„VÖÑÄÖÂö¥ äϸo‰½k“¸ù 1øß+€ð'¾ÍÀþFЬ^ß’bÂ, ¹.Ü#- é µâ& á$GH›>ÇÀ^Ê*£ã|ƒÐèôÚhâ0@£‰o4ñ  ÑÄ7šø ®Ä×¥< 5ð¹rÅsoWצ§ íCß}/_ËÜp”ü†Râ \‰¯cú(44šøFÁ€€M|£`À@&¾Q0` €Fß(0@øß¹§@ê@-Å¢Êõ;ˆü{!r¡›i1:˜bó6À\´ë2^Í:1PÆÃB„|ˆ).ƒá<-Ñé VXܵáéSˆæs¢ÈÂZ ??ÁpñÓ§¾}@-Ó§_{ êV oðrp`\J°Kº[´|wE¹l:´@áO|VÜsp¿2”1éï’T˜B&°™Öu ChÓ;DÂô+ssÃÌ¥A!pö˜éÊ–ˆ™cŒªÅ¡Æ`kÖΙ¾ [X ´œ(© D<÷nîš¨Š¹¹¹M‚B¸U®-åZÉÍm¹ç÷ ¼ioÏLÁ§ïŠ•ËLXbÊ=_fÚ‰ €U»k»P )JÎqƒ‡R\9@¤­êA˜b@!MŒ¼Íð‘ø”a¦w!Ÿï¤ÄwÙM·&8ñíO WÐ,Tß0]ýétO´ì Tj/^÷`¼è´˜'Ó¯X‚Êû•À‚ñÈæÝø >Ó•XßR‰ø£‚n×µ­C<ñi‰Oy/r Ú .6€ƒØÄ7=ˆ(! ؃H|a¦»"ßtn¤Ä÷]«™×à‰a%¦…ž>Ó/cI|ÓM…}¡\á¥Ó5€³…¯Öô+ÜVÄ'¾éW°$¾éOÈJ|XìÚ;Ä@jËXµaÃÆZ MŸ †:Æ›íAÙ=œEôIúy-^2xÐ`†N©ÀSÆHÈ’©ðwè¢5lèII)têÚýG÷ßwú|UÓƒ(…ƒâú _Ý ˜e¾ÑIƬر†ä´&ÊxÌjwQï‡Ô ÞG¥u¡W2hð\­ìÉ\ÀT)ÍÕÁÊ‹ØÁw’OC÷Øžd…úÍeX7/¤lã^hg”/éàa]~ÃW%mº‚ñHàV÷’«R& ™G-]x‡üZù>™\ìS­ôˆóÐZó¼ Ñt–¿á›„†No•åd+?Š#Vo¾9õüj¥LõFŒÂäxG±Šÿä>™6Ñý.T<›n ½*›œBQl«8“µ¹­ÅM÷Ɇ›Ñ`ˆºß—Ô—±j„@†©¶ ÷ §!]L±öÂÙˆ¥/qyŒ{il®ØÂB…­Œ`ueš“<¶ÛÆâ2«’Tצßaf‡oÿ½>Ç`ì ·æËƒÉ´©‹>Áÿ$šÀõ >ù€2`5¹©ˆ°jç|wÝžpIWœ’ËüM1ÆýE¤Ý»=œúUDR¡»´G#§âl©ËŠÃ­S¦Cÿ|‰L‹"ÌǹøÈxfÛ‹œÌ· ž1¾Õ:ø†oLeÒáž­æÛ6Où”ü0Ÿ9âð¨<8¿à‹ªgÔ;k¾>éÏÒÄÜ¿ðMƱ«iKˆ <4ïÛ€iÓÛÝÑq;Úf5mãÛK 'õÚÇë«ñâP>Haç»óTn K¯ÔZ6¬ê‘zYEÓ o@Á#×áµûçð} @mê6 a¸p’aµ'h¥*ÕX¯Àᕊ¢Â¾Ä^#`ôHé@A¥(RÙ"ý¸Ró()AÁîÎÉT8ZâØ>ûî“¿û§v Þ’« ¾8p3yÔny`Å‹À·iYæ¨À†l÷ïû…Ü= SšöŸAy¾ZDSáÉŸƒv;G^k*ð…ù Ý7GAàÓ׈]§Úõ9g…iWøÑðKÕnà&u~m܇^»ã¯q4hWÐ{…GíJM§@ê*ÖM‚o+Óßw_´òįZA»ûƒï˜TìkN@ÉãMÊ5 a7=šhõJqI3Õ.Õg߯“v!â¦9äÌmßH,oRfd÷ª4)º×z§aÜìùµû+€ˆJ|]K)ã»ñBpâÛnm`$>h›’ø€ànÍ `ú$¾éÆÂàFÓBã ,‰ÑÓ41¾†™ø_ˆžøDMŒ­ž€“0A<µù`‰Ïg¯æ&¤ÄW8ÝÔx+þÄw æ}pâcòÙ³–øLi"÷˜øL0¸«žøžÀ»Ñ–žWæ0·ùLŒ‰ïònãËO¦w5knE4N!vq:ôûJpâÛª9]{aßôMàöpH|¨1C a Î ›}‚’Ð%8@0~ kªy‰ã1xš3ˆ+H\‚BnHî²µ ˆ5XV¬¸–óçÏÏdþt¾¿ýÓ¿á›0LÍðÆ¥™ªÓ”m ±2\N|­w:ñЂˆŸ™áŒØc]â°Ò+g;pcŸe-ö»ù9ÒuÿTÓåKn6ž8²«zà>MÉqÔ;¢3# uëE½*ç¿}ÉêfýÈ8št´bß­ nö‡ŽêJŽìmëh0˂‰ˆÒ5¸ ³Ô ïJ×*ᲬÒáÅZ_Π£XR•gôg ˆ4œT)@PùÂ+è"A& É€Y@)L˜‚ÈÅ÷u?§µ…æ]˜,"EÁà?Þl FNi®¥í’k+ûù&Ô,Ï.r÷ ånÄWÍ ÉpçFÍØÃgÓÍ_Êuw3U:<L®M2„Z(Ó9v^ÿ¾˜±vÜ ŠR¥Gœ€'R:Hñè] %7È%| .0J4–R$W¾MÚP䦱”™YÑ&m¶-¼Ýiçóöý|3}´+ã’ÜɃ2¶‚´Jõ~y ý­bçiÍR@eKôÄ,O2‡<‰t\p¬üîY|"3ÑÝ%g*gÒ:NFÞͤ>yä¸zUøÒëÇ&¨õ)?¤é!߯¸Ê 33™’±¶ÂY> Ø£+XqÎõ­PÜ7QrÐ’Ãg%¢Â¥…_§kƒ#Èw f¥€0¡[áØ?Ù/ èÞýˆMUü*P8ÜC碋¿™!‘ˆž±i$7…Ç›k“,Jö3° ü43ƒ-–ÄùçèpÔrZ¬G×?î?~ÐК^ƒÔÙƒXbˆ¼´=#hH%>ã AˆÊA{1¦O‚ºF!@C*ñq,-”ø]£íÅ ê;š¸€]Õ2  Ðhâh4ñ‚4šøFÁ€€"6ñ1€¾n{nBˆ˜®$`´©0N©…AO‚€Hø Êj¼¢­ßÿr# øn á ˆ„’/äaá;ØÂ5Óé*sH²èaGåòtÏé¾ïÞ¡Ìu½‹AØ55à ‰oŽ)b=ß^e¤erDSdåÊ® ÄwÍçêääJxâ›sm4j†? Ëè·n]»uïÓ­ÜL›Þ _QÞ« ž~çP±Üê;Gs«ïôéO·BêÆ¿›6m½,½.oíš>ݼ4Ïsút f`¡·u«æô­ï¶¢ Òù€æŽ1­] ¤L KrWƘ5Û ¶ ”`÷Nß{Yy4’†+ ˆŽi\ bøk¹÷ÉÂ'›b”ƒºÀk*¬¸…Õ/¿ãV_yaéuuPÛnÓwkÕWNgzg©Î0ýÇ&Ð •ék»Ô}º¦/TWçî3~¢~3ñ11*W_k I|–@žØ. ßrO×;KÑÑH® €T»êÜ:×,]7hø>]®v}—T]³ÜZõîÉP…zÛxá…é :{4Á Š^ñœÎ 2}%°W¡ Z,µAË­–†$>Ï"Ðê! ª½Ä§©1}¡¨éhµ[¸Gç@áP ÕËiN ƒÄ@„×ó=aÐøa<½p!´Í‡H|s`KòÀ@Sy=t™ÜJð^Ê Œ6¢ÚE¬ç'>Ð’¼•+¿CЮ=!C1T×ûÓ´ƒÄ@Ÿ7ÃpâóÝ„”ø6ùÂßmðº¦e hý9(ñ==fuÙDšøB–‚·‰q˜ÎécÀøbbà‰o“Ä®Ñć¬b'ÏcD(ñ1XÆXí>6]ë@ÐÓ9+•ŸXúj€—î}¢¼ò]×Þw[9LV®·×4çp¯dšnZj¦.¼{)hÚtÍÝ+¹¦oZ¹òØeÓw?@³ïÆ&܆•––+/Ä<±ä8d¬.¼’û;H.èÀwÆö5ÏY Zª¦ñnå;Ñć=ñÓz8ÔS@jáЙîj:ývLŒé«˜˜P¿Á5ÆŠ!†ƒ#æûtSH¡¬v9b^ÂxßAåhuú÷`‡¤yúÃpåj Ùš[/æ]É}‡ÊM}c€šÿ€ÝâÇŒ&>¬`µ•ι¢!žúˆZÓk/»4Pw|_þ®) Ô5Ý{5FnÚ£GâKã0µ:÷rh@.,¢‰ïןˮЍã\fº„½4šø†hâká ^âã¢#@J|4šøF߀%>€M|£‰oÀ@‘øŒ±ù¸Á˜/oÒBås\ô©Ü—›Pù.ûþ™nª©N—-«K9ðËg˜Žº.ç8|÷“|¢ý½¡ÌÈÿ¨¹sÂ¥æAŒã}DNš9ü@‘›ø6½ÃrŒèÂ%>OËžž&h{&‰OýûtSe&ÍÁ‘ø”ßa&¾k*/ˆH{ék`‰/ÿmTzñܹ尤·”øÊQßšÞÅÃ/ñ¹‰Ï×Kâ3>@Y €Öóqà ^¨=Ž-E\˜Î yŽl;PGˆ(bÀ8VðùµÄ$¾€âD:Œ²¨ó÷W„ðòæ‚ ¹™(©íôÜa˜øpsƪ Ã@†N~Åx E»Æ‡,!}›Ú@ºæ²hÑ”.&ƒéth;´`R^<:4O5w§º:tïfwŸNâ粤?ÄWy²û§ôOÿí·é›Bšø©a]OoUfFÁñͺ憧µ˜6WË|k«^ÞnëÅüú¯ÙŸëçiàË»ÀoŠáÿ#¾“Ü\1kÂ@•L…Œ¡?@Œ]¸;#)Aÿ‚-¶C–à(¹ÅåêÄ!ЀnŠÂ·4ƒƒÔ\\Íè­q°Ð;:ôt?Þ=¸Ç{ÇÇû[|Ê‚›®úˆ_x@Øœ‹2á{Såí.àÕ!û1}S¨˜R-;İda-òP<®3Í£ įê[Âã8À3Y‹ºVý$sô,¦?âãÏYä6(„¿C7·¾Âå\;–ªX íìp)éú@:8ˆwã¡óØý Yã¶ÈˆvrV($ŒL”á €²õ)ïÕ­û‘ÔxÆW'y‹øV³ª%‹ôFÐ/;ý Êh„e„Jy @hFF.¾2BJ*–¦kT“jŸ+ÄÝëõeã –‹\¦°'Ä2¶8EÓÜßTo°rGvѾ77ÈDÅÍMŽÔ¾»-“Éα‡ÌúFží¨Ç[Ç[y*ƒz0ï4Pÿø¾•Ì–1 V×­Çö€Ï?Üdbªaù½Xª\V·‰±|ªã9Ýø¸d}ômÈÊ'…Óßu–\3Ó=Çhâ-õ2¶>5™3}aátcKÅÓá ‚¯.ÜÂÿmžâ¤â™þ5yþ§fúGåƒëÔâIé½5yoA‚QÀĪvó€*[¤÷úûõ–çƒêÝ‹Q‘ýo'õ^Œò·ç?É›Z‰¾cËX@¨vŸrƒ½;àÃÄç'ç@K™E‚Ÿ 8Y­5>æiòôØ5б¸On3›: |4”5@çóMßúƒ‰)‘ø4WšÀbK| Ô9ŸOâÓ /Œ’ø@ÉMƒû€º)èÀ=Xâƒ$è{`ºì Á+¹Á‰|ì¬Ý >Ü/t¸(¤+sÙdéÖ§Ó¹ŸÅ×A“È¡àÓB…·2Ø¡àÄ·A™IÙ“[ý˜é5Hâ{áN|àvÑ£¨Ølä]%>(î¶íj€rH‰¤œøjæúÏ '¾ÈžÙ@áÓÞ@Òl0ñQ¯ÍGßKâ B‰oëËé ÀÄ÷gúË— C ‹,Ïmúq´º˜ø€q ÙdÖuìƒåÏé°Äwššö^ùÎM|êÓoA_áÊ—ÿl:O|—W>Ñ0…'¾—»5§ïU¾ >>ö\ѵ…p%¾¥Wn«g`â»}Eù6Dóí—Ó|¿¼5ñ=œ®¹û%¨l‚&¾ÛE&›þƒßËÛ,_¾DI|Ê0?™€¨å~jµçû5KpâƒK|~wE$>`A©Áð²ÂvaáCl‰ï44ñ9 I|GŽÌÍ=M|§Q_⑼ò£“z'ù¯‰òÎEO|†EâÀݳ& Dáp]Žåý€!ZܪpfÏpD¡…@þ€Sq•þ€ ²E—P:dBÀ©2;¥‘î…8æV;´Ð»ØÒ±{×ãq÷=x|ß{ÇÝ{ï@Mê hˆ™ˆ\)âd0µ­C ömµ…¨±}[íR…íâÿH(MÈ Geh.¸åO B†”»Õ=Zªy]óM…v+€Ìò H@9céÊÈÎe+äß®h?¥G˜¡L6}Œ\Å—Ðç·å Â(tø®Ä!×ÞÖÁ+CššUQcóhP´9%: Ìš<+Ì…_ÌX5Ñ"û¤‡‹%èG&$wZ9¬Nʧü €¯ÆëÖýh%èPŸÃ{ŽƒBtS¦ž«~œh/ޙݓ%êÄs ÇKE7ÇBO¯-,øÎy’²:+ «p¬1¶‹Q:³¦ Ëi_ðàÄ[œÞx^z×÷l<¿¿|îOåVÂ|0ú7Á÷%7W¬Ú0 D¦€ç|@ɰÿ‚!ÁKCöLn ²„û/E0Þà¥à%)x¬ÇRˆ C Ð zwVæîõbŸî$½Ç“tpþsÛM ÔBŠ,¾Á‘q´¯²ÁÙÍŸñ0[•ÎqLÀl¶ð Œ0 R‹vl0IÜŒ¥Ž5ØÞZ~ß9ÄiÀ˜Ziå€h¥‚üj¡÷XéŸæéoãV˜‡½O8[ Ôð(¦ƒ*—€xØ1ÐHÁ§Þ•8hœÌõ¡~ñÌl-`Õ/ôâí2ïu(þZŠ„Ùè×:TÀ£_ÑÔ-9Û–ë¾â‚ê4}':T´!¦µW’{nN{¦=á®]uÈrÊÓgÚˆ>yF´ÙÅ51qèUwNkÑ<½yóâÿl»¿ˆˆ6úذ ur»@›1±ÞW12§×¢Š!ýáUå‘4ž^ðÄ@ŽÅ}ò}‹ãIu'LÌ™3‡›c4ñÁ‡œO‡ò C*Ã9ñþÄ÷ÒÔôš\‘©é9êÆÔSSÓ £ æ>zà ÊØ'>€]Õ2rWµ xâ ÑÄ7âß-cI|4šøF^â˜Kâ ÑÄ7šø,ñÝGÐt㽘—-A;/ÿ>!¤ºÞê)±½c«…OáìÛx6 ? Úº¬¶«cétÝ]ÄØu|×õøZ0ë¡N­oCLÌ”¤\ 0è7„õ4èÝ» ¦hòOƒbð†aøˆœÄ·ÔЂć´úò)’ðÞw ÄÇD´9çˆR¦„lËtŒUˆ!çq<Ñš®N|ºÓ§—GRн«{§È{bìz/2’øŠt\9þ|g½žÄ€˜pÃX»×20@“ÝúŽ/øþgè'>€"'ñQv~JÖtÐmlB†‰S·%ñqc¬M…¬J_2)ù®ƒË:¤$õ~zcít"ß2ˆÊ—¬.ûþùþ}ãwÜà7Œµ[ùû¦=èÒAßñ‚?¾—ÉÜ·;x@ê®X5 ˆzV‚¥Þ7lN°2¹?²Í‘Þ"mË)lOˆ…m¶±0pÅÁ!\sg’W% ˜"]È6ZZ„@vV¯Nifg™avÙ3³»$™‘"qÁr¾êˆ´¡ª{Íů½kÌ•ŠÁ½nÛ# •»àtxgk[÷öå-˜öOÍŒ/±T‰‘ê{„*—§ŽèœÁçñ›hÖ×ÒúªŒ™»á.ñ‡]£,Ê[¿®r.¹†n£®zHîŸÿ?{TìÒÎÆi1L»€÷‘‹àÊîätÿĺǯ~ ¾5UÖ'ê¿;£C“q”½À×&Í";•ƒvF‘ÇÍ'&èNŒæä‘-g»® èÙ‘L1ÿ¦)oSzqijäøRž)ÝÈJkZ Wëª „~2l£5kè¹”¹§ãÒDÖÖÛ¤õù¿Á÷+sçïÚ ÅñÁQóDH”8i»»åéÁ¹cŽB§ºÞâ’EÈ@†h,ÅÁ±†ËV(˜¡‹BâBOÛ¬:õ Çq÷~pðá¦/ïýßlιuA[xnG‡DîFèÚ<M׋۷ÉîGºÇ¼¤‡½l5¾§²¼WX´u3¤9¸*à!FËoÅÔ¹\#¦qn@=RÀ䀯CÈÒ|tWŒÉÐÕÊO,x¼Jó_ecˆ`®+€ý<³ù¨­eôã…¬éKƒ#i­f¦¦ã’`óm SQ%äÁf³/.fz${7×þ‘'I© ߯ðݪò-×¥dÛ²ª…³CþÌkäøµ#Oùp·8’»iEÕÄ‹ª¦r»ñÛßÒâ]‡8¸¾SSöC†VðV¶Eab<ŸÈfœ„çÇG+L' Ÿ0î§øÇØ˜,mÀ°M®‰âð¾=,÷f¤à 'ŠVûb5´fªñ5F¿ ²¿u ú?ð} ÕnáÓ˜=ßAû*L5W¾ƒžÏ©v­Vþý£q´* ´:”z/6€ïÛêÝûn/HhÏÐJ¥w––Kƃ@ ›Vjþ×±O@·N!W»þÕŸÿ¼ ÈZuÔËÛ/<œî;ƒãÚôéL¡Õ®ÉS°]A ûq7…Œ×Z©/ô ÑЂhU»>žÓ54}§ß†¬ CŠÓkšÂïЪ]`ÍyÞŘÌ”(e×Ä"º;ß‹rDÞï|¿kPê=ŒjÖ‚Aª]°æÛ×µÞ‹èèè2êÈ{YûKG‡Q7­VG纕ή}::WÖê@Á.¹Ûøò±M:àpqƒ€Øò2È:ÜA––Çt,9tŽyÂôè\ ÷”ªÁ“øˆØÃ!M ‡¡$¾é껡wpcO|Æ»}Ö"%¾ DK˜øt„|'>Øð(‰œÞÀ‰yƒÖÃsÓ‰oúßB_ŒÄ÷´ÆÚUÞªþD}ëBQØ¥ÈÄwMØä(ñ=® [¶âºV˜á ±‰oúõÉŒ»tA PåüþzˆqX7/Úø¦_ù^äáÃRƇ@ òDÖv?|ÈXÚXûðáõ wé>|è©ü L˜ÀÔõÝ@&bX^3æ±l‘sL®Ý “~Xô’Ìc‚Oâ ‚‰oŽò÷ _ÐòQexÉ÷|*øåcAK§ûšˆÞÞªL|,-ÿ $¾9®ß-Q_—/<ñ%ˆ c`â} `z·%ñƒ%¾‡ÇPÇtÓ ç6_áw”ħ¾–øöìUr̤¹h-(¹…˜|šwŒ œøŽØÌï+§{‚J>å ¨‰¯[—±TD÷úä»»€ýŽ@Ü×½¾«tW-ˆQ˨+R+rÌx_+²3ñ¯½>ù:°—<ùsíuPר¿ñ=(E–Š4‚ú.×£§ïö©!W¢ƒÀ1Èzí' §þƒ»ä@“ò9в¢c õíת¼—òÁ®Á“øps…º Ã@´V‰¥À¶_°IQ§-©!Va%E Ah LJB*Lš&•4Cý‚)C“<0r 褞Ómt|Ìàt'Ý=Ù÷¬{÷øøíòÞ§ZÑS¸B@ÑF•¹jkç•—°´Œ¡Ø9ŰÀrQ||Þ@^ vB+ÄÄè«L‹@òæÌ4æ|QAÉ©µ„GcÇgŠ¡OæO7î„béÚøÕñ~Þ½éú<[¸n8è:þ…ö'ÅÄvH‘Í·Þ<†Y`—à‡>l:Î!'Ð#øuÇ|佟Ëi"Ebõ~_#k)3ÉRvL<ÆTF„ÃÂJÈ€à”ªôçYÄI½µ¼Øó¨çkˆ¨H©è°fj̘d:eªQ[vÒé^Y"¨ýV+ÙŒ%Kä1µàë¯xBôº‘ia·û¼ö|hJ tx°à#(Îs¬&B,þø.pwí& Ã@t‰L!”r+¤q¯-\§tf¸‚ µê­Ö¤?\¸t)nÜÇ.Òd€qÜç=ÁÁC !ãâ{vmî9÷>ƒL3¹ VÉ»,Z–|³ü‰jâ™Qr—”Ã}•—r4TÎ,p/*rðýÞ…v¢mÃ}ySÔ#·RöRB„('óóÖ+-:Ykˆ‚xïHWw1l%0Ú-`b^™G®âáõRUru•Í67µ•Ng=œ$ä4!sªì#aåI"Eñ˜Œl¢ÔY'fRñ™Êàè2ztüÀ›€£‰Ê(íþ‘ø>_âÃ?¿9w.m&Ž>¾|DzkæÚSnŠ.¸µ4ŽéÖE"Œº´ŸŸrÐÚÁ“øˆüćØHEíÄìÇ‘œ¿ÿc (FöÛT*BO°ìØ1Ñ‘žøˆüÄG3ðÑjí!Òúàƒ'ñÐ L|þ¦×¬¨µ æÄ@ƒ1ñùr\Û0zëäH|4_ˆ¯é†Ñzw$>€"œørO£& E¤}5kPw¾”ÁØ)sGIÜ6ï<÷5µÂL|è „/ÒŒéÞ½¦(§j<Ý‹²’…i/ºð0š+ÎØùŽ4–¶ ƒ B¾ã¾à€^Š´¢ëšæˆO|D0ñåzAÝØ^ŒàX $ÌS½‘@=G®æí$Òß*øÐ öÄ7ÔÞp”ú¬–n2E̺yÆÄxîFR§®ƒrnéwãµ1:èû wã\ŽêËÐÍ7Ûàîeî§ÄƸ+ÈÁ1»‰õ¡‰çˆO|D(ñÍ‹Z¸ùŸÎ+FææÏ†'žâÈIk&­šdq \ä\„%¾ºtâRßšÜ~¼‰ï_ÑôsEÓo›êL¿}Nq4hÞDùRÞMß§¡lø a‚N¨!O{âL|EO—ÂÙ:ÇðEc<‘3qJ¯òt­.XVÿ>ý{׈O|È9cÔb ŠWº€°¤0˜íŒaÙ~«xÚ¯ l—Æ­0l#ŒëmŒ £3Øíb³°M àäžÑ,q— $¾FÍc~¡áÿ_³‡ê E ÀÙíZwo‹Ëþ4‚)7¯Ûæû,±6µÀ—álýí½°ž[¢÷™¸v åòÀ¬Ë<\;û¶q¿Á¾Bǧƒü¼‹tŸË”ݵè3E`Z½3iøò+ 2©eçqF&V2Ì•ò3õ-Vþ/øsƪ Ã@žü~€NÇA60Þ3„ƸC@¤d÷‡TÃ-¦ œºˆà±të`´ûÒ¥%%{ <{i¡–LK§ö: ÝýÒðñK ñÿߊ:çâó¬ÉC¾¹+‰–O»A—I²£â0oÒ §tIT^¥åÞf{……ﱤ²;vCAY²â·ù… ûFð‰}Ö$!ï¯9‰ë„¸ +Ü›æô+|gߨºÚ,úa?¸°0øîãXk¬ÚHp?¾µ¥“Ô«ãtô1©sÜD_åèøÝvs±ŠÁÔëG¯ÏF#Ì” eÏ4 Ûª·Öá–PuRB{’­böÏôØó"3yLÁ¬Sh¡Ó´½#©á(.ÚܮŌúÞÚ¿ïS‘ø¢zÀ§wŠœô¶®îíªþÞôÓÀTv1=ÝbæÛ£ùÅþ§AÂéðÓÀü‰¯<˜Â&)Ó°<ìE7ébÔÅâÓýÅà“Á‰o¶·¿byúìpEÐáaþˆH| Q«shŽé®ß Nçˆ9§ÅÀmÕë˜NÙdõTr6îep5ówº«út`37¼ÔE§[õ¹>ìÒÔd:DZIS¬Ò `м`¥l:j3KLuu-ßËLç4Õ7hƒLç€$i­ ÀÔ#Ê1ýrámß>ð±ùO7»û& » ‹¾Oßln:§ê²,-| ÑÜç;ݬ’Át°¾ºÕ¹ËÓŸjB6b@‘ø€=òüºþÜ€IáG€éÇߢX›‚R8ñ„×_…Þ[pâNwqR$(åöÂH9ñA’ôØDâhùäPŠâ@]o`U8=Xìq€ã.tæ³:ÇÓéß¡Í:Sð˜ K7L×¼ìê >î£Ð ´¨è©««ëmÓBWW+rWðŒ×ßé–N_Êá ,dŸNÿó˜|€  éÕ§Ç\ñ¦Cö"ùþï‚R ”{ ,_5/€ìÛlNd笖úþr €*šMašAv=ÂàêºhwÚˆI|È;cÕb ßó˜[ ¡»§Pœ!pä¸Ý[J½ÜRò …,"sð2ä!Ò%]nñÔÑOà¥ùe‡vLöŒ!aôa~i€OO/«ºúX2?Ú0|g g‹K‚Ï€“9¦%®_íòü¶îôÆhºkg¼^xS›m[}wðÍV©‹jÛ}ÍðuŸU5ÑwáóÄ7>Kž?Ëÿ+ ï(˜h ø¼Ïªo®HÍ}ïÒæñü3æ§žÀCÓ“µÙ"û«,Š.àLh”ô³–£² ¢$ûCJ,p`±Gp…‹7ÅçÃëì^ŽÂΩ*eŠ4'²b,yGº "*RÏ1Êžs9Îå!ÀB$kŸ ¾«ä\1k…0Îèßx«¸î7AAw'} ƒ‹ø j;Ê£tr+þ©déÔÑ¡³‹z‰{ûºdH¾»îãøŽ$÷ù.—ª×øe\[NP3â0^+D¦äúÖ¼pëêl@œMûêµh⟚Kö>`õÝ·Ü »¦*ZÄ{²¾†u—՘ǜÙù€¬ó5 ÂÇ ©³ðú ùŒÀÛ\ÓRšßç-ˆP`•;im¥˜‘ïG R8û>Á§LPI›ä@V/’ ý§5öxV¹ §}1èRï ˜ÒI ÌÆœÇOÀYKó†Bx¥géáP ç0Ø(rÙ†]ï©­äs9 Ýol,¤‘æ:ÞË øØ‡äá<šÿÈ÷#9WŒÃ ÿƒ²ZBÙ31е| 0°öò˜úˆnHˆ)K'~Ò;§YÛÔCâó…áŽùW©Åî®,]ÙÇ:ªB‹‹²¼Ò eõÖi‡#1†8Õƒ6ð=™êE­‡•…˜ G“>N Ã@ä¦ãµ[I{öZ¥éî­Ûõý»ø ¾¹\r;rF*›…œ­" K§ÀìC’äHùÉ—Ê'9؉̻Å8[:Ù7‹H¨†@OºŠT´üwLÁZÜetàHìå,Û¼fw°·W¸1SºÛ‹ò÷b졼Zú#ñ½¡ÄUEì±rP•é§0t€UÀ¸øüâp‹ât¼ã|¬¬0xVØNtã€Ãdz ã–¥$ñÁŽI½§‰L}“zÒA«”{1g6ÖÌ ïÁ=ã:nfÝ$ÿA˜ø^»†¼Èáö†k×®mÀæ¸"ІF­!šø`ÇI!+áâLTÌT(ùˆª .‚ÀŠ ®’od,,€'>iwª"R¶Ä@ƒqUËhâ€Ä­Géšøh4ñ&>ŒÄ©|‘03¢d„WÐ0ÌÌÌdÆVãM|4šøFz⃲` ’¬Ðú.8‚Q¤$>€M|£‰ ^¼!Ò3Zɇ-ñ!ÔãïãL|4šøFFâcF/êp'>x‰£Œ7ñÐhâM|è‰gɇԮC¤Cf”IJâ ÑÄ7šøÐG”™ñV»\èÕ.4Ý’Ñæ <‰OëóDŽßÉFßÀ 2Ã{¬ðk `]YX§ƒ‹y4YGgâ <‰z°0ýÁèîµA1½†+)1Smn €ð$>ØÁÂt9®mÐM$Ã?ñ¾Ä§µáÚe_úÓL{£‰d&>.ffff.ª%>€Â“øn?¼`å [DDOpÍjù—£‰d0&>ê.© |‡C¾Ô:§³a€Î­¢Ñ&ßH|„÷dÒÛ/ï=Ô¢?xøòåhÚ ‰ €^s›þ`4}ŒÄ@£ÿ&¾K|4šøF߀%>€M|£‰oÀ@&¾ÑÄ7`‰ €Fßhâ°Ä@øŸë(¸ŒÏ7¾@×F#u4ñáM|p€p @¸uÒ—›™ùïVæ <¾ÑRffæÔÑć7ñaq @¼{™¹húôÌ–¦K—ŠZ-]ºaºëÒ¥K¦û‰ËK—‚fÁbbºÀ‰ïïRÐ)&1K—r|_Ê0Ç£‰`â ¢Ÿè浚O˜ß­µdõ\+,üîú¦wÌAÇ‚˜÷‚®ZÛº”ø¾[XT8ý3óîwAš£‘<šø%>€""ñ ï~Â|lúô­Ì™E™ƒŒ§1/œ®Â¤)Ì4ýióµ•ÀÄ÷Ç’Y“ƒù‰èt`âó}Ç,<É£‰Pâ "Ÿ¦æJfKpâ›Î¡¹™ÙšøæL%>`I7Tíj2ƒs0ñ›>šøF‰ €ˆªvϦ4Pâ‚k [ƒ˜Gßhâ£Bâ ¢;°ÄçÉ´t´äM|ÔH|DTâÓ b¾K|ÀjØÙ@$>õ fS   ¯ (ñYÆŒ&¾ÑÄGlâ ƒÌO˜™54‚˜}@‰ Ôí˜îä ìéj¼c~·W˜™yíô¥ï„w3sošþGeÎ'1Ó¹™™Ÿô<åÑć}lâ{ÛÓ£5ÝH‚®ÐúþÝ º«èòåï 3·ÿüµú:-ÊJlùþÝu4–Göhtnw4ñ Xâ ÑÄ7šø,ñÐhâM|–øh4ñ&¾K|4šøF߀%>€M|£‰oÀ@&¾ÑÄGÓ>|. ÑÄ7’Éý;¤ÌÌì‡n@ªsh4ñ&>ê¥;qð#"ñÐhâM|TIyò @bâ ÑÄ7šø(/òœäåÉI|4šøFe)Ï ÈK|4šøFt⃸Œè)ÂDòòp¦¸8RŸμqL : €F€Ü@ò%e ‹Uòa$>€M|ÔH|þ äy®µ$åQœøh4ñ ‡ÄwŽÈ£\©’øà)âÄ@£‰o8$¾3.<¼MNâ#'é™›³P)ñÐhâ‰ï£©+qG¨Sœø€)Ïœz‰ €Fß0H|‡}/wy´ì"¯Úef†$=ê%>€M|Ã!ñýḶá!±‰ù6 fF’srÌ)K|ã|4šø(·<ñ}'òÂ0Œë\˜‰Ly9`@íÄ@£‰o„&>.®ØXbî*14Ì¡Jâèvâ3}ôäÏ“ 'OL rOžø@B|ΓcDFÎ8ë È(të>ó­O‚~Lz²–©hùÝ—ûLP6uÈŠ$$”™5(¼\y¤<<<<‹â#½"=k¨‘ø0f*ÎaääÀ™æ,p¦““8@<±¼?Œ‘œyˆRyGNônú1½èöƒ$-U° Ÿ{2}úßä&'T»\M)K‚0rÈ÷é]ïf’[dMz{ÊßM^x$]㙬êÞ¢‹¿¥Nâ—|0 §§‡%¹9ÂE%îÄ@d$¾'k­¦OÝJn⛳«öÄ÷p÷Òé*—ÉM-}¨vuQZ€jb$¾ éÓ’øü#‰o.°,ÌÏŠÊÅRö…cŠÐ&ñ€8ƒÍ@n˵a(ˆã‘…¿î'ˆ(-sÉ «¯(+d”À ÄGu!5gú*å1Q1±©RÝ@Uä`$_!bf6ìîÒ­“ÓSyyïïîàÇýß_áëíøñÛa37C ÞóÚ²cÜí,}pYÿ¾W}"?Ëå‘ÀN7šåø8ÓßzåNÝ­àr\¾j¬CL3'ÀÄäõéÐà]>þT²:p–sDà\¦.«ã•×<ã ˆ%´¯®çW¡fœúÚã™±…¯Uõ À,Nßàm7Ôq“Åö>\“à±w}" :<ˆx¸¥Dqgá*å?dt#ð1`wÖ¾,x± VVmøZ‚JuK¬ÙÒš‡cLÁ­ÿø¾àæŒQ‚( v#P)rãǵd°u!,Ò»r\¨Pc|¤YBH±˜ Œ@Õbp)B Æ'ДRk7Ìn‘”éSüùüâ13Õü _M‰ì‰ø…O.ŸAúç§Ò ª‹mÀKªÕ•`í ·¹(DNË¡B¹nŽÁ=zî 0Pî ¼kÄíÂgAÐáY[‚p¸ýJ/íCʇ5¿ªõ*ÍÐ}:•Ù)мBC7tÀ–Hpáy\biŽ˜Ã<,Tº¦€O΃vIÓŠ;”ó) 6çLê …©¬^9hëÂ#9Þ Í·­¡á; Óõ&_7í6 .Z8 ºX*ZXCïŸ÷s¶FVü[DfÅX¢ïÁõ‚ÅãW,W3šÌ›;?2^Ó„ï…þòm¼Ÿ…´‡—Ÿ£œ)¿^ÂV͘Rß cŸÍI³f3ªšÿ |߈`âó¹|ùòVãÛÆH‰XÕ0­=LM[Õ‹˜@eŽÎî®—Àh¹vÍø]—iëô¢Ó=}¦¿{òäÈx× `uw ÒÚÚ´õòeMn× `z)g+çÝ­3=FeúnÍé~<õ}b5}Òéö{•Áiïéís&ÆEÀ”«Â­î\>4½&üNkí1­Ëà:› Xj]›nbüRk-Ó5 ÁßAÕ®é5ÏwK}ÍFShµkeù诇 Ó= òw%4‹ºÖªczÍrØ¡@×ÏÑúk¡Ю ¦×‚VZ©@ßtŸ½E…+u¬,µÖú€«Ýþ#ýÅ ‚n±÷éȺ£À¬&oÍš¹sAeZ¸– ?â°êHú¤â·“¼ËÂÓý‹ûW%/‚_øª5³óý#ë@5êìÜ5é½þ‹gËÌÈ€‹þ“ÂW׬‰êñŸ4iæÛšIá“€ŠÒýz¢†Gâ b«ÝBäÄ·P]™ êÓ- ]`ý Œ–>n r ø_Pâ Bj]™óÞæ%\ŸÊcLÓ©é8Nm¾•1 »t,§cI| Uç1&”ÄìøÌY² ‘ø@YXçî)€$>õ9>ÂàÄoóYZüJ|¾ð~8Ôr™{Î÷9p‡‚ýµ$î»{ÃJ¨CAÅnLÓ±¡¾¶ùÀ‰ÏX!BêÑÙÀ‚+/Ñb&>ÿÓyûÉ­ÔlCI|@ÍkÞæú+öø×Ìõ&¾`iYžpÜæËõö&>ÅÞSÀ¦a8´Í×;L@‘•øŠ4Bb_ùrâ³´ò=€šøžšBÒÉ÷hRÅ©é1uHÊÝà{šø|0L?¤Ùµövˆ öÄÇ´öá_“`âÓ Z M|O¯SŒñ;”Ä÷iú¦c:&…°Ä§É4=Æœøº€‰ÏxZâcˆAN|@»”a‰ï6"ñs 7râã>Æt€ûØ—š˜‰/rö¤I³#A‰%2šøfFSÓ̷ȉofx ,ñåxéÐÄL¶QÅQÀÂÏßûm>$ñõF¥÷ÀŸEñ¤á‘øðrõ¬ aX2ƒ¿ Bì ½ÐA¡…@ÿ€“-­«ÜªàrˆYžÑ!‹)œ2¸¤K×t̻ơCß\u,]J·ûxÞ»{á{ž÷à~ùŸ…€¢t£¸rÂW-X XZ“kRѶ Öñ6õ6´þ¢J£Ö|ÊRô ¾\/ˆ $Öͺ:"“-½»ˆ˜R‹’Ê:¹]a ç4gúÝGWšBcˆn1àTÃû]8,á>œøYgtð¨3“][â(voàëI1ù&”4ŠÐÞJÏMp¬Ì6^âêƒ9ht^ Þw^—ùYÈû‚:œ¥—ôÒßyºÏYRœÉ|ì,–AÝX®Ê1spÏÂìV)f![97w¥Z¯y ÊÑ5#ÇÜ2œÉ¨1Ï=.Tž?¨rÎðZ*.V<ü¶5>(òôô$c]Šæ5t»bþB€Œ‰5EóœÊ8<=¯×Å* Ö†s—•bQS*2s%ÞܹÐDÀ\ ˜„± Ÿ@'o×·ß?Jq$>€"˜øºÖ®Ô@—7y‚ǃ—UŽÁfB`Ê}||¸I”QE·K’~Îm"Ö ͸»æOçø˜2Öb•:¾þÆÛYˈ-퉈°c$¾šº\hâ«é­«QìA“ŸûÚ ÏÇ'>á€"”ø˜|6ta$¾¥øŸŽ |}„¯dXIjâãPÅm—2q·I£j¾½sìâÒ­Ó§¿'>]ÝéÇw!+`œ<]ä}¼ %ñ‰¼ÿü¬4íw2DN'¯Â¸WO&HFÆAÉø€æÿPÖÉÿX¤Ñ5ÑÄ€¹«e¢ÛS=yûöâÊŠ®kM8—¨þƒNV,ÔœiauÄTÂÁ‰žªJ\ ®"¶#ª#ª IbKm#6™7;$}%äò5Ï{÷µ4À·_ë €qá‡3о„dÅ Ùr.[JÐzV¹ tz|]͆/J¿_)aªPžã4cÀEÐŒ+&p:[!©TAä3P2> CÓ›ˆbÐtº|Ú:®)½ƒ˜[3ÀT¸ÚЦF#`õ©?µ ¹Z˜þ¤éâ” “os7·÷éâhÞm¿Kíœ$·¦Uø·¾Ýõ³öÅ­Ïj;8‰žN1"@Eà AqÅ1)dqŽ"GD•{¥Ø•îRä^¨qÂÀ{¹úϲûûÇÌ]¡nÃ0M3)°É4ÒÒ©, È TJˆé&…ŽvR¡Ai[ÉĤ “"M‘ Öfí¡Œ´Z ¡tÀÀœtñ%ûNòIÏï¸Óý¾Ž½„ï‚*·! I\O‚ù¶‚ÎÂâqη‡Ê™yé’û,Ó+RC×éq¡>÷"’žZ#¤øèó¢å:QÖ¶Ir.åµOáf%´òÀq"¤siuàó\ˆÏ}¯ßf*‰ÕŽïð¾¾pŒFpt@×tÞÜ—?¤â¬F~裺{èáFLßI¨ò2uÈ¡0miÞžût9ßQ&'ï’S„q„¨Á›'’d9 ‹MÒÈ»Eƒqó2ÇÜ%‡sK’Ž›$o(-(Ϙ6>Ј}ÜïŠZø3ñ¬çØ:4¤ ´;¾¥LH‚ß·ÌÛ-kÃ@ð£jP™õä ÝhU3‘øŠAú ö%ZŸ/;q¦fb…P +»9 61{S“ˆØ½-Čٞ¸î9xÄŽƒçþÃ×(|™ÁçNã¡Ã'I³Òõ¿+9²«srcA|9û"ñ@ƒ0nSgJ{øxÅDÁ¼»¶ÃÇbNY¹gSÒ<.hßË…Æ' ?µÏÇT—¸ÚDC$ÈD¥öiÃÝ3¨nU¢Òý×èð}|I‡oÛáKî·Ißåì9aîÌúíˆà0Û%@„×Cð®•Ü rì©NšÐåüI¯ƒT÷´…_é­l ÷b!’êpô^IY£òÑR<\! TÌmŽF‹ºÉ p¼^³s½vÿÆ÷#õV¬Ú0 DÏž “|A¶…=Yâ݃!Y< úŒ²•xô %‹2x xˆÝB&u+…„fè° ]œ!C<´PÉi·þ@5‡8!žîÞ§¿Áwÿ ¾;tRðèª>&~ì®9“Ö®¥2–a–iøÜ±É* F°^ðLJ«Ê÷2=É·¾Tç:v©«Ë?œ¸]ôÌ62¡ój_´ËtzVÂVgOí>ŒêFß¼i vu[²‘ú‹“õÍpÒí Y¤àŸ¥2h&Ã&Õê[ñï¹,h!½bqÐ7¿Ò½Ýì-2Æ­+Ž7•Ÿ9¥Í~Àg«ù1<çRt­ ˆxHÝÎs‹ÎrÁðVeQ÷nåQ$µI0‡å’ôtÉ»Ñv> áJ:¿K\±$)D‹]&ÉR"ú†ñ‰Z‰5A‰JˆŽ<ØXYjnƒ›Ž_ŠÒSÉÚEiú@v„€ƒW[*Ø®üZCk`ù5T+…M”=:M?è?ß·ÌZ±jÃ0­<2¾úL™ì_è`°·Œý‰úÙŠ ]<Ü4ÐÅ‹ÁC²º[)¸t¹ÙC'Ò%ÐwJ²uÈX ²é|òùq'=îOð==<Á'ÁB€` 0Ýa%Ä’  ̼õL†³[ ›][»$˜Ò‡úE3ãÔŽ¿˜é7O[×¾RÛæ°‡Š&è3.¿“ý‘¸)r¹ñf™"(¶°Ñî…D'V1§e?¶Êädùí”y ò¡> mýøªèˆ;qn>ºË{W~»9³-;YŽóJJ‚lm’-Xóºë^<3zŠá±tÎ-GñÊî•R©•«TƒLeû4ÏØà½fw ¬LP:%âÜ¢š¢ÓíØÛÜ—9Eõ Õ“-_°Iù%t‘vÉc¬šmû±Jº!-šxr.}õÏÀ÷+€%¾¾µdï³öÁ5Á Ì1Ê`ÃZM tkš  Ôî¤ÜI›®PËs -:8ö̓Z6·‡hâ B‰oúwî—ä®äðrá1ª§½µ»(Ñ®9g¡/#2¸ÎH)h\xÀ“Z¾3^¸p¡p v9Ñ+]LOM‡hâ ¬‘Öy&qœCî}õ®¸=M©¿üÙõEÚµLM.£.h15Õ¡–ïŠ@]`\³×VVˆ·hÍpáÄ7 †d‰ €°&>Ž KtFcj4ñÑz† €°&¾Ë:Gßhâ£yâ ¬‰o‹Nç…ј†`ÍpÖÄ·íÂåsHÜBlŠ.(¯Õ«[™(‹¢É]ƒ÷ô|••c€Ýe&OP7ƒCY]kz‘¨²2bm)ˆ÷¹c¸a¯²1’íEÊk×*›îE³@ÇóÎÞÃ&_DGnp6•Æß‰5ðb@½ˆ®ÒËBÍa™ø@›vÁ$=@aM|™ç¶hᕾµà4´w/æà<®rK¿O·Ò4=÷ôÚtŽ§Ó¿÷i™‚€§>Qdå ñ1«é¾(‹Ž*t˜Ð,ˆñÁé@_OÄHÎÓ.|îçð„ÙcEDœc:ƒL™©–U×ÒáYí2CHü%3u@aM|ç¶“øž‚ 5_QÌ…Å‘Íß4ý;º¼tú&`I©îªówúôsp ÍEÈ%ÐSô„Â0ýÆ0ª1n.E«ø×ûOGW@Äd QOacêצÿM|”&>€Ü-Ã0 …#•ô=CÕ©lŠ*…–ö#ïC¥9ÁxµsL#‘JŠ v‚VÚ‹û32iÃÃqœ—ø“àØá»Î[v˜BƧêÀ€Çc½†ë9%M0ªDoAËGªñfh´ƒ«»˜Ë·ÿ ™°²’,ÆÇLÙ ­µsa‚“Ÿš:r ïþ’<  $aÊsÛhq £MëeŸ®WJ„b•†IÑWjÆCÉ¥O¸çî¾yç¢ZÁsò.3\5ƾ }­MÚßÀ'Å2Bµ ÂB¹Œ¢fÑO½×¾Ã÷€»+Ä‘(„¡•\`Î@J0+0õH’Kì?ÈXN€ïAVlB‚A}ùO€a’¥ìdÕÊQ“` …¶ék „”ÁÇç×óK¹X| 8’æÔÛ$úõz¥lÊx% á9TÐÀgbžþЃÓ¿}ø¬–ÍüÈeÊ$Ñ£§¿Íų¬NªÛ°æÖ¬ ì¡jä½±“ÉÙ¤z©q$¢¸o½?o\¶@tÏ5B¾3ç²Ô¢œ­§Ñ»½ÆÖ¢:çµE`¥]¦Á`ŽØ.åÐ!:“¨+ÉÈ'¨«ÂùUW‹lîei¹…qv Ñò’ºy±zÃáß |R¦e·AžT_°ü½,òýÀÍ£0 ÃPT£/ÐK/²x÷˜ÍcN‘ƒtÕ5r’t12æ^<ôKV¡…Žê!XÁÖwàób°ðWóm`:‹ EɼD¯lJ7¢¾WŠþZCšíhÂÏÚÍ7Ku¼TÌGX —pšoŸe·yEv–T=`¨‚|¶ÁR ¸TDM_×YX.ˆÁT¢‘,THU -b•·…†ÆÕs?-Àpä<ɨÈ[–´Uî©ö{IîX³}åûd ÀäÒ;·ø^Kû#ó]íš !_7ŸÝFÿó=àÞŠQ a`›·È¶6éSú™ûL¾áKd!`sÕ–þa…K¢.wppl{eLLFL0ú•|¥]ïbˆ1òi—‡MxuzˆX0n¦Ü ªdœt^6-ë’ó·UËqÖþÊÂ]ÉC|»È±ýj‰E¹à¦ÃBâù·cõÎzéݦ¡˜8lÞ>¡I^±Ì^%vhy®„5Os2 ª«Ä‡ ŠÅz8˜¹ÊTQoMC§ðëÙÝ»ÉRøü»šodÝQó-òݨù~w8^pgÆ8 Â0ºô,k–ìÿB¹ ×ðIP$K]2Ñ-·èÿ1j—®]:€"ô°ðeòá«ølÚór]žó½Iiô¦þŧóåg|àO› ’±ô m86ÝÐ1Ž}ÔÏßΨðLD9Å!h)/y&V2úêš1J—ªðáÂ})ãÑU£#2N¬SÔDßωX”–UU¯ ÀT®ûãà&Ó²õy ¬iÜ­giév™‹³d..ÑZ”wid8n¿ßKê®b† ÷Äê%»?Ägú¾¤bÊRé$F~qNh¥7ÞrSQ!Ž¥ƒh%¾Šï}Þh` |Ö¨ÜTý¢0']†q¨ `'Íœ ¹OùaE*A†—_ ˘®¾mÄ;n×ÊÁ…ÅZ–NqVzÀ/ãóüG¡X¹Ðs~dãÌàfbÔáÍC¯e5nâ'` ¸FôH½Ž•P’‚ĸ{MVÍ}Ul+ ¶Æ’˜°ÓŽU)la§m1:íßÅ—ê[Æ÷Øó=Å—Ëîë_8>kâ{yûÞc(t…5xñ#”›†QP|®¡! ¢Å "pã`6‚…àj dU¨º öÁ97ÜÖyˆì`¡ $ŠPL€V EœV(þ„ËÂÌD³æñéH^¼=äxœÑÙ…ôvAí>XGTò1Sez €°&¾GÓ_N.àÊ€ Ö×/_b½šöÂKÌèô=§×kâ»=È30 àöCÔvXÑDZç, ÄÃ飉ž‰ €p¬¾=} C0ÈV2ÐhâM|–øˆa4F(‹NffFfÁ™£‰Oâ ÑÄGi|Â1‚…ÌM|¸@&>Ê33,Å1#Œ9šøp'>€M|'>fXʃ³P˜ðÚBA*åébØ&>Â34šøh]ð13£©šÎŒ„Ftâ ÑÄG‚……ÌDo›‡ÌÓ M8È6Ðhâ£OâƒÖÀèõí`¨v™c™™Ai¼}D€vp€°!|5)hr->»¹z4ÃË Jy [×ÈJ|4šø(j&*$2¹žEôQË?úl3 +ÿôÀ¼¨¼®Xò1cYM ]W`šÙ¥`µKfâ ÑÄGLÊ»uë3³Ÿ~˜±p‡L⃦܉ìj €FÁ¤w ÈH~¥$ó€N¹J| ã Œºš3ñ|·ùh4ñˆ®[H9õ0Eßàèp@:ÌÌhK™á«IaHo¼˜ÑÛe&»Ú ÑÄGBÚ›>ÔS9ã|à’Û83¥Ók4šøHH{Ó‡zê£kâ#<Ã@£‰ØÄPÒ©¬ÈÆ]ÌÄç£(ñÐhâ#)í¡¦¾‘‘øh7½@£‰„Jwȧ¾YR‰ €F‰ioH'>®ÁUòÐhâ#©Òâ©o%>€M|$|CºÏ1°+™1@&>R ¾!\ô1²Ä@£‰Ô‚oè}̃,ñÐhâ#¹àªE³„JÑ7ð‰ €F߈I| ’¹ìøÄ@£‰ô´7$Sd%¡Rê£û"ŒÄ@£‰od$>`™©y«™é—ø˜™ÁCÌ8@&>R»C2õSxá~u5<õѼÚe&4Î@£‰Œ‚oÈ%>PÚ¥>f.¤Ô7ðƒÌ4šøF@⃤=H{‘ú>ñÐhâ£8ñ ÔW M}j̃#ñÐhâ#'í ©¢–ú€E8õ©©SßÀ'>€M|Ã=ñ!ú¹ÀÄW”ú>ñÐhâæ‰ÚÏjëRê£×8îÄ@£‰Œ–!”ú`ý\Hꃵ÷˜Õ""˜™<ñÐhâ#«à*‰ÞÏ…¤>æjh{9˜i”ø`+— &>€M|Ã9ñÁÒ°Ÿ N} úšú˜#ì옩™ø )˜öˆ.ù-ñ$@ `EMp .`P3€À ì! ¦€5¸C „A ÈÂ@6 C/dAÁ ¨ƒz(ÐG|øÁðL|ˆ´W I}Äia¶ƒ§> 30ñANI#±Ú ÑÄGfâCN}̃?íAS8íÚ{(©‚Ä*ìÈnóÐhâÃL|Äô7†@чšöÀ©\ôE€Û{\\±ÀÔ§ÀLIâƒ$<ò;4šøð'>ÜÉj°'>ô´ìçN‡ôsXæqÅÆ2+(€S9‰™ ½]€M|Ã4ña¦=¤~®´Æ…¦>’3335†Zh4ñ Ïć-í!õsQS‰‰~á)¥‰ €Fß°L|ØÓž3¼ŸkmïS_3I‰™™jƒÌ4šøÈM|ƒ9õáH{j̈~®´½Ç\PK}„3ug8h4ña$>"ÓÞ N|¸Ò^3¤Ÿ J} ©@⃠IÍÄ@£‰ŒÄÌG9%—™yÐÜ1‰3í¨Ÿ L} H©ÏÙ`⃜LJÝÄ@£‰œ’e-é`+þp§½H_)õ€SŸ³ ¡ÄÇL‹…4šø†|âc&:í[|Ì(©Tã‚RŸ‰‰ žÄÇL«U-4šøÈjó1¢‚µ¶Ç—ö@å¨u M}Ô§g‚§ä N£Ä@£‰¼ó J|%Ìħ=È °Ï „à´lïáçc†HO£Ä@ØÐNp¢ƒÑÀ4Ç F(‰’ò˜©ø˜Ã˜ñ$>f¬‰y {»Ìƒ'í• RQiÜÓà÷@iÏgâc¦ñbR€ÂQòÁRÉÇŒ–ø˜!‰™ ‰™9Œ-ñ1#%>f¬‰yP%¾ëm€_ ìÆAbÓ(õú¹Àôiï¡&>Pº¤ÃJf€Â•ø„@ÉB«]º–|̃¼äCO}̺ÌH7¸!®¤Âè 8ñA ?Ò°Ÿ ÒàJ{ÈWÊÑuÈ swŒ DA´˜cQØp +b<®‹ÐX`,´`—„†âå“là ¾yãمȽŠÏܳ‘É„çÍ·Ã"¼R·¤ÇNJÐðyVBª;›Kw­\ø@zØ"÷øÏùÆÞä'#ïð©ï‘½5ôiﻡÐ)qwp Qôð;²KKÑ”ë̬ ‚ã%äÇ Yˆ‡|À§Mfná½3rê™¶7¯hùÓšÜ%É+|¨ »K±§¦È»ð9Ù«ÌÎq]J>ó=v_ÿpðxàþ×¥Iÿ³–Ë¥¯Ï^éio? ÎŽq€`( ï6'â^N®O‹0vÿò7e‰OåYù0–Oñ%ŧåcø$zV?®]ΡtÏÊ–áCÃ'|lžC[»œ‰¯—¯ø3|Ê·G€{?‚+>jOnÏÏáY‘øÀ%+fɇžø m>Pµ;ƒRòÚ|ÌH%$ñÁÚ|X¸Í‡”ø@M>Dâ§¼A”ø©f±ÈLÓ´g2À‰ €(H|ÌÐöˆr!ªÚ…%>âª]f¤j—KâŠÒ"ñ[ë"§>š!ø‹Tf Ҟɧ>€Â3ÎÇ çCܰ «v™Q;à6¸ÃÁ %f@;þ´ÚW¸(wh‡"‡èp€ l0à…`•|D7ùk h_}áNÌ”¤½N|4:ÃAVâƒ%fzñaM€ÌC7íM ÑÄGrâcF¯xéÙnÇH€ÌC7íM ÑÄGRâÃv<3ÝûŒÌ”'¾A‘ö¦Ðh⣤Ã10‰¹È’3ÞÄ̦ÄÇŒžø@-ÌFÌÐ%-ÐI]f8 N|טô@(é]%>LÀßuN| †>ŒæãQä&>æÁz b>w¦½é„kœ–옉J|Ìx³} $ñ1£'>ð3xœšøÂÑ'w%<ñÓ8ñ˜@”|ׯ˽ë „W$@i‚Á©’øÈ-ùýáC3íM B%3J>fxµ‹-ñ'8ŒÀkZ€Ps~ =ñ]Çø*‰–î(M|̃ýÄå¡›ö¦žÄÇŒ4Å^S&!“àÕ…¤àršø`«ª ‰™Ù Zé2×TYÃf9`Õ.d9þÄLx`\éâN|×q%> Å„ Ä‡#Òlê•8C˜É5zH§½é„on1¹ JyÌð©Ý&fÈì®$tM¼Ú…Ìì–Í€$>Ðì¼äƒÍíB×TA–¸»Cj]ì‰ÖæCK|ÁÐt‡‘ø /¬ÍG•ÄÇL‡Ä,ZÑKWfR ¾¡™ö¦Þ’–ø˜«ù`‰Dæt!‰Qò1ƒTÁJ>Dâƒ-©—{àeUðÞ.¸Ú§<Œ’Kâ»~-ñ]G/ùÀ…®ÄGnoW{Ÿ&%©‰oˆMlÀ@Yò±¢%>pÝ+É _FTòÁÖóa/ù ë ˜1Ú|ø(õ$ýáH|°6fÉJ}$'>fR´øb†.—‡Â`*˜Q†é $òŠz°èj>f„®–'óPN{Óˆpâc†T»H‰º¬¥Úe&«Úef&#ñS<ñ]Ç‘ø{»H‰øj—˜´WM/Hû3`é ‘ŽR3"ÉáBÈzq;†y(§½é„oIˆ„w8`m>P—ƒ²š[‡ Õ.3|”1k`èp0ÃWTÁV2C·p ÂZ|àq>p½ К6Îwšøš| Ôwuœ\ï^ÇSü‘ÕœC.‘‹0¤Ä7)i"*Xf4=̰U{ÌX Óø†vÚ›@£3Ø3Qm5¤¢=ñ!êTôB GâÃ*1y:ÞÅ|¤¤½ÁÕÙ€M|X1M~ÔÄÇŒ¥ä×øðW»Ìh%ÎÄ7”ÓÞt€M|ØQi¹Tb†î\ƒ‹AûH›a™‘FU˜‘ªc”½“PõÓ™úñõ7†tÚ›@£‰Û=Tnf¦æ 4.“˜‡tÚ›@£‰’ŽA’ø†hÚ›@£‰*‰KÅH½}¼8Mâio:@&>Ì}»Ó‡ `Úio:@á_ÕÂŒ%ñA¦7 ã|¨‰™ÜÄÇ J|н“Ì8ŽHc†%>fôÄÇ J|:"ñ1ëë3CÓD 3Á1C1UªÝK|D¤½A°?+@ͽۂP-îþ:Œ’‚ŸÎHÅ'·|Ûò‘ña囋Ëòqćⳙ*ªòå‰4">_Cº‡ãƒaΫ'eðøß•½÷Ëåu„¿ÚÅøš¨˜øŒ%¾l|‰/ [âC.ùÀ Õ-–ÄGj4q µŒÂ’øˆL{ƒ3õ`æŒm„a Xœ(%˜ýgÿÛAiH hÒ¹;½#ùuÏ}¾ªõ-©©Ò㥋[-–öT5Ešd-åj¹è‹ãšá»ë|ØX°«HßÁ‡œ›l6eäÚMQåH[•{|±Wð9ýÈà#’Ž–x¼ß`„?‘̳÷KúN˜9s€ S¢›s¹Çéaqàì îaÐ VÌûŒžÌI5.OµTdOPü|áÛž &Ÿž»b¯®ªð¬à _TUµØ„.oÈ»b Úº æì¦ó±c/ð1¥OÄ•>â©ÎÇÁ4ûн?Ò·ÞU-B°å¬HÇCÂŽ¨BœL 9\òxU ŽÄ‡XÎÇìK|˜%¤ôƒ.ef†•|̰¤àc†$>´j)ñ1#ª]hÉEàtH­bc:òº)fÄr(”…VHK[à+W`rHÓ#ð¹|“k$¥½A˜úˆpâ·ùð$>xÉGLâ›YÎg =! _â„'ñÛ|x¼äƒ¶ù˜13ò$,bÝÊ4.ÒB+´…UÓÑV\a.h!œøˆM{ƒ/õ`æ r€` x˜çzï")ZJpríyÒÕdìÞçCzÒ:|XøT첄/v|E«r6Ÿ‰Ý€ªHC:Ò$vàË“úæëðq ßÃÁATJTóñŒYà),k\ÍÕþVá–½ß>C%„w=ŸÒ>"Vf…ŒšA6Á–óô3l!=3ôXfpâCîp –ó1C0R‡z0© b÷®,´ÃáAÎd††Þá@ŒóR^=„ ©yaã|°6„É á2S<ÈŒ²âŽy‘‰[ª›Žj îÄGd{rîüàJ|4:ÃA•ÄÇŒ}mÄŸ¶ÅZßÂëo|‰ˆ´Mw0¨@&>,÷í’:« ïp ÖMÁ—Z!¯«BV€d3Òú)DGÑI!?í1Þ„4šø(L|8¿ÍüàNw`@£‰:ëù$ñáº`c¤;0 ÑÄGîJæO|ØÒJº3ä> ÑÄ7´RÚ2žÄwˆ®ãI|ׯ£&¾ë×A)HR!ñ]¿N^â»NÇ Dƒ!ñAÓÞÐKw`@¸(í áK|Mh‰ÏœøÊˆK|×ñ%¾ë D^Éw}€–Ñ\Úšé gâ§=¼Õîu´j–ö¨Rò RžølÁ€ìÄÇ<øjÇ<äò@jÎØ@‚b(Š(% ±ûDlöbÎv PPQ ,ûe%íÉßý|î¹Mz瘆éVølqÓ•›®˜UÀÇê’3{h)ˆ±'4cÜ¡ÒLSü›åVø¤èHç[¦#° 2Ò¥™!Ï,8áÛÒ¥|õa°FÒÛ¬–oỼî‡Ç{€š;¶†¡ Z ”,CÇ,€ÄT DØì ‰aðáD˜zgƒ§Kç|5~N0¹¿dò•òAÐðI”ºnòlèž(Ÿæ|¥|ÈãvAô&ÿrkùœ{Z˜1®Åµ×–=AZð…òí}}ðöÂ/ÿòÜmóG{ù@8ßuHªW¼ ÄÇÊ M|×YAi‚Á‰O’øÀÕîuHµ{XíBÒž›=$õÒ^ÊuPµ{‘ø@’ø€(, ‚ÐeÃ’ìœ PâãE$>PòU»×‘±É_âšQ:t@áJ|B˜‰Qé^‡uv¯C ¿ëHõ.4ñ*]P›šúÀ•.¨ÍwQò¡'¾ëàzkâW½ÁðÔ;$ Qé‚Ú|ס“ßt´ÔIn(ɘiZò!¦Ìwñ"m0¤eö¸ìª‰ €ð$>¤Z—Vò PÒƒT¼Ä®xAiÏå:"íJ>`Ñjð’ßuPɬv¯C,í¹ÃÒž´àC¤=AXÚ“…{ $>šøÀiÜÛ’Àj÷:$ñÕÃK¾›7§c~¸’­b–íÀ*f´«˜©°Ì~èÏ„?ñAúH+¤è’TìÐupã”úÀ‰oÜáp‡w8 ‰ÔçaAhŸ‘ø®CúÙˆþä€4^èUý PâÓÀ,û éµò…Ô½øo—¤¨à›ŽûÄ3ff,G⎘”D ñ! µ@›|ƒh†ã:/ôlHøPËõ Dâ[yó&öº)á¡&?f ŸÉgâé-K€ÂÝá¸.„™øX]âËBN|×+ŸðnŒº=%¢$?¨(Ζª]fffô…}T»C>ÑΡ–ës»×!õî šÛ…_Aïp &>îéX ?Ìä‡Ö ¤fœ¢œ£ÙJÄŒ|3ùéšy˜4<ÀŸ‰ÔKwÄ$¿ÁÛãª ážøf’R)E3óHœã †aé+‚‰Ï–˜´Jná…ÔAeFº@ ù®!ÄÝC#xÁ*@ÈÄG\ÒCK|D¦’ÑÕÏÄ€‰Ø¤7ÀŽh&>|«¬BC)J|£¥I €FbâÃ=ÑŠ+ñ1¦<€™‰ï>1I‘øFÛq´4Bßý›„“<ñuãýhR"ÐHìp€ZË/4gâcMz442ßÍûh‹¬Bq'>æÑ¤G+@Ã5ñMÇŸøn¢¬± Å“øF“Í@ Û’o:1‰œþBCq'¾Ñ”EK@Ã5ñ™ÞœN\â Å¥½ÑR2@Ã3ñSßÍ›'¾Q@S@Ã4ñMg~Çh˜øFK=Š@1 [Ÿû³ÓGK¾A hø&>PáJ~´H|£¥U@1 gÏAJ£zâígP ÐðL|°gÐÂï&FâûþìÄ7šô¨h8&>fØÆG RøMG™Û‹~'/ñ&=*€†‰˜´B¡›¾ASÐSJ§#-,‰~‡~£Ž4ì°´C¬U†ÌÞÂ’ê’ª›7­HL|£¥•@1 ¿´g .øn"/—Gé^€ßt¸àhÉ7p €†]Òƒ|ÐÔ7žüLo"¯çƒÕÈÄ&¾ÑRú €†fâ» ­'-”½B(%ßýË7¡Éo´ä8@C*ñÝÅ @§*‡Þ …Ö¹äg‹–üPHš˜Ä‡¼GˆÞD{; p€"‰¯…Maˆ´‡¨{o¢¥Áû÷C‰çcFªx™‰=6y´®& ˆa8$;€Ÿ'j /ÿÃ.ˆ*©äßøÐÊ4f<©i4í‘h0'¾hR4ù…ÂÒ J‰Ç|Ú„v8%>Œê¥öeF>Jžå„ ä3èaW ]‚…ÊÑ €†MÊC$¿›•ñˆ¦´ð‹f&µhf¢Îòã fØUÌÈ|fÄ͈k7óh¹8}:@ ÊÄ·“À<¹‡z6D‰o:Žîò=BÌÈ× 1#ÕËÐ;Ö¦£_;„‘ðF|ê †a•ò © ÚÅ… ¹@ ÁPhò#"ñá.ö ?ø}.ÓQ΢BT³ð"Q+CTþ4È5¤î½i‹­éÇÌC0ñaOÌðćš°à"H5033ju W‡|ÖhÅ; €†]Ò'¿›°¦ôPªPĸ ć«DbFôyH"ˆŽ3ô oø°àh; Á“øø© @M?`ʺ és@¬îÅ“øF‡†é ˆaX&=Xò³…®@ë^OÈ0óýûqXßhÒ£+ †ašô@y”ï&´ðƒ&?¬‰”bG“@ †Ä'F+À|yR :ìâé‰±È À€x4MÐ Ã0N{ Ô4i¦^÷z2‡Š1£&>$=£‰‚^ €†sÒƒ'?ÈòRxǃ9ô¸\D$>X±7šüè h€Ÿ#ô(4p …t@…™𸀬#4ñðO{ ä)ön‚–»€Š=PÒcË€f{!) †÷èFjâ M|ôðº7ÔöA(XE£‰ö €FFâ ¼92ÆŠ‘ö˜™±%>ãÑÄGs@™ø´é @É9ÄbfFˆBÙ̘êG­@1Œ”´J~¡¡h"ðdˆ%ñARßhâ£! †‘“ö0Ó3R*ííÒÐÀ%>éÌ  –|´Ä0ÂÒ¡$‰žúÐ÷p í'"ªÄb½8 7 ‘•ø`iŒ™™ŒÄ‡ºöØ…ð£‰7 Ñ’¼ÄÇŒwùhâ# ÃÈI{Ìxþćºü±–±Zžù²zøŠfØî!”=—ÈjFxâ ‘Sò1ã¨qñ%>cDA‡ºW’}û$b›8|ý<ª D2DV3²@˜ÄÇŒ'é.ùPJ¢CìaCÛ¤‹¦y›%ÚÆÝ‘šøh„$>H¢Ã•ô$>fô’^á2#ÆÀ–ìËÄÑć hdŒó1“¥À©äcFÌÌ̘-9ØéÌÌÈ>ävJ›µÑ7R@ˆfhX§=æ×Œ ž ÄL•>ìHM|4’ævIL|Æxg8Žó‘0k6R@ ÿU-ÌÌ(ËXˆN|Æøßt*ÎÉŽÔÄ@#e=¡Õ¦˜ëùŒGWµÐÐÀ.£§Cªbf&+ñAÓÞhâ£% a¾‡ƒ™™HuèÆ£+™ih ·NФ‡‘ø`åÞhâ£) á¼o—™\¥ˆ´7šøh h˜ŸX@NâCJz£‰¦ €ÅAAƒ)ñ¡$½ÑÄGS@Ãù”*RÎSƒ1ÐÒÞhâ£% Ár>Ÿñ`H|ÆèIo4ñÑÐà9™Ôx –¤‡2‹F»‹]Fjâ Au&³1Ï@f¬)o´ä£- Avý%?cfìIo4ñÑÐà»‡ÃØx']¨Ì3fÐt1R@ ʈè–þÀ ðÊ©ÑÄG@ƒöî5cãhc¤vÞèqh0ß: J4Lw¸šy£€^ €ý}»àTÒB5`<šî ¡qÓ¸1’ ñhºl €†[áÉÇø.ÑÀŒF÷àÄ0mLåA ˆa8xb4± M@ £A0  Ðhâh4ñ‚4šøFÁ€€M|£`À@&¾Q0` ÀU¸;ÜuPIIEND®B`‚procmail-lib-2009.1202/doc/article/pic/cr-system-authentication.png000066400000000000000000000263051130547513300250270ustar00rootroot00000000000000‰PNG  IHDR_©„B£¶gAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<•PLTEÿÿÿÌ™êѺحžê÷Ö33Ì€€€ïïïÌÿÌþÿþÍÿÍýÿýûÿûüÿüÿÏÿÏÎÿÎîÿîÓÿÓ÷ÿ÷ßÿßâÿâéÿéïÿïóÿóáÿáÖÿÖøÿøæÿæÔÿÔäÿäÝÿÝñÿñçÿçmmmòÿòôÿôÜÿÜúÿúõÿõ===ØÿØÛÿÛ‘‘‘fff333ìÿìëÿëÕÿÕùÿùÙÿÙöÿöÐÿÐÑÿÑÒÿÒòüÝÖ›„™™™uuuIII:::TTT‰‰‰^^^wwwOOOVVVåÓ¿BBBØØØîîîåååèèèxxx%%%GI &&&ììì@@@qqqãããßßß666òòòÜÜÜÔÔÔ‡‡‡[[[¶¶¶§§§```222ÚÚÚMMMÐÐÐëëëÁÁÁÄÄÄQQQˆˆˆÓÓÓ³³³***»»»ÎÎÎ"""ÝÝÝ///rrr...###………111ÏÏÏ«««eeeƒƒƒÑÑÑjjjííí×××àààáááCCCNïè6*¶IDATxÚb`£€v €FÑ( % Q4 h hZ€E£€– €FÑ( % Q4 h hZ€E£€– €FÑ( % Q4 h hZ€E£€– €FÑ( % Q4 h ˆÎˆ‘‘9|Іº'i ™ ëˆ×Bi\@ Ÿ:TU,†[OWÓQ3YÖÑ/}}²2<’é[~Á ¢s þò‹~ €èÒš¾è]‚ÑE3#Ù:¨«/ ºô€¦/ú&°Ñô…D·pM_TÖLzp‘à.ª…@Ñ/œGÓU53’\Œ¤´ê©^D¿`F¤/d×3b '$#J]#.¾ô…¢Ìd„«Ài$šíHÚ°ÙŒÕ(ÂzÁJH¡§ôpgÄè†2bS‰ut­ÙŠl ª"´l‹ÎŒHQ€”°1Z¨IÓ2lzq…S J)d+ÁPÃbâIÛÄ–`Dÿò 3P ¥/Fœa‹M%ZjF«‚°˜‰‘¹1ûfØŠ"Fœ6£…51cêÅÞš".}¡5´wÀT‰=üñ€Øô…5PŒ„ÓÎzì6$3qÔ¥è1«ÝÝf¬-oŒê»ÿð…1鋘Pà qÜý|, 6’Ò@ |úÂltbÊÀŸ¾ðºÅ.ìmg’ÒZÓŠ˜Ž0–Ù/ìþÃb$–ö¾ôE8Ôð¤/Œf=¥é €8}1"Å& é kýŠZ.à(3pÅ)é K4àM_Œ(Fb׋+}a Z¥/$»¨–¾ˆÎã@$´¿ˆH_Xƒ ³sw¨kéI(}¡·oð¦/l}bÓÉí/ Ò¾öÙé €è˜¾p6p¶¿pjDbDm¾ãhhcW‰­F œ¾à#XlÆÝûÇ­—‘ˆ–)‘í/BÁ%ã1â¬(M_D¿lÜ '\ýG<é‹GA¨!„j&öèÂb"jb+.q:5Þpé¥Vúb '}1L_8‚‡pú º5Áðh´{³…ÂÄh•⮨pš‰¯Ë€o|‚—Íx<‰[/#¶ñUôbDo¿1âì|àò#¶ìî$<¶K8}ªH4|¦GžÁœ§À>"c!Žþ#J\¢¯âo×cцa3£±ŒÐ¢é…²1FMн‰"èiˆÎþù‹¯á$`'ÕÄQ@Bسãzš5@Ñ;óàL^ß³S#KŽbÃ)è‰H>ä5@ÑчðâAƒ3¼Ü‚ÕL•fGJuìЋÄh""ìÙáA‡Lô gGM”5@ѱtF.¤`Žfg‡W‹o"%2vhã" ì Ø$FkIâÃ-üу)±S'¨ˆþå’áå2’'Ñ1ÌÓˆ–šÄhùEZØ#S(A¨BáNyPÛ(e<}Á)¬þBò3‰Ñö‰aš¾‚{ú¢0¨h “¼ß‚^|¡×¢ð¶‰Ñ´Cb™ÂV="BœA @ô÷$;lÐ…)}!Jg”æ'¼¤ƒ7>Ñ%Fiµ$zóôì(õ;•‚ €Qós4½Ð¥†=èie)@ ¦îóheGÓ0fÇÓò§™½4hjMöÑÒ‹æ­/œAO;{hZ€E£€– €FÑ( % Q4 h hQPwarGrØÐ(¢$a—¾I=)l€ET(±ˆR=2C €Fé‹l#'¤h‘–:P*Fš—|CÐ(ˆ’åL”a h d½6 e3ÐÉ2€E¤•8C;…±2#ôǬ BšÔM{4ŠEþH»L(wúBI`šHIŠV) €FÑài‰SbQÉ ˜¾ˆMaÔò6@ 3Dd>¦ulÓ=E[~1 %0HŠBIa0@ÏÃhÈæ.5i[~±²2`a4KaDDÓî ¥ÉkM‘ä¢Û_¬v˜%$i¡Ö’J’ò  º":t_(I`ƒkèÍ5ŒT*¿ìXY±W’Hi 5…1R'DßôEóî Eå×`W'a å—ƒ®2F%‰žØPR3%5@Ñ9}ѼûBVÄÕÊ… Ô)¿t•°a˜) ­IFV(}ÓÍ»/¤'¯¡2ˆß™¤•_Ž.:,B(NaD÷ò‹ÆÝãPJ^Ä&0bÒ—+‘)ŒÂ8 z§/w_ÈH^C£kD ïArùe¥cÏJ0‰aK`$†@Ñ=}ѸûBlcì /ìé‹‘jå—Ž½µ2ž†¾¥%UR@Ñ?}Ñ´ûBTòŠ °ñ'0rÊ/ke]gle˜%à+ÃHp7@ Dú¢e÷…P@Õõ}ŒTí?ÂÓ—“ ¤QÌ–SiC4 é‹vÝ‚ù˜Fi‹€C–ÜòËÉÆÍKúŸ¼XHp@ Pú¢Y÷…Šܤ$¯N_ä—_n¶zzhé‹@êb!%}Ð@¥/u_*y åò -}L]$¥/€¸ôE›îË@$0`êT Œ¢ôE8u‘”¾h Ó º/R~ ‚ôE­ò‹™˜äEJú M_Ôï¾ @¥­áQ~—ºHJ_4Ðé‹ÊÝ—«‡AùElê")}ÐÀ§/êv_èŸÀø!`è—_øÆ¼YXÈL_4èÒeÝ—I^ âý…§7ÏBvú Á–¾(í¾Ð=ARÖ ª ÉO_Ĥ.’Ò@ ®ôE^÷… ¸A€I€Ð”ÉŒÉ\XXXNÎÐPZZKËØX[[MMAATTTJJLL^^VVII\ÜÀ@__HHHBBQQEERRUUCÃÄDDDDFÆÈH]ø€€¸À×Ðê§/*•_¬„SIé €Sú"·û‚”¾P’Ò,] ƒòËœ¾ÐZa,,”¥/€<é‹üî FùÅÈI`ŒŒÐôÅÎÎN|úbcÚ¾ØØqú¢Fùå *ÀІ¼Y(M_4xÒùÝXúb„—_ŒÐò 𾨵´HH_&ØÓÖô5X±åþôÅŠ2âÍÂBqú A”¾Èî¾@Ó##¼ý-¿Ò–ú‘Wù­Ù€é‹ ©ü¦.6xúb¼É ùÅ@LúÇ Ò@ ªôEf÷’¾å4y11BÚ_ìÒd¥/uÌôÅ5XÓÑå—7+qé‹……*é uwˆ Q”AB‚«Ásî3þNhÑ¿xiZµßòõìûró/iU=ð¥#¾jÿ ¾hùb\¾$õN†/;¾ìòe{ãì /æ<l%ÿ»¿¬µ}hð¤/ò»/Ðä)¿¡Í{FpóV~Û÷ìjììÀò‹^~12Ë/FhùŦ"ɦª I_"lˆú˜ÄxØõ#¤ìšå#¸‹¤[ú A•¾Èì¾ ¥/`²'1 6U ôÅ. L_Æô¥€H_ŒJJŒâXÒ¨‚¦/6`ýÈlßK0Pú‚$/.hÂÌÉ‹‰`$°20Ð+}ÓMº/àäÀ$ž€$/sDúb·¿ØÙPÒ£8júbc&/ 6pò‚§/6PýȃH_¤5ØÒ)³ŒFŸô@ô.¿hÑ}§/Èø#°ÏÈ `DK_ âK”¼PÒ#¬}ÏÆ& I_&¨é T?"§¯A_=2À˜ Kú :§/št_ÀÉ š¾ É T~ipúb7„¤/vHú‚µïeAí{F”ôŦ L^&àö0±¸L^ ö=2@Z`C³ý[<-ÂX1"ÀÃÊé €èžÀ¨ß}׎ ñ/F&0`’‘˜Àaé Ø¾gO°ƒøÐôjøðñ Hû ’¾€å°û¨ÎnAªG`ÙÁàâkH–_Œ°å™@¤c@éÀ»‚SuÓ@ÑѤû‚þ‘¶óÛC§ü¦)èsP zÒ30…y@‹0*¥/€ˆ6µ»/xÖO°“×HH_„Ë/`™…˜â…tÑa) y€T†…Q1}ЀaTî¾à)¿ØÙå GË/hÝ.¾X‘ 7(}1€Ó@ TFÍîË€®ÿå¸åMXÐÆOaÞ¬È(ÀªÓ•Šé €èŠhÔ}a¤äYòB¯')”µP(å—…+¤F­ô@ô¬iÕ}aÄÌŒÔ]Í8„’Fö&,VhåIaÌh) %}RµÒ@ѱð¢Y÷…K@3RwýýP.¿ ‰‘¼•$+Z2³°`¡òø@ѱð¢Y÷e´ü"X~AjGfx)†È숺©ü¤8 €èX7Ò¬û2Z~hAS ,™¡”[Œ¬Ð¦´}O(}‘æ.€¢_Ë‹vÝ—Ñò‹ˆcõ µ!x£¬k¯0ƒÜé"œ¾Hu@Ñ©ÛHÓîËhÿ‘ˆñ{Fäö æĤ/ÒÝ@t(¼hÞ}-¿ˆšd„¶èY`R”±@Sé‹ ‡½J/Zv_p·¿0 r‹¢¡_~Á+IVflÍ0FÂé‹,w}Ê/Úv_p–_Œè ƒJ0ŽÄò \FÁ27t¿) "·H_d: €èÒ¼§q÷gùň©T~1¿ôEüú{pæf…Ô%«$ñDÙî :–a4ë¾à*¿Àu!¤B„0¡\IÂ+J¸*8¾å¼¡ÏÓÐÌni¢XXøaò@t+ÃhØ}ÁW~œ„§0¨œIw`4¬Ë/@®>X¡E4…aM_”¸ €è<F“î ¡ö¡ô…¤ WÛl•_°f¼[ÍìVVCÞTH]D÷J’ÝÒÊ/F¤kؤ/RO=7Ã`Ýyx%iÅi§ E¥î úa´é¾Òþ‚Þkk1¢´¿p7À†Wù…ÔÐGÔ) 8`±„Ö$° Øa4Í0ªw_ˆžd$;± ·ò Ü c€åqhAÆN^ÐF¥Ô@ÓЧn÷…øñ{FrÓÊð+¿  }Vðä ¨a„¥.H £Rê @Tï¾°~bDßã©$Y˜-i“žhÀšaT쾌Î?’¬1+¤}B«â €°FµîËèú/ NÍ¥0Fš¥.€à†>Uº/£åeDzӲ­@Ø £Z÷e´übk ‰4À }ªt_F˯º÷’@ƒ£’¤¬û2Z~ Þò €A%Iq÷e´ü¼å@ Šf…Ý—Ñòkð–_4Ê0J»/£å×à-¿hx4ãp”_ŒHÒŒÃ:} Úä@Ã,}–_ƒ,а.¿FÛ_h´ü-¿h h´ü-¿h hX¤¯Ñómù@à Ԁ¬¾ Ñä5êoZ€ èÑò‹– €F“ר¿i h4 GË/Z€M^£þ¦% Ñ€-¿h h4yú›– €Fz´ü¢% Ñä5êoZ€ èÑò‹– €F“ר¿i h4 GË/Z€M^£þ¦% Ñ€-¿h h4yú›– €Fz´ü¢% Ñä5êoZ€ èÑò‹– €F“ר¿i h4 GË/Z€M^£þ¦% Ñ€¦1à‘[~Ðhò¢Gú¢y ´å@–_4O_D6BË/€M^ôH_ ´N_ƒ¶ü W~q`C=} Úä@#®üôÅ?bË/€-¿hž¾èÒƒ¬É €FË/ú¤¯‘Z~ÐhùE§öØ`4Z~Ñ%}Ѻ?hË/€-¿èÔ¾¡å@Èò+ %.« [ú_ÁE#V&îëàGÛ_0@#±ü ‰‰v/ òÂL_›à±$/FlLœ·Ác¦/ºú{0€åWj;DUxBJú¢vù5Xü=@ €F`ùQ L`þA>`ŽT?"Ѱ QgBªO¸(<}!+‡žLïkò X~¥Wg—J°"_0¨ˆ­õä@­ÿ!©…–€¥’( ‚*G¤:ÆÑò h–_ù¾%QÀ䕚ؚ\š„Òd„”A Èjõ -§É¡œÙ„Ñò‹ €F`ùå¥ *½Ê3kŠ=<šZÃ1Ú_ˆä„3}¡!$ FFú·Êmù@#±ÿÑè_™Sß‚¥ÿˆžx¢~dÀ^?"•_Ñð¬É €Fâø—gHn|Z0¶ñ FDãܘ‡6Õ‘Æ#࢈«=”Ã.ûÀêqP%0€‰å(‰ÑjüçÇ-¿h$–_´œ ô5hË/€¡åíæè2¬Áš¼h´ü¢ñüö/¿h´üékÐ&/€-¿FË/Z€qå×ð÷`4š¼FýMK@£=Z~ÑÐHM^Œ£ÙŠ. €Ffù5ø/l.å@Ôä5Z~ÑÐ,¿‡4bå@¸äE žFË/ꀱå×hû‹. €FÛ_£å-@Ìþ#ÃhùE'@ £ùxÔß44Уå-@&¯QÓÐh@–_´4š¼FýMK@£=Z~ÑÐhòõ7-@ôhùEK@£ÉkÔß´4Уå-@&¯QÓÐh@–_´4š¼FýMK@£=Z~ÑÐhòõ7-@ôhùEK@£ÉkÔß´D?žÃ&°Áåk€¢MŠB¤&B)n4y oMJ+R ·Ñ€¶å@Q±Ì¢$¡P« M^ƒÌßDµúp3šÀ—¯ˆJ%5“êhòFþ Á”¶ÈnÄ&°Aëk€äÒI@0@ѵ1t¢-JC5,¨¡î3ål$Þ þâï­W‹ýj/ï\R'qöÝÚã€V•1œÃºŽ£Ru1fŒ!ÊRÊ,›çiäyÓ´-¥]§õ¶!„ŠbYú>rb'¼ø·§§”ik4 ›ô@ƒ5u‘iÏhù5ÈÒ@ âÔEVs´ü\é €uê"ÝÂÑòk¥/€¢W¿n´£>¸Ò##JúbdÔ0ad¤Aú aÖU¹å#‰åjúR¦/Z¤/€ÄãhùEBúb$˜¾QË/Ôú‘X?2Ò¢~ !T†&/Üé‹Qp¦/€6 ¯‘]~ÁÒ°¿ J_@ ”¾€”1#£6##0}Ùôd€Ó¦/FFFäôUgdäRÀô^AL\LÚЪ »c„–_Œö#£©)0}12 Ó#£´£10©©1ÂË/FFY%hú¦/FEEF¤ôÅÈ(cĨ®L_¼ŒÀÔ,½y¸@IŒì@C¬ðM`xÓ¤~d„ԌҠô,¿Àé‹Ò¾g„ÔŒ ö=0…ëGF`ýȨª¡ÁhL_2 ôJ^ ôÅM_\¤/€jíz®™å¸&/púb„´¿Aõ£–1£6rúb„¶¿í/PòBM_Œ úÑT?“8}‹0Péň³ýÅxÜ@C¯å5šÀ0Ód|-}êGHú·¿PÓ—,}1"§/PýL_¼àôj~J0p _ò—¾hpTžŒÔR<"Ë/FnDúb„¤/Fpù%ͬ µµýGFHû ”¾•€ÉË”¼Áí{`òb&/FPù%ì y!í/Hÿ\=ráL^ ˆÌ¨$|!Îhÿ‘^é  ñ/FpïÜþ6ðAí/`õ¨Š!Ðø#¬ýÅȨM_ Æ.¿å#¸ý¬!é‹Ò{O€ 0\鋈‚„Á’¾G“qóCŒdÏ?2‚Æ¿€) ÏøÉ €(¨µcûltþ%}1S–¾x(M_DA£–¾ U$¤¦„ðµ&^Q„œ ßK¨âeM^D¤/Ð+Ùë'!$îôELò ŠÓt_,©02 ïiÄ)ŠªƒÎE¢Fåõ#-×瓾ˆ‚.rb@Þ¯ÚìÇed@â32 ', vRŽ–_ƒ,}#¨é IŒµŸ‰M”Cjú"fT—q´üé o2 ¤ˆH_È’Œhzñ§/â ÐÑòkàÒ?œÄˆ‚ñNŒô…œ’±¦/Ìö–ôÅið32Œ&0rÒ#|üœ¾ØÙIL_llØÒöFhø €((¾àý%}±+ÀÒÒþ!F!”ôÅÆ&Âl±Û_ÀäM_àú¹yÏFbú *Ç2#Ée#•KK:–_ŒŒŒ(³¥Œð4ÀÊaDöC„+Áf¡ÉXlëW¡é‹)}±«Ò;ÖôÅmß³±™@Ó—Jú§.äî#‰Õ#@Q'¾#[äêĈ:¢Â8p弌b ˆô…ÊaÀ:;˜¼E\ÆœŒÅÑ‘À²~˜¼Àé ²?M˜¼ŒAí{vpû^ ˜¼äû;@é‹9}+H`ò2·¿Ø€í/PòöÁ-0`û !ˆø@T*OÉÒ͈§UÂHVú¢sû ÙŒŒä¦/´ò ÙlF|çk£¯_-_bðúUFhûž<~$Áå"}Û_ŒŒðñ Hû š¾@Í/p÷Þ{waGRzDçú‘˜ôÅHAB§sû ­~d@®‘¬pcıF‰ B¢e$8~?HÏÏ òBcÕ #r" oË"‚ ižˆm}"Å-2zŽ1`¬‡DnßÃfÎàU=zûY êý&(â „Û÷ƒ8}¹!‹¶j£Ñ€¼n)'"ڮȽ/”šƒäôÅ8xÆïi`#1㫃6}9!„eUJRCn¢¢î˜) U¥ék€ØhúBDƒô…ÙüE”ï¸Ó6'73xÊ/ªïÖÃ?5Ò@Ñ%}¡´ÿ‰M_ŒC°ü¢iÚ%ºÝ9˜@‘SÀ#5™p¤/F,Ý+¬é‹sÝ*I3/莾ë'ðeƒÖßDVúbÀ\KȈÚqBîa,7„ Ë£l !­¢aåÞP¬¾ òÒ× u4ÁäÅ8ÔÁ ð ñq@Ã,} ÷ò‹‘3ŠRˆœæý`;ÓdÄ´¿‰ó÷`J_4Üа.¿ˆ,·Sú Ñä5tÇ'†Bù@Ã!äGF#¾Ý9˜Ò@ ƒ¤É8B“×è?Ð`J_Ô°{´ü\å@QqFÛ_ƒ´ßŒuÅ>âô"ÊcŽˆ )p#}0ÚþÂR~1âŠ1F*$  òôªô5Z~aé?b•l 5Ó@Q#}1¢Ï#22¢¯leDQ /¬Ñ×DZÊH^I>Z~1!/"f„oÜ…®Ü†¯¨eDÈ¡7ƒ,Hqú z.Èys):¶ó/Ñ‹hF´Ã5ð¬L$ί£å¢ü‚Ÿ|ň¶Æ~â-<Á37""¨“¾ˆlŸ1¢Ù†šp°­cÅÔõÐU,:ˆ/oGË/&´£Ô0öXâ,Ð÷›P!}yºQ£^×Á9Ø×"õcˆI_DmQÁÉ‹pù…¼e—mÃÒ@‘§½xA¹j_úb$¾üb çŒÌÑò‹ 9ŸÃÜ!6‘cœˆE€PŒ„ô@ä§/ô5©È']bY˜Šž¢à€#}×ÙÑç‘0ÿÈH•„AFú òFP®@@9viÃÆ:V¤®#–Ë·Û}Ñd’2~ÏHÅäEŠ9DEýŒƒÀ¡£å®õÔœq!Á €¢žŒôwè??z(Ì?µL +sPs´üdë¿h¸¡Ñòkp•_4L‚w´ü¤å@ ·D:Z~ ®ò €†Ué5Z~ ºò €] ¡Póhù5¸Ê/€¢ª1h—<°±á;ˆÑw+£Î™‹£å× +¿ˆªæ°aá²4¢Œ:-¿Wù@ÔDè…qé‹ kÚM^–_èÇPú j…?}¡Ôʈ–¾¨ä¦Ñòkp•_DØ,Fâ“ZbAi¡\:€´`„äôÅ8š¼†Pû €¨hfúBO>Ø®A&5}1Ž6ð‡Rù@T,Â0º‹¨—!a»™‚ôô5š¼†Vù@Ô3ój-Få•î„Qå×8 €¨Ù{Äš¾Øp¤/F”uÒúˆ*¿†‚¿ˆZEìjD%‰6¾ OûðwhzGšJþL €hW’æãQ30 ÚuléŽÑ6¸| @Ã,¡&¯Aæo€¢Õ`ÅH`Dv†IP;P“sƒ5yYÝâÁ›ÀHÌÇDíÚbD½ósP†Î -¿ˆÜ—á‘ÀˆÛHÚ$ñhù… ˆ¶M}º»€Üò‹ù„ìñŒh;ˆQ/ EìFÒˆ²iË=â|´£‘·õ£\\:dË/€ºõ$5HÃ/ˆE\˜ŠÌA™ˆgD>ó¢c´;’1LA:ðq«-#6ý(Ç%{"Ü`M^4Ó%ä—_Œ(Gü`™ÈB;é 3Ì«±šÂˆ’‚çè1 ž?€$2(mù@ƒ-12RåÔQc›5ö1Òöò‹[úB;¯9ýb؈HaÈSgŒ¤ï`M^4à%ÎtÊHN#³ü›¾P“<áúKúBmÁ¡ÕŒXëGÒêÇA[~u Æ/ÉÿBY€u¢Ywûõ€-F¤ÓƒÑÏàb@m£:éôTÒ+ÈÁhÀ«K¼e#©çLÒ|LÚéHdœ¥4hË/€¢]…‰g¼)㎌Nhž¾mò º„-RuÁHÆÉ<ŒC?“æqÒƒiЖ_4ô«\ÆÑ€Äå@ ƒFãhò¼þ aR“ÐlD/œ…«b/¶ÅاÎFŠD„"ŽO¬É €†j:Â!ARò‚¤¢¢‘¼°%RÌ %!³Ø†fù@ãž$#±1`Ù±I ¢ÙPµ°Ñ1yÒ?X“@ ³¢ø|Œ”¾Àµ$ƒ«"èNh½„FJR`Y¸8T5’b3Ù`{Zì€kb@ÖÆÆg Íò €†[o’Ø€†ÚƒH6ˆôƆÁF©(Ù Gn@Ò$²6¤VbÜL64ÝHŠŒÉ6¤Ë/€¢µ$ÅÇ˱¡È…¼c@MˆXFRÊ€ÄdC­tQDÐÌdC/˜ÐDÙûDl´å@ ŸBŒ‘äò‹ ¥,‚•lØ -6”¤Â†Q‚1`a$Ot„™D±G\ñ5h“@ ³Þ$)å¬ao<±±!ÊxÑ—†Uz–¬%/hØP3À«B6DeÉÆ†* ÓMfÌhªÇA•Àh¸µÄHjQ°‘¬šªÆÖä@ìD#­ÿHÅäEbú"ñD’’× J`4ܪÉÑ ¢Áåk€fÕähòdþ aÖcM`ƒË×4|Ê0pcbM^ƒÊß4Ü ±Ñ6¸| @ÀF˯4 š˜Æ8ä®#àâÁš¼h&/FFBÍÈ8ÓãPn#ÃÔ»$yH æ]±A|¥kØÜKwgóYOe#opNPºh‘Ü£2÷õìO¯ÏµlP)T~§úI·éέÃôïÕÓÜdná·.†(;Å\ƒâ2òBBy´Xª¼P)JP)JP)JP)JP)JP)JP)JP)JP)JPGçrRtöO-àøÞÃi-Ï…Ë>[Žôu½kz5Gú†âë¢åêL×¶dó—r\\\<`>˜• ª8`¼ôøß2ØØs8kì]ÃH°^ÛÉo#F@`®¥IoGäkŸý_®? uÐ÷æ8sX‰£’M¹¢g.³ e¡/¡ëÛ‰:æó9†³êî"ý9ÚÝÄÑ>€%wè˰@`tA×b®?ôãŒú“èo§q>7ì7vÖÞ/<ø[ȼµ³­ëzÙ®Ù<ðÚÛËqq,pÁ’I*¢²I=€¾ëÿÂëÛ¾Œq—"ÞxLªIÓƒñðæÑ+ê»::a½À 'Q})·Kå1͕錕¯OÞ¿‡õ¬Ì £w ˜Wl´tü_\¼›R*Á×=gcн5&bú9&%Ä6ð'c4¤zÒ)$Ÿ@:‡ÿïø¼Çÿ…cþŠZœúUê|n08›üv6éò·ª‰6R–ÖÑU•^WRFÈY;w^Ä’ÃZ!¹u×·˜.­Ä`ú— ”y}ÇgygznPÌ@”ÆŒ¾òù´G™~ŠÕþ—ÿãèÇü*¥·¨¤;)qÿHF–÷ÙÙòÙ?¬#iÞn Å|X@+¨¥„š:,u¢ÍÄjSébxnºëè²âÞXæ‚\Ÿ8äƒ+©–Ü‚ìA÷A“þßñyÿ ÇýµÓ3™ÈpVöÎö·wsÝ\-µµµ¤a¤–Fèl…*³b {×3ÿ„wü^cÿ±ÿE-dúg¹¶Ãfú7¨2¸ˆòx[;‹˜.àpŒ •/‘»1‡Ãh#`ÐZ2Ým}Ò×öê|E¥®>úámVöÏ#ã,2±|Q$qqN<ÉaË\;Žâµú»é>Ó¤ú—ƒ|>Jâ[Ûˆâ7X‚±¼2™y!â€ûÚÞûT>G+ôS.Þ|V¦2÷÷¯68ûkkq,ÒÉÙˆl÷.–ôŸÒÿüaýÿ…Oô¶ô‰ô¦ÖýcŒÂæºc%‡´Ë¢ý_wtÊZGn #Æ»àyÈ•Úò bÉÕ}YgÒÖvþ"{NJúQo°G ÷S1('²®ÈÛÃ@<ÿéþ0þŒ§ú[z”ú[¶Jã¦oqsÆýMazfÅcä+Æð©Y$etc Ë`vãêëA!ô‰wê[<w§d[¼‚bøû´–)›l Ì!Æ—°Þù¯Ä€g.ºŽãë18üDóåd´[¹#¸q6¨N€šUæ®@û(}ÍU|×Neºß®zg%w‰ŸŒÀÊ×,nnb3\HHeTXŒ‹ÅZ$Ùf‡:ôÝUò·ý7útÍÛužÆk<ÜV’Y^ÞE©ü>áà¬ÁnÚà O ÖŒÝbÝ'›ÇÇË5¹º¶1],Ð\EØy„~{µ)é;Õ[+ŸâoúòÓé\>îüÅ%Ä÷¸Ø Î ò棻32§;Ót5¸¼·ÑgUds7×¶ÿIÙ›8..$–;hļaVbB L€:ôž‚ƒOþßñyÿ ÇýµtÉý"ôå­”ŒÉZfr ì¸üt¾Ñ,òf Æ åAâvÄh|kŸý¥Æ`ß’¸–öâ8ÀÖ ¬@o …&g^Hx >ö·¾Õ–úX»éëü|ÙÞŽÉc:~ùÕcÈÏ*4‘íûHS‘B >RÜ´€H+QKÿñ‡ôcþ?ÒÛÔçÓtÝ}^Û˜£šò[‹t±Œ¨ic*F=K•æ4½õËẠGRõ,==o%¼—ÙK×1Xc¡ Is&¶{žÊŠ;³žÊ;Ÿ€5ü·Ò ÷Jæqö½S€ŽÓ~ë Y;;ïå,K¤|]±=ûÀéµCÉ.G£zïèË#Šx1x¨qÒÈdS ½ÓDñ¿#ËŠú¡-ñT:åǵãé«í>‹rVqùî®å·‚ÚîóHgBÕ›@ýÇÒ'ÒM¿ÑýœRIˆ¾¾šmÊ!Žwî´Ä€ä( |½ÀÎ},þOäqòäº_+iÓ×’´Zܯ†ÊÀ°ß¢áH‡.,W‘ xèÔþšq³a¾„úcpÑ´öW¶ò4d•,–Ò)#`l|…JÂ;þ/1ÿáXÿ¢–ƒ uSýKy‹ÆZYûn_++GilÒøHUiäÑ⪽ûǰ÷ÓÔwLæSwˆŸqŽŠ‘¤pÉ1“ÄïôgÙŽ‰ÙT©_úGé¬_Wdpx™rSⳫã]bï¢>áŒÄd^<”³U†» €jžõ¢?TôQÇi’ËOÓ’Kc‰×œÑñ1$lä)aÎFÑ}y’H`@tz£5˜Åœ¯OtìwV ŒÖæþôÚKtôѧ†à#q.ÈNö@&C¤º¯Ö}?gd;²4rññ#e:Ó…$­0ô`~5Êþ³¿EùŽ’´‡/‹éË ŒQÁqõŒ0)œ…׊®Àså¢OÄïàOHè;ü>S=ïOáàÆâ$»Z´1$BéWHfà qÛ+( æÒu½”ê<ýKtýæk$Ò KT þòf$…UæXßC¿rz‡ƒª²ðå°xÌÇMIg>UÜ aºÁZBŽüTø»Mq‰!ÛD ޽‡ uÑ—¶½Bd\]ÃÃÒ$ EåEI9 ÅX“±¥;Ðó;,XýuNÙd20uLÝä#±¶3Ki,ˆ#VN[hô¼À Ì¥Cİ ´uGÒVc¦:ËÓÒôÄ}i*Çev2±·)8_cÙ†Ô²ŽZ ;Õ£©³™L<øˆqxˆ22dný—RÞ{?†x4œ½ÆÚ…Éøö OjÿÓFþWô5dzCâdñûº´â»wÐóÆ4¥%ôQ­²¦ý)ôÔŸ—ÒÛu/‡á­žƒ·~Ö„ê,–Râí0xî ³¸{inr-k²!ÓuŒáX2–!FÇ”·}Wþ…§†¢NIeg¸H•˜íãJÚ_™â¬t>Ÿ…Pþ‹¯úßqÓa‡ÁÙgqRË×( a>¤mý« rRxñÙØ‚Fø‡PÂý ÙåðykÓ¾Žÿ)·¾Æ@¢âu˜hEŒžj[’†:‹  ü?Ó½GƒÈ_`zRû!um,¼m"¸MˆS!õFpíÅ9c½,Ów÷™ŸÉ\=¶6ÚT·{û8£.æPK( *—L{ga³Oÿƒü^d?²EÆ?égëþ—>é|®Vù"g¸µxG!^Hf#NÄ6ÕP30ÖÕwÚÉÐÝgc×]5bÆ9!!Ì7?s  WzÓ 0 PFÀ;‡ÿø¼È…dþŠ*ÁÇþ/2áY?¢Šƒ°Uçéúç¤îº«€!…·I\Iq}ìÒÌ‘±"'R|̬t|¾œ¬Ycq“èÜå…œ~%ÕÖ>âS£`£g°Ù#Ö¹ÿÑOÒOÞt5†[+c¿ÆD–®—2¬*è£Q²o7” ü˜ÀØ\?/ð_û?ü´ñ'ú§Âñ5á—.8þÛŸ—׎ûï]ê¿yô¡y„Äà3™ì Ø,¿‡ú®ÖüÎöÞ$|Óœf%'¶÷Äq>§A¡ó]u‹ÅýÜåaéìUÆó!%¦Å ûEfã$ÈÊ5·ŠI8ñA°v¹ôÓb,¾ŽpÆ~¡"ó^«YÁl‘Áj–þ„x1'ª*˜”335¢9CÿÒèÿHý{yôŽ·É}MýŒÒ­¾ý´Å ‡owÃaÇIëË{>Ÿ}#õíçÑþ:ß%õ4ö3J¶ûöÓ‚B½ß ‡'¯-ìú|j§ÿ‰á¹ú9±x%ŽT…BÈÁ€eŽeaÛâGÀ‚+_þùlm×Bâííò“O-ìWQÇÊÌð˜¥@ÙB{rô éGÔÿRÞbñ––~Û—ÊÊÑÚ[4¾@Gy4xª¯~À±ì=õÕS^e38ûü5ÝŒ¸›xf”èÌ'çâlÂnDû>ÇA‰$Rªß]b:é^ŸµµÎû.M¼{¬FRÎU‘‰£¨ÓŽMÜÄìxdìhƒ§ôwÕxžµ½é¯6—׉ŒŽîß)ò@Œ#7Î;_L3æ ƒ¡þá댦vÒ UÝ‚bž$>ÖBÊÌÜÃŒ{…YÖÏèô¨»¥ë{β»éë^™ÎK%¼A€öb“;™GÙ¶¸FUÃø’2hz€HÜ?Ñüaý'…Gô·éïÿT=Yþ üÛZ GEý"~Sg2}?“ÃO…ÎãüòYÉ'Š?(ä(¬>âJ–êC'ÕþTEÓKX2YŸÜ]G%׃¤ 4ŒÏ&,€(RtÛ:&Óßþ¨z³üù¶µ¹sŽŸôásŸéødÌ<ÖBå”O’Ð2¯‚P» Ûø*J’HŸÏ]æéæ:†ó§eéëèröð»DšiÏBU24r“ȯÒ.­ò¶¾Á&F$¶µ²ñÖGŽ5⥥⠆>l³ÉÙ®AÏþ›â‡;ÿöÿÿÑJtÎVÇôQ‚Éäîc¶³·ÃÚ¼²¿¢ ?I$è;’@&ªI=S†êï¡¡¿ÁÞ{]¬rÁ ?„ñéÄÐ’4àFÃQÿIøLì_@x\|óøØø­>²†ŒqÂCòâ|ʯÄl<½À[2]qÔx®Ÿ^¡¹èÉ,8y¢[ÝÞÁo³ö¯‡Äº%’»îF˜‰ÁÖ8·è¸z¦/{¢GŽ(Å™ÝÈUˆ*“¹9šßfìHÑ5¹Šên_¦­ú‚ ˜Ó5¿´%u%ÖØ9…+¢¿bÊ¿š¾Óè·%gžêî[x-¡^ï4†t!}Y´ ÐïØÐVþ™¦[nºú6Ä…#ɳ°Ž6v Kn{*‚XýÀ~1—úTÉô¾RÓòŸ£.ñx[«†…2>ÙåÀºF]Êò'A¸òãU~ºÆÍ†Ìý bî6žÊâ+y2J–FµRFÀ:Øù ¸}7L¿û0½°Q#Ýän-ím!Ž6vš_\ üQ¿ƒ^¤ ‰J‹é¬lØn•Äbî6žÊÊy2J–D HØ[!R” R” R” R” R” R” R” R” R” ‹Ítæ#¨RÊXÇ;Àáà˜’ÀÁ•·ŠC¡Ú¯u#z©JPAÁÒ8xn"ã»»x\I¿¾žícpvVW`®> #gG¹¬}IÑX®ðÆrÖ{¸ãÑX}²hãoMÁ//1µ½oU`¥o/Ð}=ŸÅÚcrö×w¶–®ÏO¸cÈüY¹íÈÙ±: kc%Ò<ÏO®)i%õ‚¸u[«‰e6ÉØ•˜¾û‘¾^„NÕ9J ¼¿G=6:ÆÁúvÄÚØÊ&zó€,GwØUåË|¸Ž[Ь™®ƒéî¡ÊC’Ê[]Ïw‡ÆBá 8÷UÀCåSµdoÖ¬” ­ç:§º–ÞÚß3mwyº*Ç™ Ž>P@béŸLG3¶;îMJ}IŽ|?Õ76þÛb}è¯Ý®¹ù¹FRÅ´{“­ z ¥OôiÑý/”\ž Š…VšIJëÇ›»lwÑ#КØÍtOuR–RÚî{¸<2 aǼj®*¨#~µd¥o-Ð}=¸ÇÜd­®çŸж’…´Z †8<ö.|ÇCdèU?é N~¥éΜëd–ï47·&MI.Ö%ˆÜl¶´YÜ’;¬E›Ô©Z÷Öy;9,ïí »µ“\áž1"6ˆ#j{è ãy.•ú2†ÝbèËèâêk—øÙqYeš9X3qvã^EØŽÉË]õ]S¨zWÕvb×9Œ‚ö5÷ ‚=Oeß½½hö­Œf „ñ~©ÅXØxÚñ=’Ý"ç­ë|@Þ¶}~f¤( úk£ðo<lvi;‡”‡gg hm˜“¡ßCz?3S”¥_¨~:cªïÖrÆ{ÙÜ}8Hö‡cµGÙô†Ã)F I Ų:[x·È–ÊÚ !˜¤C@ ‡nÕ9J ÝÏ_t½ŸP\àn2ÑÇ”·@ÏlÑ¿&ØRªž]Hä2élwØÉÐøOÉÞ‹Åã ¿³I^$¶áùˆd™¶vªÌÀl“ 6Iîe$ÄãfÊC”—hùS„Wm ™Q{öWÖÀó7`~'ç[”w=!ƒº¿¹È5¤ßÝ8i®ín%‚wÒ*2FÊÜ4‹ä߀u¾õ¹cƒÅã°qá-l ‘E©NHPï`wË{;Þ÷²N÷R ÿÓë}5Ð=/ÒÜ`±1ÚÏ:’C#ÈÜAÞv$ è5½ ú ÇÔ?G]#ÕW‚ó1„‚{¡ë23ÄïØ3!´Ëzøj­ ‹ƒ§±–}? Î ,ññ Hã´žHY@;ìèÁöOrw³³½ìÔ^'è÷§06sÚb`¾²·Ÿ¼‘Á”ºA½©ä5'•¼Š9 vÞ‰h¥_ô{Ó˜9í10_Y[ÏÞHàÊ] ÞÔò“ÊÞE†Ž»oDŠØé¾ŠÀôˆ0v³ÚG&ËCí“I'[nåyy@å­èkz«(SÉ}t^[2¹kÞŸ´’ð8veä‹#r-·E!\’NË¿C±VÊPGß`ñy˜K«$Æž‡©fê(­®Ó-3ò–år¿px°ç¢žUòÇ@ hj¹ÝòýõGÒP¯XÅ–NÖU¶Š;ÙÌI j¿jX2«³³¶¶Û1¤d(Ñ'´T~O‡Íø_[b¬oüø~×n’ðÞ·®@ëzŸ!AÎúkÑö]o^»$÷U²¾’{Ib(éÈy2™y·$]*ÈOæïªV½…ž2Î;; H--cß`ŒF‹²IÒŽÃd“úkb‚¯Œú;é\6F[Üv+Ù¤–Q4‘Çq(…Ie&.^”¯—ÊtWD ²O7VòÛÜEÐJ…$ŽE ®¤h‚bíªÉJ œF½% M XÉÒki–Éo'¯' Ûh9ødmWÊWZkB­Á Õ¼¶÷G4¡I#‘C+© ƒØ‚;j²R‚ŸcôYÑ8Üäy›L_G)š6HQìíc-Àh.†µ¡W RƒO+бÎbî1™;hîl?£çGp@#DT~¤0}.Š˜‹I!DB‘¬—Ì"VnL›7Í¢ÁuÈ€Nô59JüÎÔ8ç°ËØA{jÛ<&Mñ$ÉOª¶‰Ó ¾Æ£ñ}Ä^Z]ZÚÎÓYDÐڛɮ²¬ŽÁ6(»zU‚”ýCÒ¸.«³¹Ìd±¯¸\ñì‚x¸Ó.øèëGµ,z_ayâC=ÅÔ[ðf¾»–éáØ!¼6•˜¦ÁÑã­öÞô*b” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R”ÿÔïô¥(¥(¥(¥(¥(¥(¥(¥(­{ëûb£ÿ.:jNÖyx22z˜q¯dQûb†`¾ƒ‘Ù{"‚ÁJ¯þYbÿ¹sŸ÷ïõ4ü¹édòÜç¬l¦õ½ü¢ÖdùrŠ^.»ÆÀØ ŽÄPX)Xàž«x®-åŽh%@ñÉWR6#±wÝd R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” ÿÕïô¥(¥(¥(¥(¥(¥Wþ¿¸Ëùzj/ =ŽRYG²)ô<8’Ó2ì(tËâ+),}Õ}?޼’Êë5còh1:´ä ªÄ vbÒ€IØÐ;­ÉX¯>Ó5¾ÈÌÞü~Ðð[øÇàFÁ=“ÚNlAÓ3S6xË8ìì- ´µ|!‚1.É'J; ’Oé ‡ü²Åÿrç?î+ßêiùMu/žË¥ó—VçÜ›„ü¾g<© ï±æQ½llM‚”ÿʧþæg?ËYõü°°O,öȦž?©®¤àßÊ8ÙGâ¬Ê}A#½X)A_ü¸é¡ä“/7^‚ÊpÑ]“ðQnÀJXöâ¼vÛcomê ·›k.×Õn2q4²J>J)»‡cµ9<Ý[ËoqsA*’92º‘¢=ˆ#¶ª•±ÇÜE.&k¼Z#‚m­%Õ»&öP@Ü£@ǹdUmìò; “W}ò½C•ºSæ0ÛÊ,ãGù¡„,¼Gp¤~Ç¿"Sò'§dþÍÇýg¯sëY¤¾ðþ|PuænÝÎæ)J)J þo¦ñw>>F,å߈[˜Ùn ì ›„Ôˆ {ÅI<7ºuìz9–Î8r™¼­Û&ø,×éÉ'DJe}öýrI5¯/xÕ¢”øÌ âýSб°ñµâ{%ºEÏ[Öø½lúüÍHR” R”sô~k‰n“¥ÜÎ^[«kIä$ìò’"®ÀžäA Ü Ç¬îí§¼úã¾¾ÈñT÷/¸ÈIxŸÌXÕŠúraÅì ÇðÝ[Åqo,sA*ŽHØ2º‘°Aˆ#¾ë%VâèL&yRÖH®ç¸šâ[ÛišÚáÌ’4…ZXŠ; - ¤‘¥]ì€k'äíå› ž¾·×ýÍô,Þ„±øÞžeU£æ  UòŠãß©l`Æ@}/¢»Ú)ø+»*21ÑîS‡º9–`µ` R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” øÌl ñãÇûoä¤ÿ¬µiÐÿÖï~<¶þJxñþÛù+N”ž<¶þJxñþÛù+N”ž<¶þJô®¯¾'z­صüÿÑA±JRJRJRJRJRJV½õõ¾:ÎK«©<8S@¥‰$€ªª6Y‰ ’Hh6)UþE˜óøÿPÚ7oÁŽkÁ¯ÎçÉáMžÜxÉåïÈ3i’6²ùïr™Ë«ƒïÍõ¬öü¾_g$c¶‡•Fõ³²I ê?Õט¼žK[ùYî]»,±Ä˜ô-!ÖЂ%ŸÓU`ªÛô> ‹KÌF+‹¿µ¸Ic¹µ²En;Ôˆx°ñ—Nû× ÀmEY(¥(W·0µÜWÒŸ gšIÑÑ|Ü+kÐzï[å¾õdš¸…¢Ž4À1ˆ­eÄÙ)ß‚Xøf YÙ´§¶†ÏoÑ[èêV‘9ïské_RÑŒb<ùø´í2×2É#MKÛηäïå FýW¿¦þêÇ4eï±y¬Œ ìUÞÓ†¶¦EâÌN¶<¸òÑÙ$Ž÷Ô¸ò¬¦U€úz|~Ÿ‡jߦ¥ôæ?¢ =XœêOŸo—ÊÝuUÕ•ç²[ÛÆ’”´kyrÕRD”Ÿde<˜(2è­³ºÇuagžë+ìv^Ò û<}¬ð[\Æ$d’K…wâ{ÔH;*9k\›r˜îžÆb¯n/- ‘gävi'’@†Gç'ÌDa›ÌÁ¿A¬™<-–_Â7K:ÉÂMms%¼Š¶¼ãen'JJïDª’6°t£ñm‰éË\eœ·×PÍwpUŽ[¾24ÌdJªÜx»°Ü„)Ù$1ª ¾BÊnŸÃc’líêÛf-È#Á»–CˆRGïñ~ªÖ ‚­íâŽ"@‘Ç…TP4°vÕEÚô¾&Ï>*(gkI¥iÙf»–Wæ]]ز·1Ì †ó 7z ŒÝÕå–{‹ áxèp/ÁKÏÁ|ÏÅIn ænW¦Þú , V6?“¢Xç¼3NÏ4¥Ëǃ!ÊEBîîK“cg•~;1ÖßXØåN+w4^t{)™$c }Ç ”¡d“Èa-É–)$)Gãú‡©aé.´²‹ëþ+Û&¸0¬‡‚,#̲\G¶>2íüNåIáæòÝ#éìdY¹³ †òWñ´ò2à#æ±–à¯ÁBòloDïNŠÀÛc­ì­­g¶Žßb9-ï&Š`UâeWÒF8–#Q Ö‘tøº³« W×WX¬U¯±ä-lM¸yÞámø†˜)Á§°GåÝ@yµ£¼»l¥ù‚K¬uضy ŒÆ’î(å ³Д.¹ñßmèižƒéïg¸·Kk¸ žâ+—Ž…Äj$ŒP®@Uз‘u)ÂÙbï/î­Vq5ü¢kƒ%Ì’p5°¬Ä/`”Ê£ÑFƒŸÜAuVfs77§º³Ê‹kŸ<÷0†´‚F±ÈZUá#î ÛI6Ç5¹a—¹Êg1¹Ë{9.2–m‹¼ ;Áu.’OÖK°;ØÚì-ÀU¡ºGÏ{!ŽïĽ¸RÈ/§²…+Î6ç¸ÃÉÇkå÷{VœG½9ˆ< çY"¸…Ö\¥ÔŠÉ?ëÃM!ryßÞ ¹:«="g™…ÞOØàð,^ÝâQ˜ø¶óÊ„?‘»jÈã{âbÛ#ÔùÜɆ ~A1øù¯ÒñZá#g»G‘Q&Òj5øjíèËæfäo’øŸ«½‹ÁŸ‹ãøþ×/´xšãÏÇåârãäß-ðòû½ª>nšl'´_ô­” –ž!†FàCÄr`죟&æKÁ˜¼„¶Ù‰ Ξ¿Édn2òÝKi%„W¯obÐÀѳ,g‹—äí²$¢ïÃ,;0ÔåGàðÖ}=ƒ²ÄX' [H–$ض½Y´,NÉ:îI5!@¥)@¥)@¥+^úö,}œ—S$ïkbg; vD¯Àvõô ØªÿIy,òÐwÆÛd&‚ů†¤M|9|X”h‘®¶4Ç$7YÌ«”ú¾L5¡FV–âX¤ºåÄ€Q¼`TòfnêTÇ¢µñ2\ôݽŽ% ¢XÆ‘ÚYÞڗ쩈åŒdöU%Ü1ʳ*°Y)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JPÿ×ïô¥(¥(¥(¥(1ÏúËVnOúËU3¯:§òK¦&¿—,DP!ô.}?×Af,©ô×Úüw–ê. ¿¿i²9 ßñ22…üº'чÒÍ•èÅõóIdëösÌÄ´gäO© )UÏËÞ–ýÙ¶þþª~^ô·îÍ·ðŸõPXëb×óÿE@bú£ š¹{|vJ ‰‘y4hÞ`>z©û_Ïý¥(¥(¥(¥(¥(_Î~£Îbó}ñvqN“1î-ä $ì> ª²¡qÝD¤!v P)Tü½¿LxCŸŸÒïÙ±M ½ŽR4À}·R<‘:¢9obÇ/ÕÞÇÅÿKÀTl"ÊÝÝ›X"öÍÛ¹4¥¼Pœ‚ðFãß1­qÓÔ|}e‘¼¿²ÇØ`<[«ˆ®‹É-âÇr[N!•y.W‘:n<“Ê6þ¤4&²†9rÙ'½†ãÚbÈ3FeI8ö«ÃÂÃf^!5ܶ¹žU¯GÅm{kwk—ÉA%½½Ì#‚C¼ïâK+rŒùÌ_CJ €.Ô†8:²ã+쯄Å{To·ÉJ³ÜdOÏ‚Æ4ÊÒ}›ì3"ƒÇÍ¢Jéã³ÖW™¤½·»Î½ªË4úkaìÜ*"ÑO+PFÁ<‰c[–}…µ®g+ÁiŒ®½Å¼e¼8Ù„{^!܃ù¶XÈݺ½»|’ÜÜ^‹è¥íewðôA‹É§Øo³y¨4Óªr9-­±œ2wÜ$H.ÔøKm7€í¼|^BÌ…ÕT÷äË®ðøî»ºÇt÷NÛ eöZèá,ïo$DžYH„>NBc×0N¼ÇlVÁkИë#ŽÒÿ+ ,·föÆy'pòÅÍöUITó/v“32Ï¡ìñ¶vv¸ü¦VÖ8-#²”¥Àg¹… VvRɯMŠÏ@€«Ä61]Eq”êÛ±-m! k†ÈYÂÞ4¼ 'D#|Þäöì°î ‹ŸK,´¹r׳@.X[$² Š‚T•Mr-Ä ½ìf±)›Æ).g¶ûX¦I ãÍ9E#’²ûÈ=A «Ùg28¼ö~;˜ç½Ç&n išu ²ÇQ…îªòy·ÇJÛF-Zy¤ ¿ªú‚ÚÅ1±å­1—7¤9¸{o ˆq:„"9W˜!5b¬ 6f¡"6÷&2‰u{ñ%¡‘‘á#ž&,…Ë'Ã'oËŸG¶²ÅìÍšÊû cçÆCh<ÛJª¥ø\΂G¢ÌOl¶ÂÙ™­âkˆãŽr€È‘¹uV×p€HßÇC!Q xòÞ\M4޶Öò¢X\ƒ$€‚W޼Äú|¾[õ­Ø¡›c 1{EóûI&”d–bN‡©÷F”o@( pbUqÐÁ<„Ì’xÆTõñ7½÷õùw­´¦µŒÙÏ­´ÅkÝæ<û…Ëq-¬‘t¬ª±£rÈo{ÖÀ®ß}kË’XfšNK.`ð"4²ïÐ7c¯OM_—}Ϫ  ’FòG2»Iâ©–a¦$GÃð­Y±/ mU…²8—Ç1 ô`[`˜:ôýJÎŽx2¼kãžžýßR+¶€4º‘bW’&Id. *–,‚ÚÚ²ÿ.·Úe¦6o#B¯*£NËϲÇê =ízÙÕ|‹dF‰ähT©idRÚ'‘ Çc¹õ'à5ñí±õ5¯œ!ŽEQ*r~>Ÿ |†‡oJ›Nz+]ñáçÏË,³ä#‡—aüESœÅ½ã^EôÞ í•n™Ä›ç’að¿ÉêLtrÆUæ™ã£ÙFø±­}Çç_$ÆE,‚F’^~‰Ï |E'dݾ>šõí𬣲ÇÓÛg1çª4u78d–;&t1î’@Ñíøë[þ}HYäÍÝìÖÆÖX¼5VÛýà‘ïéøúW•ÃZ¬F d(eY, ¾ˆv;¨ùØ·±ŽÞâyÄ’3ÌÛnGÓîü>[Þ¾§w½´1;±ç‡ûg§]¢-öøò÷ÿ§Ûëû·ý“öH½³Ýý{€çîù}íúvùT…)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)AÿÐïô¥(¥(¥(¥(¥(¥(¥(¥(¥(1ÏúËW7úXÄ^äºY'°^w3­Ê.·²¿ut‰ÿYjÒe¥X¨4³ù»ÌþM¯/’4›ˆN1§5÷T—GôVO«¯,LJ}Úb;_¢²_FÝ1”»73ã£ñ Ù*5¿Æ¬¼=†Ô[X[GCà£Ta¾ƒò¼S†i÷ùÛ'ýuê¡ §´êlËø:õïuÜéAÍúèÀt®Z\•Íã\\Q ø-u _Ïý¯[¿Ÿú(6)JP)JP)JP)JP)JP)JPWñßcÖ™¤»þÊ¸Š -_Ð5ª¼¦Ù%iY´„ñì÷X+O%бËÛ¬öÑΈâHËvhœ£èãgL¤ð"¢ý‹©1Þ\}ýõ¤]¢¶¿Ib¿&¹ Ûãð&&b Kô Uëü¼~Iz?*ò/fk{‹FÄ¡y•Šü‹*z€{SòËýËœÿ¸¯© °Rªÿ—xéò?Vc¬2·¹1´/ckY;ãâ~©ð”¯-ÄŸNÇVH$i­â•á’t ÑHT²=ÓÄ‘±éØ‘ò&ƒ%)J)JVÇU[$¹Š•ÝÂdý‚+CFÏ(eeŸÀgäì7¦âH( ’©÷}#”ºl°lž*[|ŽAnÞÚïãÄȱ„n¦_7ëp¸aÇ̇¶›@$3AqaÐ7½EiŸÚ"ǵÜv·(ã<9jE,5ÇÕ€;ì@ÙÐ1sumÞ/©rk’·»l|XË[ï +tÝ„dÎ&yŸ™ Gì„’‘[‹1œ¿ÀûgFÜô÷¶ÎÞ6=ì}®àø²ÆSÄNMßgÓgåPwÝš¿LêÏÔŽrøÅÇ»iÜ@4„‘©@#SJàx{,U‹†åï_a,z¡pK«£,p;x±È¢øeÄ­¾iæTe»‘ŸÈg:0¾i¾ÈݲÊf¾Ïg=…›ölì~€|L0:ò,4Få*ÀH½Œ¦/&Ám!iyI-$ŽåÝ΀ffmÞ€B‚/ØúÃ÷wÿsMÿÕSòWÚ?d³ÙËî?­þ¬öN?ìa-ö÷¹k]µ³»(4ñ¸œnÝ­ñxûKË´v°¬J[@l…o@ ý·)J)J)J)J)JÿÑïô¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥a»º†ÆÎ{»—á´²>‰âª6N‡sØTÄLÎ f¥sΑ͋~©{ò–÷§5½Ô7 /³Ý,;RÇ8’@š¶usê;k6Kohžòò+8¿æäè³hЇjßSf½5#N8ç’"xe/Jçýa5ÕÆ;¥2øfÈ®nìË*Jê6ÞU~ÃÍÅO¨›ô©xº¾I°·—‚Â$žË Ö -âÇl¬s+xhÍäI×Zv[îÅ£ŽxwuÇ_ª7–šW3Ìg-º–Û§¯–Ú$žÓ©â³gĪtI&94 F Þ½;Y—-mÒÝG×ù?eåÄþ@/7t?Á¶m“ßÔžæ¯èWÇÿ®Ÿ8Žy÷›ÎJ¢Ü}"ø8¬ÅÜV6·OŠ’7³_sŠD—²”“‡r±Fµê}+në®’ÂϨ%¼ÆKø´"Unb`<0XvgL >ªž‡¯ìýcÝùzúU*ë®îqß”߉‰~¦Ž'vdñ]pq®‡~çáð¥zsª#ÏÝä­[ø¶-i-nDðÈ®»_K²4ÀvשøVÛ.­k7˜áwæÁüÓßç%˜÷y>¹º›|OäT]Ÿ‚ª¨ôÔüÅÿug?ïÛß먗]&Ý¢êLTòË ½ÚK$‡à¨ˆK;@ª '°ÓòËýËœÿ¸¯©§ä¼°yqÝGœ²„÷1øéu¶ùò¹I\v×`Á{o[$—ÿšq¿Ü9«uüm.BãG,Œ?ý•Øøò„]†w9g”¼2tÞf| Îna»wˆË'«å7­ ýý¥ìjðE7ŽšÊ[7™ÊB%ŠWf!ØkàWhÅJ?5´m‘‰1 ¿û?µýÙÊþÈ}eÿ!ý“ûÖ¿“Óî­›žˆÇÞÍš{«»Ù—0¨.#,T¦¼2ºPA]vÙ þw*ÞÆuF/˜Éb¬ï ’û)ŠhD¨\éP³ž ¸BHeað© û<œw–p]ÚɾA ‘Dƒ¦Žˆ#ôU½+[9ÞóÏø7a“éDÌb.1·ù|”ÑÜ2´JÅTì(˹!CI ÐËôŒæÛ1uÈÝ5þF8q(‰–APO* (q$#s èzXäËcaÊC‹—!h™ “œV2‰]{÷TÞÈò·p>åY=¾Ï뫽®nð¼fñ‰áï>>¼wÛ~›¨¦Ó©^Sç‡â< Bƒé<Æ;#†Ì§EÔ{(,íí]eJ²xÀû½ù~Õ5±ÈUÒÆÆK?¦¿º¼‘ô9ÜzQUG©ï­Ÿ‰ [·é`Ù AxîÈ–æeñ•° ½’•ˆøÐÖKû<œw–p]ÚɾA ‘Dƒ¦Žˆ#ôSWh¾¬Î~„Fã¥2Y<„9|”W¥hÚ!ÄÆAN>O@‚ ÞÏzÜÀtý—NXIibŒ³4ò3ñ½N”Q  zT¥*¶Ö½£vg‡ã‘ˆW&è¼uæU¯ï纽x‘&u4—|”2¨rf ÇZ¯iÒˆ¸I1-—ÉIl־Ȝš c‹@@ ¶ @ÞˆÙÝ‚•>‘©Ã#¬ÁÑø¦ÞîöeqmŒe·;ò·ccº|£ïܾŒSÜN‘(UyÜ3qPG`;ó;$“¿J‹ëj^1i1 Êt62,\Xø§½H­î–êЉA6Ì®Ì ‘·ox1 ÷'K­›^–¶³¶H ¾ÈFç rÊ“k™ î$Ðì €aS´©£VyØÄ¥+”¥(¯}gŒ³’òþî KXõÎiä¢ì€6ǰ٠~šØªŸUä#°Êcî­Ä—y 4w[m<ÉÆO/ˆÆä18âÁ©Ø2 bÊù,¬9+…½éÈ32ä•‹‹K °\B +ÉçáÑr ŽÏLÅsY1IÕ‡ÅL·Bß/ æ´¼´o×lci‡‡ð¶G#­œÖ9 +{I2Ô#”Ú¤7‹ Ü‘Œå›‡Ë¶È‚ÿé;§ìžHe%¼Akoª®QÔx–åÐ:=ÿÒg:} câ·»›)‰ê P´wûV&gPª6\IºõïËàO¦‰‚¼ú^ÅNªø8®®à=ÅÉÇÜ27¨ ƒÐüwð=¾5˜ë<Ž~Sàc¯d· öjè Ž6ôósÓŸ½‚·©×ÄV……¬ñÏqwr#ŽkŽ<¡…‹"ñ²&#Ôèv 5åÙÆÚ…ÂÓéQäà§r7 Ü<Ъãò 3#|»ú}ÿ ’ƒ©r·(—øÌ$oíOpPýì(¤Qÿï.ÏÄ/š—JˆÔ“Ãcco޳ŽÖÖ?Ù±bI$³3–bI%‰$’I$šØ®;oyuiËÙ®f‡–¹xnWzôÞª~ì²âD‰Ò+¢Ï¿2qb>@øjѫ敭º{Ë®$ˆDÎÐ7.=õë¡[5¬qB·bù ¬}µÃånƒË»Žl€{y+cýýÖ»þ$?ÕÖ,Gì-‡÷¼抨Ù_tÕÏ]¯±ÝYAK©¡n¼¼”+óI=]`N- ý‹"q⨞&zš×KDwL÷GáÇ:—Ìñ\ü;ßÝk¿âCý]<;ßÝk¿âCý]sh/°·ÖÉúRêïåÃÝ[|t…î® «‹‚»o‘^ˆ9¹$³2¥“¥¾©úÿ+ù;ì_S{-·«ø{?´rŸÄ×/>>/ޏo¶ª³­©ùÞñÞ²øw¿º×ćúºxw¿º×ćúº§ý#õý5kŽ»¶Ë¥œ¥®ÛÉáq¹ o$Ф0å¯#O)í5½•#õ\÷}Ýžfךäf²—#âÄ‘¢Fòy%*éuXÏ/ ƒ*¯5eŽÛWááƒSËÿÓì~ïîµßñ!þ®žïîµßñ!þ®¹Ì]ßIâ¯ïºÄYd·–%šÞH®V;ÈÔ¹,›%cã'$ ®Aô£ˆ]M›éèsÝ'wq”Ť‹tó$Ò\F·’ÖqÌ1>ã0A¿BBýÕm©æ#ðãßÔê¶xw¿º×ćúºxw¿º×ćúº¦eó—Ÿ–‘ØYgàUŠêÞ)qд~9 Q›p¼e¤^ ³"Hg‰1žKÜî^>»k/­1vVÉu 0Ú]Þ$Mu*uŒÄ^FäÒ*•‘W’TñnQÛj{¼#ðoêu\ü;ßÝk¿âCý]<;ßÝk¿âCý]Sñy¬z«7Œ~²@ð^I ¥œFÛÆ ÀŒÞªKÜ¿AF_ÐjZä:œZO2^ÞÝÞañsûe´–±øwWÀ·†ª0åOÜARQíμí·m©Ö<#ðoêu^ü;ßÝk¿âCý]<;ßÝk¿âCý]Túc/sya—7ÝM‹¹‚ƒ‹»Køn$¶Ø~Lì°Ç¨ òCÜ>ÉÑÝI ÏHœÖK©`ÈK„W7ñÂ#ãg¨Ë6Ò0\1ÑØ$ì©âyC¶Ô÷xGà›êu[<;ßÝk¿âCý]<;ßÝk¿âCý]Wºšñ²#i“Åe.­-äžÎçڭ©öv• ³sSÅ1s°;/›ËÈœÇPÉ6ÁqNnÍ(|µÔÐ[Å3/Oà¼DùÈ ±÷ðÛÎ lÚ“ÓÂ?_R{×÷÷ZïøÿWO÷÷ZïøÿWTK¾¯7X.É~RYb¾µíxÀÄb×€í!^{*É"ªƒ½+0 Ý.«êKœ]…Ü–ÝKªÁ‡[œuÄÂ\”¤IË[;±0è($2µ=¶¯»Â?þ§UïýýÖ»þ$?ÕÓýýÖ»þ$?ÕÕ"|ÎfÛ¬×&k0ÏoPßÝÇ —±²F^A‡“¹f‘T£¢ò@8ùX6Ý…Ù±ë,¤¥½ñ$¿_cÅÉá'†=2 Äà®\rRxlXörc¶Ôëø7õ:­žïîµßñ!þ®žïîµßñ!þ®´9Œ¹›1Ž%ì÷8Ø”ÞIDz‡BÊüx(-ñ]ꑊë,’â,$‹\¶S!ÓóßÇhꈕ8FˆšbX™CNÚ&â¡Ú“ÓÂ?_R{ÝýýÖ»þ$?ÕÓýýÖ»þ$?ÕÕ †g+ÑÝO·PÚßÝEf^ÖLMôwW)'7.Þ[ s4Â_ÕP$RIµQ¢ÍÎ!nK.‘Ó|ôš‰×ÔŽÿ¤+:—Žö÷÷ZïøÿWX¢¾»´ÏXYËu5ÌWk("@ƒPÅFþ#_Ý[•sý¶àèëM [^û¶é=ÑÒWÒÔµ¯2´Ò”«ºŠR” R” R” R” R” R òýQc‹ ˆÂæäxHÞôvÝÀÖ½=};TLÄs÷70Ú[½ÅÄ‚8m˜ü*—›ë6˜5¾/h„iØiÍùvøžýþªæK-y–œKw/.;à€iPèú}{ Ò¬m©3É8zwiس±%™ŽÉ?3^iJÉ%)Y!‚[‰<8³kz Ç[öX¹nˆwÜqoÔú‘÷®· Ç[Yñ7šg:TÖûëÐâ’·D/p¹×ðGpÞ~?ÍøúÐa·3Š€¬iÛ¿qÛ°øÿ7óT¶^ Ù:>Æ+ œ„˵™’)#VáÊÊÇr2D }HìÈÁVœGì\?ãœk].h•c#ˆÉß ¬)a |âDÑÞI$|ñEcP€bIÃK†H2;wõÆÉ™Âdn'ÍZCoã}uÃÁÈóPq¼Uv äx83GÃhí¿õÃp¥n‡?ÉE{P^[.:{ÅŸ7Mí!xÑç¶ŽÒ%WC#¨<.b‹ òìqqËN83¤ËšÆÉÞg}¶ãÌR=ËFÀÛCf¨!ÆÞm(JŽ»²t –.Ó-n°Ý¤„#‡â•â’6ÑGBN‰‚6BEkãzЏkˆ=®YÊ]ÞÍrȤ‚B™]Š‚B’[â»Þ†‚¿q…ËÞ]u=˜³Ž;KËØ/#ši‡ ¥H­• *¼ˆGðeG,;Y Jbâ½\ŽC3.:{U½öx†?œfE(YZy ¿EYA˜ð…;“¤[(*ñÚ^Úç²¾Ûmr9oR夌CH¡O8'Ÿˆ­eâ„l§™{•×ú“#í^Áìÿô¯ÖŸ\s]ññyxZß?ÃýOû_ ó¿äªáJgéë–N§Hº6IS#³¹*¾ÈÕ¼m H[r ‚ÑLx¶‰3®ïÆÙÓÑ^ÅšêY.±ÓÚÃsY­ä‘ãa2"‹`+’;ÄO˜Ì¿`¥”¥”¥”¥”¥”¥”¥¡³X|MÎòò\Û4Qñyíof¶fPI Æ&Ràxƒ½:÷Žüeú¢Ç…ÍÈ:ð‘½;èí»­zzúv®’Ë^e§ÝËËŽø TúþŸ^©kÄ' Ù\¦EÜÁeÕY¹mÈ+)–;XËO)Žuíñ7~Ú#u og³Ë"™¤–S¹%žg•Û×Õœ“®äëzÙ?3[¬&Ó<ÒR”ª…+$0Kq'‡moU3:Úω¸ÔÓ9Ò¦·ß^€|ü”ÿÔ²Ùbåº!ßqÅ¿SêGÝþº•·3Š€¬iÛ¿qÛ°øÿ7óVa ÜnuÄ€|Ü÷Ÿó~>µ³\k,øUá‰y÷»“ÜùoÖ–#ö.ñ¿Î5»]uå «ØØ[ïxÿ͹Q¶^Ïù5oí~³{ø¾.¸pà7Ë}µ­ïu˺]mF;§ÎVþÙñ‚êvh.¥ScŽ%Xèp(²=nµñ½6>Þu/œbzg<燃ϴfÒìt®IÑybßKN×ie“³73-ljä[‰„ Äë‰òoï:VP~Hô¿‹õo¶ýjžÙËÃñÓ°ö3ˆ¶y÷Ov>=~ôLa+JV“n&2],Žòæ­´áåê:ùö®:SyK[ ƒs¸sûOë±=Ï ì e¨krÖöð&1tå䑜éG¨ï±#ã½ÿ£ìW+xSø© s‘$a½×Sð®«lžÌòúóÎ<9|òÆ5º¥dš8µÍ»ŸEdþw5ò9㕸«ÚßN¾z=õQI¢´ÜïÂæFH¼SÙ‘ÞÿŸôü{Wßj_åY™ÊmùSEUwëÜèþÕ½‡>|÷£·â™ mH#zíZ9,=ž[¢wŽ=î%¸‘#mdE`²)Ö¸¸#Dw;ÒŽG[y!å/%Œ2Ç”ŽÞ¬;÷ïÓcãÞ¶î.ŸØ¬¿iÍa–P4þqÿïçYÛdµmÞµuãHÒ¢ÚUŠQ–VÕ¥ \òsèOc÷ýÿ¦µZKŸ ™.$C‚vY·ÅHùèŽúý55ØæÝþ÷‡Î:ñÉêT=¹˜_,SÜ< ûXÊòÙ#zÐõí®ýþ_Vü (“`H‘kºÊü‰?w®¿‡ô|k=MÏü½ëÓS{¹³JR¹Ú¥(¥(¥(sý¶àèêR¢î¶Üãqýo³~çÊ~ÒÛC÷!i¥)]Ò”¥”¥”¥”¥”¥ª·÷“­ÅÄwX‰%¶ñ)Œ¬¼ûö%~¶êÕUÌŒÏxòZÞ,J¤ý“D1Ùõ> õVó1„Zf#1B<=;zYµæq#[>]ü?†¼\t¼m®¾\RUþ°ÿUJ"ÞÍ*A±µš"yQ¶«ØëÊÝÉûþúÕ{,LÞɬåØVX¦*XÞ÷¿_å¬ã˜þ Ûz"P7?’·ä|W^h-þ×ù*6H¤†C¨ÈãÕXhÑW…\Ä#qÏky¼K¯?½íúOαÜäîÝ’çsáêEÖþ$|~ꉤc++–Xy&Óϸãïåôcþª’OÂ5T×yHòƒ½vý±íþúÈ –䆺ҦÁ©Øÿü{ü=;|kdª@ >’XáaäA,îvÎÞ¦²Ò°]^Cgy˜*¨Û1ù=OÃôÐg«>ÒLL ˆêyi‘ƒxüEQ͵Íù&ópÛìgFîßKÒt?{ßÔUã ‹"ÝB¢‚Th³ØVº\Ñ-úWê§œ6;¨q¸Ü,°^ZûZ®Jý‘Ú8bçÅÄat]µ¶ä6ºÖ¹o´å¦g¨z»©lÛ Ôø| n¦æK§·´>$dȉ‘¥dm"®vmî‡@šxm<òÇT ìf £¿Ä±‰ T_Rgÿ'1ÑÞ}Q•Ês”Eàã-¼y`žEv4½µ¿™:Ü¿ÅXäÞÍï­£œÙ\ «~}ÂJ”>½ Ž·ètGpÜ ©ô¯Sçú†öV¾èû¼>,£µ½ÕÝʉd!Â…h4 =ö;v'`Ôå§×\d}·Ø~¬û/`ðyøÞïÚx»òûÚãÇáëR ¥çz'/ÔA%Üým™±Å„Õ½†,‹f´ –”lÈ V:aÛ—b;îÉ„Å}I‡ƒí÷×þ/Õ7óx³>Ø·™´7­è}ÀT…(!ìú[ évé«[?ÑI ·ñ\í$,\r'—~Mñí¾Õ_°ú èLfFÚþÏáÝZÊ“Bþ×9âêAS¢ú: zÕâ”ù\&;7ì_XÛøÞÃwí¿—„ɾ-Øëg±Øû«_©:[ ÕØèì3–~×k¢eOãÓ€@;B£ᩊPUúoèï¥zG#%þì—RDagö‰dÚ v#ÕGðTŦ+Ù3·ßMíÞêi¦å ¿ãöK¯//VõÙ© PSó};ÖWÙ‰îq=wõ]‹ñðìþ¨†Jó±ÙÙ÷ôÞ¾1eõî?¥ÛÛ¼ ®fÞ)8ønÙKx{ßdfy~hbuØ ˜¥Öt÷ÖW˜éÒé-—Ée-ñÏw‹ÌNü;%jðJ¬{¨bGXh¨åß§Ut¬sA Êž(å@êá]CÊÁ”÷ø†ƒð  ”¨û¼=½æc”gž;«Fb”ªºHºduôeØFû™ï×q}]'YCo½!wD‘§‹"d äÁcâ@ÙóÈéÜw ÿÕïô¨~žÊe²ve³?>é}c{˜§FÙ>ë#lè¾J¾ºÖêb‚«y:Ü\Guˆ’[o‚˜ÊËÏ¿bWà;n¢Þ½wRE¬Ú󸊭.þÃSy/žñäµ¼X•Iû&ˆ0c³ê}@=‡jÕE½šTƒ!ck4Dò2£mW±×•»“÷ýõ”ÌïnÌ)íÜOǹqÒ>ñ¶ºùqIWøvÃýUqÓù+~GÀñUuæˆòßà=’§žËÁ·†òk9v–)Š–$7½ï×ùkaW1ÜsÚÞGïëÁïF»~“ó¨Ý¬´QäŠHd1ÊŒŽ=U†ˆý#e‡’m<ûŽ>þ_F?ê«ÎNámÙ.q—1¹Ñ¤]oâGÇî­!·$5Ö•6…NÇøÇãßáéÛãYÚ1)cOÂ5T×yHòƒ½vý±íþúÙ†‡‘³¹Û;zšÈU  € ûU V «Èlã3³¥Uf? ©ø~šÕ6×7ä›ÍÃo²=»|,?IÐýïQAxºI‰£‘O-20aúТLj·DP¨ …Ulö¿]uå «ØØ[ïxÿÍö<¦>\”¸Øïí^þç%ªÌ¦T^ÝÊo`y—¹ó¯˜Ø[ïxÿÍ[µ½‚óª ·|^BÞ;[Éýš$ÇKK/9ÜÉ)P„6Ü(V;ñy6Ùµ6´ô·Æ^}£6•†×7‰½¿šÂÓ)eqy/Þ+„y#âty(;$¿dÇå1ù{v¸ÆßÚÞ­Á¤¶™dPÚD©#z#·Þ*‘-ýÞ'¨q8¸²’A{a~ò[ä-Ög»•‹,q?WVi&Û‘GÓG+SêlžR(.£´’ÎÖÝæÚHv`EVЧ}hì€IT˜&°°Ö o­ »·´šêînyx¼€<¼FÛŠží¡ÜëÒ¢z£Æök{o°{Wêÿañ/&Þ™ˆÊ"¹tZTOLx_“VÖœ|!¿­yûW-ù¼N}ùowí|º©jª$¥)D†{qpW”’*€AU: ¨5š•5´ÖsÄLb_B¨U4øWÚR b’Ý$H $ h:úëåò?¦‰ ò¼„{¼õÛø¬´«oÛFìg%)JªJR” R” R” R” R” R” ‹¹þÛp?Çôu)Qw?Ûnñ¸þŽ·Ù¿så?im¡û´Ò”®‡iJRJV ›Û{>>Ñ'†z$võïè;wü>€E­ŒÚq ô­®qÿŽ?>HÃ_ŽÇmwÞý8>ýÆÓëœÆãÏ’0×ã±Û]÷¿N¿qµ8gé^ÔxÃ~•¡õÎ?ãqÇçÉkñØí®ûß§߸Ú}søÜqùòFüv;k¾÷éÁ÷î6˜=#KÚoÒ´>¹Çün8üù# ~;µß{ôàû÷O®qÿŽ?>HÃ_ŽÇmwÞý8>ýÆÓ¤i{Qã úˆ›õù?íç­®qÿŽ?>HÃ_ŽÇmwÞý8>ýÆÕw!šK‰ øQKŸ+BÑ•y ÷ìw±ù¯éÄê'1Üvú^ÔxÂ^¼ÉsFc•Ðú« ƒú* gåÄñíÇowˆ`·½žçÐUâÀ÷[pçñó³)P5æaØìoôkã½z‘Ôg'o¥íGŒ3¶.ÜPø7ÀÄäüÝþJ÷r¥,J–,@“zžã¹¯d¬îdðâœ3ï\tA[׎·Ûîo‘×»ÏìWýÏQhˆ‰^·­øÖrН„…RÌ@l“ð­{»è,“”¬KEfÙÐЭmy•ÓÞ3[Z‘µ†6!ÜoóûvýÿìEr´gk÷º• ±N|X,““åOoÛ|>ñð;¬Ö¶)nægc-Ó.žfõ=÷ >î!½ê³Ã Vñ¡#}?@¯t ÝÈôÐêž—LlÙl•…¤¨é:X´hfRތ̌@ìF”† ìÒ«N#ö.ñ¿Î5®—4K‚æà×xœßÔK¹Oo¡1ð¾·"räð÷Tç·¥w¼LwÐá¬bÊMù·n¥Œi^P£›ñmŸAø Ü¥n‚”¥”¥”¥”¥ÿÖïô¥`¹½·³ãíxa·¢A×o^þƒ·Àè ZÑXͧÏJÐúçñ¸ãóäŒ5øìv×}ïÓƒïÜm>¹Çün8üù# ~;µß{ôàû÷S†~‘¥íGŒ7éZ\ãþ7~|‘†¿ŽÚï½úp}û§×8ÿÇŸ$a¯Çc¶»ï~œ~ãiƒÒ4½¨ñ†ý+CëœÆãÏ’0×ã±Û]÷¿N¿q´úçñ¸ãóäŒ5øìv×}ïÓƒïÜm0zF—µ0ߥh}søÜqùòFüv;k¾÷éÁ÷î6Ÿ\ãþ7~|‘†¿ŽÚï½úp}û¦HÒö£Æô­®qÿŽ?>HÃ_ŽÇmwÞý8>ýÆÓëœÆãÏ’0×ã±Û]÷¿N¿q´Áé^ÔxÃ^o×äÿ´ž¼TFC!4—4ð¢—>V…£*>òAïØïcó_Ó‰ÖŸ–?Ç·½Þ!€Þö{Ÿ@}Tk‹ÜW>ã·Òö£Æ’EјåEt>ªÃ`þŠÕl]¸<¡ñ o‰È ø/»ü•‚þ>v`%*¼Ì;þ|w¯Cò:‘IMðum'z4á+WR·õg,*RÄ©bÄ97©î;šŒ©[ÏìWýÏP7wÐY')X–$Š6ͳ¡¡Xêói ‚B©f 6IøVƒ_½Ô­ŠsâÁdœŸ*|{~Øëá÷Ý`×™]=ã5µ©XcbÆÿ?·oÑßþÉT¤0ÅoŠÒ8×Ñ@ô É,¶)nægc-Ó.žfõ=÷ >î!½ê¶©J N#ö.ñ¿Î5»ZXظÆÿ8Öíu×”*­ã]£ÀYºÆÒ2Ú¡šÛ#°Ùgï TV;­±¹cg†æÒÄ•íæ¹àÄ^þø±+¡³¶v=êWd 3«È-S‚»qñèè}ú?…Sq]}gei ÌÐJV)í'OÝV)w¹aä¿g ÞˆÖ˜PI­)MžÓ©ÚÎ'<>¿Î<ñ>ØÞœ§ÿ+íÍ«Ý v@Û‹i.¢¤kãE(fP\4Á‡ 6=>Uz÷ÖR\-¥ñxø³ÃÅ9„hZeŽŠ#o}µªô¸œØéYðŒqìͬá;¯ˆà®Ã‰àBúË‘>ª6½1-—F]c ‚ÙrwV¾Ï4­;²¹ á†æT¶‚÷ ­A¯Z˜®É9Ž9Äqîë?/¯NHà—Âf¡ÎYµÌO «(ã0]Ȳ)ò’4U×ï­~ ê[^œ$º·¹™ 4Œ` x*².Ï&vÝm`í.,0VWB!5¼ xNYOÄH¸ôí¿­iu~&ó;ÓwË#’vM¼ÎT( }”ìù@×o_^Ú<ôÚb¶õ3×»®~¨á– zÒÎ Ê,ožhàšâxTGÊâÆÅ‰p§Ì­ ¤žÕ5JÊt³dº‹õjx–ÊÍÅ¥]Ú©î{OnÕ]ÍôöNÿ!5ý·±ø—X—ÇM“2ˆ‹òVyŽäh…ô>ÒVø›‹3‚†4±ž 2Ï4gÆŒ(1z…ÙmŸJ¾¥6y¤MgÇ¿Ý?Ïêž ªÔ»ÉZÙ\[[Ìîf¹n1GM#à!A*€²íΔr#b¶ê ,-Æ/5qÆø-üªoä…uó’@…ß[mFäŽà+F«ÄñB!ŸÔV9•ì÷ŸkÊÆyÇA­1UfòóB9GßYãÍâföß )dþÁ¿lãp‡Ùõ½øüšâÞºô?*­àús-owl×Ö˜»XàÊ]eKK‡•ç’a2…`bOE˜{'ìÀ×. 7Lg0Ù«[´‚Êhíl'´äùIõ+7†U–Ku& GÙCvß âÄ,—K‰‡‘¿†ö Èñö¾×:ZÊ’8‘Nüå]èЋ«­í>·LóYXIŠŠ)®š £N=Ã&‰å¡£ŽéÌ´_F÷]-5¦.ÖA‹k($¶¸wI$hÙYÜ—ŽØò:äO#úp?N^^bz¤Xãg±Ÿ/jm£ƒ%u.Ó3°ð„š^S»÷f$’ºE LâЧq[ŠËX%ç¬r] HÄ·–ïâJ@!TÅ#©c¾Ë¾]½=7·'Qa"ÆÅ’“3K ›„wMt‚'nýƒïDù[°?ò¨œö?7žé¿b¸ÆbuõNB,ÍéŽ|öב^É%Ã1xY%â±qÓ±Rºñ-¾'›¦!JÒ9 ¯°Ydnr1β1–V›Æû3/´7˜;o€ì9ycŒBZߨp÷¶ï5ŽNÖõ]ȳNÄ RÜU6XŽiØ|Ëó·e{o´K«Y9ÄûÑ ©`{«*@ ‚W=²é^¬³ÏÅ”ö\+ðº{ëFù5ëk~ÿÎëzÿ“ý÷k~'ÖÙ+¬ÅÛ§Ö7Š¢híÕV$° Rœ›>¼DaŠÔÌD&b!5JRª¡JRJRJRQw?Ûnñ¸þŽ¥*.çûmÀþ7ÑÖû7î|§í-´?ršR•Ðí)JP* ©;{3zkŸ›Ó^‡×¶½7ïMö׉íAu'ofoMsózkÐúöצýáé¾Úñ#˜æäÛ¿··Ëïs÷¼ÅÖ¿‹­pýî¸~gÔïs÷¼ÅÖ¿‹­pýî¸~gÔú¹;²X«ÌtìÑÃsÀå@T©S®@@_ˆpô^©èÍÓ¸Oý­{á±â×ê&—À6¨ŸŽC7(Þ¹}@õ­}•Þ)Îg“¡ûŸ½ãþ.µü]k‡ïuÃó8~§{Ÿ½ãþ.µü]k‡ïuÃó8~§£]YÇsÕxÞ‹¸iÇ·m ·{–Äj²“Ç’/ÅF¶Tsà³ãù¼~Ɖӹ{Œ>/‹äe»ÆÞGmf.&卿*-¼IC¶Âñ*©î‚ ¦O£Œmµå*r¹ƒ/qmí2÷˜¢ñ 3ž'Ôî¸'¶¹G9E´wbÓž_UæÆÁZú5IdŒï°>`^º?š;v÷=G'o–ŠÊU‚xd,Aää®»ŽÚ!¾_.F!éê5éð#_Úúkó}<ºŠnóûÿGóÖz•ŽoWôÏÚŸñ åž.+iàR(Ñ€1oàr÷X>k ÍâÞáïRÎÈ\IéÌ¢ÛÅ—kéÛ`uXÀâ )‰”ÛCÌOO Ǭ/¾çïxÿ‹­ZáûÝpüΩÞçïxÿ‹­ZáûÝpüΩè_Fx»\å,|®`ÌÜ[{LÝç1§9âÞ ·pÁnÜyù™ÿñ®¼¶é›ïؘ±ÿXIò‹‡YB“|wñ¨ÐÚ\(,^kžK¹ûÞ?âë_ÅÖ¸~÷\?3‡êw¹ûÞ?âë_ÅÖ¸~÷\?3‡êzÖKNCwœÅ[Amì8ë²-#£ä<$ U €w… ÛÕ<=A…é\nc¥írWÆI2×ðÅzù@Un!—ˆe18ÐSŽ•F” ëLa#r¸ÞχûOÉzaº’'„Ž @ðÈ$qÑ;_)]¢ë޼¼WÃË ñÊ…¢pUN¶;k_Á¯t‡eËÇìy%Üw]YÒ\”ÑGVi¥ás .0Üa¥vÐY{ìÛuÑêŰ’ëqsrë)My*ç^'†¤Ä¢¿~ÊR"ZNωˆÏ~'Ýç‹£In¼dE!wÙ‡§m}Úìøkæñû÷ÃÅË”3Í!Ks]ƒ°|Û?ÀG¥Qz6ÚÚÓ£±Í P‰-"™Ìj“”RÌH=É+²wù¾£ŽáéuˆžnïÓcvoå o–ŠÊU‚xd,Aää®»ŽÚ!¾_î­ <\VÒxò¹¸ºÿ®W¶´¿!ü¿2t*ÇyýŠÿ£ùê*¹µ#õ`¥)Y¤¥)AiÄ~ÅÃþ7ùÆ·kKûøßçÝ®ºò…UìGì-‡÷¼抎[ü²u,vr) —“5¼¿‰k ÂW”·É”(N vÍ¢Â6&Gû aýïù¢£­:hÙåšù3YG®¤º{V1ÝÝJ鈌;*‚†c ˆ?4k›[÷-ñ—ŸoZQ1õNFÖýÞCÀWEy48óc5¼’Ç °GYŠÈ¥B’Qt ‹½vg}úÞ÷’–Öy­à†åg¶¡R²4«Ä£;ƒ;åßÙð:VÒOh[û»Ü„RÚÉf‘ÝH…šæ”+¶ø§™Ù›Ê<Û$¼fcî..¥¾º¾»R7¸¹†à…Š ª®w;ÖüÇd€¤Ì0÷”Ê&.8?SÏs=ľ ðqç+ñg *£JŽÝÈ÷uê@0Yn±K lFL<ã纞Öî+®)"H‘Êx A°’ÉV$i€îgr˜´ÊGê‰í§·—Æ‚â<â~,„€á”í]׸>öý@"6ã¤,îlìíZîèEl×°+‰å$W’@ÈA?k!âM·u „F;ÒØËÖÉcmïÊêÈ̼ýžíUeAðä wÖö7ßGb¶ëSdØÜm½›ÞÝ^˜W‡´]²´®>ˆ®ÛÖλììÖÝUR”¢ R” R” R” R” R” R” R” R” R” R” ‹¹þÛp?Çôu)Qw?Ûnñ¸þŽ·Ù¿så?im¡û´Ò”®‡iJRP]IÛÙ›Ó\üÞšô>½µé¿xzo¶¼HçkC%úÃÂ"_ £Þúèú‚îì~`¬³ÜûU-©£5¯?ö©ûŸ½ãþ.µü]k‡ïuÃó8~§­É'Y·P®RÑ5n,üdÃŒ+ }¯œpaÈ€ˆÒ§ðºäÞ½Û½kÝû=kåèF½Ó^µ¨ü7äÞ½Û½kÝû=kåèF½Ó^µ¨ü;fEvM¦¹Åyüœ®Ú²6Ù[Ÿ«ò–ÚO&ÖHAÛE"í6¾RGt(ɰS‹qÙ`&\ÀËæ/#½½8Zˆà0Ch8€å±!ÉC¶$ªxaÁ½~Mëݻֽ߳־^„kÑ=5éÛZÃ~Mëݻֽ߳־^„kÑ=5éÛZÃfè»N7qöQdéÖ¿éèqù»ù.¯!rƶÒC($«Æ„eèzvBAOêßš-l¹<ÔRCnUÜZZµ«Êè¹·‰Ùy!bªÜPJª2Åxü›×»w­{¿g­|½×¢zkÓ¶µ†ü›×»w­{¿g­|½×¢zkÓ¶µ†Ì²m3Ýûy… ò~畸½Â_EcÉñ.­&·2De •xÌlB0m PÚB‡Á¬ÏÓ¦3#cBßë ædÈ]Ë V›–Ô€¤¢¢©ªú(øv<{äÞ½Û½kÝû=kåèF½Ó^µ¨ü:}Î:_n¼…d•Ñ×Q4rž<¸þ¶×`žžœGaÛm0˜Ù¶®ŸgÿÐ’ƒ¦™ó™»Ãoõ¥¥¼±,«ncPÍÝ[ˆ“@'ÚsÝ8n,½7€¾ÀI}ãdmî"»¹–îEKF„¬¯Ç|O‰¥QÁ»hÀ’¥ Žái†å)q ·êf‹¿®ôHø€v5éÛ\S†¨õîÜk^žMkåèGÉ}5éÛZN‰‡…;6Õ1»1ÃäÔÅùr1OQ¯Oø~×Ó_›éåÔSwŸØ¯ú?ž´#²LuÌr™dp6¤ ݵ¯Íôüß»·¦‚„Ûšxn,¤xeI FocåT¼Æ%èì:WÒÓšÞ19ü#©JW#¸¥*=Õ˜üwÜo^ãï×ÿ~‡ãS‘;±Î4Øå#„Qóbt[ì­Í­œp³*ÈûÎëòök¨òÉ‹\HV=hF‡C[ØßÏáþªïý'R¿N¢u,&M$‘÷4‘èd=6O#ñ¶ô¦ïD­T¥+D¥(¥(¥(¥(Ô½™½5ÏÍé¯CëÛ^›÷‡¦ûkÄŽv´2X߬<"%ðÚ=èñß®¨ ŽàÇᱦ Ë1ÍϵRÚš3Zóÿn]—éÜ•ÿRcrñe--Æ-¤6ð½“6ƒ¢£r>* €¢ÐPŒ"ÍÕÝ?sÔ¸Yq1ßEem0rÖåßÊêÉæuá°!†¼£adC}ü›×»w­{¿g­|½×¢zkÓ¶µ†ü›×»w­{¿g­|½×¢zkÓ¶µ‡lÃÊ›j‰‰Ç.\” :zñ/íòÖù-2ê‚+Écµ+Ôk½‹ÄãånjWP¥`õù?sŽÊÜ^á/¢±Šäø—V“[™"2†Ê€ÞpÝ!"tþBÉrœ–M dr7ÜÚEâTª§$ª¾êpîV0ì7L‰s¶ë·´lµ•¤xÉnñ¯3î0_q£DƒÜé£áöÿɽ{·z×»öz×ËÐz'¦½;kQøoɽ{·z×»öz×ËÐz'¦½;kQølÁèÛWO³™czW9ˆ±ÊAkÔ6ÐK}u%ÛO;‹C+2à­' Fàˆc>¾WíYl­ÏÕùKm'Žk$ í¢‘v›_)#ºdØ)Å„7oɽ{·z×»öz×ËÐz'¦½;kQøoɽ{·z×»öz×ËÐz'¦½;kQølÁ;6Õ3½Ž?%.ßs#LÙ«¸¯CÀmͼpmÂ9òœò$¦¶ÄTø¹Š:>›ÌYcäÅØõ[cã =¹{«h¶¾D˜º(G Ì»^+½¾Ç¢þMëݻֽ߳־^„kÑ=5éÛZÃ~Mëݻֽ߳־^„kÑ=5éÛZÃf]“i¯*ýœ†ó§ä¶¸²ƒ =Ž>dÜ¢…ᑜ6š=–gOÛr=ÙÙô!s/Gì³ñÚI¤Ù™ ¸’[~|Q“Ρ|@ d`{w±äÜV‹œt¾Ýy É+¢3®¢håzlžGâkUtÄa Þ5Lš,5ªé­©â;‚6>ðESzk¨sKƒ[ëöœfâ¹^B(Ñ­ž"ÚeÒè‚5Ùî7½v«–65›g ö¨¤£:*=îÞ;Ö¾;¥ðø¥XÚ´%â0òÈYP’J«Ú ’|¤wïëSÚTí+xÌÌðáþþ|æ'ߌw¼ûLfU>™ê,ŽzâêÆ̲I:%ͼ *öÑ-ÁGV⤠|HÚëÍðõ>-3y±ôyqÔW™yˇ†¬¢I#Ñ5Àî"~=›Zô6Ë^“ÃX¼Oim, n̪DlYˆìÝû±;õDz ?$ðßRýOìÒý_ÏÄð=¦]o××–õ¾úôß}o½o}³d›Îí8LÄúµåÌ|ø}LÃHeŸ+ˆ›Æ»öÉ­n¥¶{ Š«7Ú²…í¢¥ßêgëJÃeŒ–î[Hš6»”Í023sêÀ@'î×Ãä+v¼Ý{Rú“m8ÄOžåd¥)Y ¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¨»Ÿí·øÜGR•sý¶àèë}›÷>Sö–Ú¹ M)Jèv”¥(?ÿÑïô¥(¥(¥(¥(MÈa%–êî@ö’ø’1Én[mûêyoùêåTΪêìrØKgerÓ]7Iò¦ˆ>ÿÞ6;oâª&2$­#x¢+"ñ<·¯¥þVïú+=së^°¾‡ˆy€.µ"ì¿cDšœ¶ë+Iwâ[ºü‚0mþ;Öª7¢9‰dz}´~ûë?wýgú?O½D ãeÝüÞ®’)ø|“þŠúrV·Ð³ÈǬÁU˜ ïcÑ[[ߥ}ðÞÊá Vñ©“h ];ßßYÚÜf1óW~w÷q?æb¸¸†ÖšyR8ÔY΀×z…ê­°ÀÄÈÌ&»*JB§ã½yÃýƹVs¨¯ó×î¤"Å£…}Ôø~ŸÇñªV“eÖ®¢úB3©·Ä##M,‹­ì|úþ_ÕkÓ¹®¯È¼V4î¼LÓÊúXÁ:˜ÿ0Ù ª»twÑÝóÇ}ÔAí-ƒ+-Ÿü¤Ë­ùˆ>Aè5ï{ÃËØ×fÇãí1VØØÀ[B¼c=ÿI>¤žäšÞµŠòB±ÒGxž”ãsý™“‡µºñâm*ì…íÛ}ÏsßGUp¥*ÁJRJRJRJRJRJRJRJRJRJRJR‚›ÂK-ÕÜí%ñ$b#’Ü.¶Û÷ÔòßóÔ¤oEd^'–õã4¿ÊÝÿEFõWWc–Â[;+–šé¸êH•4A÷þñ±ÛuU{^°¾‡ˆy€.µ"ì¿cDš§)ä: Eæ=›ì}£÷ÜYû¿ë?Ñú~mÖV’ïÄ·uù`Ûüw­T¡ÉZß@RÏ#R³V`7½Emo~”µ£>(´ÌDÌF_"q²‚îþoWIü>IÿEjÖç€ÖöWb·L›AèqØÖþúªuVØ`bdf]•%!SñÞ¼ÇáþãY[6˜àšÛz2š¸¸†ÖšyR8ÔY΀×zç]Eô„gSoˆFFšY[Øøõü¾;ª®s¨¯ó×î¤"Å£…}Ôø~ŸÇñ«ßG}ÝßÓa Œ ´+Æ8ÓÐô“êIîIÙ­šÕ)J ö#öÃûÞ?óEU5Š}dØ×µkÓ<«}hVõ~ÎSÎwbXÛïà …BìÂU¸…SkÄ~ÂØ{Çþh­ÊåÖœjÛã/>Ó‹Kžôù´°Ìe¥ÂÛbó“Eyxd·€[ÝC#Jmn‰!˜¹˜B¾ Ú.»TëÜÝŒöóÅ’–ÂÞ{£‡Ò¢²Ùü¾?”æ(Ë}¡]ìÚ:ôøk¸ùWèZ„¿éŸÉEá\â­ÊhF {ßÏŽ·éú*7`~sÀtÖc«/ÞtfRy¤m$a޹3Òt6NŽÕw~ú;Äô§Ÿì̘ä=­×{iWd/nÛî{žú:«>?iа†ÆÆ‚ÚãièúIõ$÷$ìÖ§Qæ£éÞŸ¼ÊÉŠ`AáŲ¾,ŒBÆ›Ñ×'e]ëC{=…H”¨üžw„ð¾¶ÊØØxÛðý®á"ç­o\ˆÞ¶=>b¸-Â\ec3{s“bÞ#­ÔÎñ>,±1(ž§\@Ð$ÕöÓieËÙ-`ƒž¹xQ…å¯Mëñ5Møg:ë³ý%tœ34k“’àù[K9î"oû2FŒ­ò:'GcÔ¥\x‘„8,ÜÑ‚xJ©‡åVõÓ~`ÕÏÕk2­W´•gVV—úJÎÉ$x t.À…•²/ Cð%<å¯]r]úlzÖ”aÕ×Q›#޶Vÿ•³°+*ü|¦I~ãµ=·­‰ZRädžãØñ)ÕÏ? Û‘)o\t½Ù÷ùƒ_y]Æõ§„+´ð†ÞS5 ÖI–¸”ïÙà‚àZÉ!í°¢?‡vØ_]¨Ù©>‰é ¬¾fÛ©2öÜ5¬ƒÙ¥¾¹šéâ ½ølì ÷;Û({¨äµ‡¥~Ž`dzÞfI»º“‰ã$…õ®þcéêOy·~×êÒ#ÛV³ä¥)VX¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)A¯uag{ÃÚí ¸á¾>,aøï×[ôô[½ú=Ã\m­Ìö­ÃJù.þd6Éü6=*ÕOöÝ=”|bt®HÞ@ì—1_J–æ3Û> `AÞû hƒVO¢~®êN¶ÁÝeó–v6Ö¦QŸ³E"8ï›lA]Õ\Jû¤#ZMÒ.¸®ø;zo±ì>?ðý_º°Êâön­n PÞ'CÀŸ>‡ÐúWp¥1‘ùë-ŸËãñàYNbŒ·ÚÞÁí£¯O†»•Wp5˜êË÷‡™”†žiIc®LÇô “£ u_£/úC§òQxW8«rš#Qƒ÷óã­ú~Š’Çãí1VØØÀ[B¼c=ÿI>¤žäšˆˆŽB±ÒGxž”ãsý™“‡µºñâm*ì…íÛ}ÏsßGUp¥*B”¥”¥{û aýïù¢·+Oû aýïù¢´nú§e’›"äêG‘-ñ·3­¾'’FAL6ª‘ê rëFumñ—Ÿh™´á5JÇñ\ÛÇqo*K ª9#`ÊêFÁv d¬”)JP)JP)JP)Z–Y+\‹Ý¥³¹{Iͼêñ2pkÌÆ™H#`‚&¶è’•Ž9â•åHåGx[„Ь FÐm‘Ó)Ñø~5’ˆ)JÇ<Ëoo$Τj]„hÎľʠ’~à 4ÿÓíT¬7¶ù këIìÍÝåsêî~,t?€ä}Qô}–é§É¾ZL‡Y»µÅÔ²>¢¹$±Mè P4‡°õ(#‡\é^ž·éN—Ç`í[œv‘/¢ceõ¼ùÛ¨®|Qb’ÜÈê¶3É0f<‘—ÌÚ`¡W@†å Jë#Öy°ê7˜ýmpc£u"Ú8‘Ì’¯wÜ%Ay²°uuµÃÔ¸ »› wQãä»™Yc—qI(:'’¯pHžàŽÝÆ«ÇJO†•Çáópe–×~,Ëq²ìÍÊC±<¼Ämˆ$’vk<åÁžs*ŠÍg‰±ÊÞfïWº’q-䊶øöiå…ÙÝΞO±O´á]Pq1ι¸­&¹²“Á†¾–ilnžáäžâÒb…‰2;I,’•`YНÙödeèT¨ÞFó’`º¯‹š<äÙ+¦·¸Ç^_Iaã¬ÒȾ2¥»q—AnUÏ#ÃÃ%Ê–fiž•ò­‹´Êåïc¿µµ²0CmxÌn8Ä’Ëp섬±;³rMÆB·'Õt*RlM£¢™ôzضÇ\]YÞO<Ù «‰ƒÏw,¦h’MFëâ1ßšb;‚¿™HÝMš·²¿°Å]_{ ±M#ÊŒDÒøf1àD››øŠíô¤( C,÷±[û·÷sáx!É'Šod(ô]o^¼W{â5ž£•¹k^Šõ³³Ô¶ðÏŸÅ`míþÊ{ƒytƒ@I¶;n[Þô$ý× Ôô}9æ*ù Én”O Ž? 8ywßÓG¹ùš7MÂùäÌ5íã\¡ò‚ÈQW¸âÃDŸ}ï}è úî$X ³´‰…æNåK•:ñx¡X“ó+¡éØšÞƒwwÕÖùG³ö ;+q Q³!gìðBBËçð>Òý=C)BKÛµ–ÖQ|2‘Ÿ˜VSßã³ßÓä5Ö]AÃEikÓ9>c%{âÏ [ñ]ò•Ïa²F”•å¦ÖÃc«:ÓÑXå¼Í]ø^/!(¥ä™”l…QúΔ6FÅRíºK=ô‘qm”ëøc³Â¢,ú~ÞGFäÅ€{†ìy…#@ëèžeiΑú>ú£"½CÔ)ó]M$Eêvå·"Å–Ðà¾b? è(bµx ©Ç—ÈÏo,]3Œ´ö'öX†×‹ñ²ÊôõÞ×@wל¿V\Äù«!‰¢ÇYä™Iå#8PªkÍß¿§àL¶7§,ñ|’ 'ks)˜[»Šý´}6u¡­“訰·Hã!-Óø¬“N.$·b là6‰í¿Vc­ë¿¦»PGþXM&F8¢µ‹Á[1w>ÙØ¨( …Òë{'¾Ç§›JuÇYdNÂsil·w³´QwvRË‚‚}IÞ÷¢Þ„Óôµœ’v¸»ñrIÌrEÞø©×e=}€æÛ¤ì-®¬gñ®dö0DQÈÊcßí¸ë@úl€NÎÉÓÖ’Cq—k‹HŵŸŒ,šs!:àwê{1%vïv'Êu}ì+y{ukÇGð^=R@ðÕ‰Óèó”kË¿­ÃÐøÇµž g¼”Í ”Èòaþ'`y¾>öõ³­lïzÿ§,òv-my$ò»:¹¸,›]è8€#Z×r}I4·¹ž ÇZ]Þ^Y[CpŒÏRPéÁ=vÐï½ÜS\ÜßÃÃ䢃!-ë‹Æb·"} [Z:×À›=ÿNÛä¬ZÚæê팎­,ÊÊ@»â§K®#{Ðo¿©$ュ¬íò‘dÅÛÉEgT‚èmFûéHÈ×E-÷[\¤d,mâ|lw)l  ‡˜é™ˆïåì¶®þêÍwÖ1]åÖx S™æw'-N†‡Ã©>‡ŽØIXôŽ2Âê9£ñdX¤yaŠR#vãÜvÙÐQ­“­o×½c=`q³Ù›Â'œM4¾"ø’=ñî7ßGãÞƒÿÕî8kÉò{K»˜VfŒ9E;ýüF޾ÕoV³µŽÞ2Å#¿ÝØ~@zjÍ@¥)A^Ä~ÂØ{ÇþhªÆ/9y}%»œ—17W±eå‘cXš(ÚXãñi|±ÈBñP¥‹ 6|Gì-‡÷¼æŠÊlm ¤¶†Öm7?àüÉ/É}"ÄúìïÖ¹u§ÿ¥¾2óí?Õ*f:|¥—O=ÞR{Xßí²é 0–ê``Y“Ã켌‘3"«3žZbºI6Sêö“7=­¶W;$ãÂŽÜ1‚.Öòs1ùÔË ·#¸—Ú“zL&&;»k´ÅÙ-ͬBy–ÝÃFÖÕtHÐíÜÒ &&×Ù=Ÿe±óö_ÝÀçïðÐòòøë[øÕ7 Þ†Y}§J^Ùú{‡çÿWí°s×ljË]·­lou3ÂE—–79-VÕNÝ»”Ö‰ò¯r>åQˆ•2Æ Ñ>õâc±7lÙ´Áð¤Šq7µ5¼òHHÒòß•U˜DäðyY:Ze¶ÅØZÝ‚ÿ"·?e‘4BI|GCÛÕ êôO®‡p$®°˜›Ûl.ñvWpqð­å·GŽ>#CŠ‘¡ HøWŒNá1 qÃcì¦eàÒ[Z¤lW`è•ë`vû…LÎS6‰†ÜWÖ“ÝÜZCu—6Ü|xR@^.CkÉGuØî7ëK[ëKßÙ. ¸ð%heð¤áȾ¨Úôa±°{Ò+H.î.ᵂ;›ž><É/¥äûhvô¥­¥—ì–°[øò´ÒøQ„ñ$oWmz±ÐÙ=êªð,¯­26‰wcuÕ´›á4FÑÑÓǸ#ôVzÁeciŽ´KKX-m£ß`Œ".ÎΔvÉ?¦³Ð)JQ)J)J)J)J)J)J)J*;%“6SCH²HÀ³©:ÒëC¿À“¯‡ o•`ü¡û†ïÿ/ýºÒ4­1ŸæÝ”ÅEÜÿm¸Æãú:нꆶœ[$k¯!–_>ÿì€wßáËôŠÅÓÒå³ýAi’šŽÆÑdâü ä ùw½ú÷Ð×Ï×§GFÔûLcφ;›èéÚ-½+í)J³¨¥)@¥)@¥)@¥)@¥)@¥)@¥)@®EÖù®º¤ÛDü¬q[‰tv²\öêAà5=б™Mt>ªÍK‚éû›»XZâý‡‡gn±´,Ä#‚ù˜ `½ø#;W+Â}å3sµ¶Tð²‹fO‡95ñcñõ?†ûj·©ˆŒXˆÃ‰ÀË2sMëeHe*ÊÀè«ÜAà‚ m"TçYàÓz¹‹HÄvRp½@{$ò:ªH«ðÌCë~b­¡¹¢‘+F%ÍzîÎJΉDJΉTPD¬è”D¬êµiseý”öw)Î ãh¥M‘ÉXhŽã±øVeZÊ«P„—Mfg¹y±y)_Ûù¢”€¦î/ÚèvØfàÁ} ¥¢¬UC¾µ»aæ2HáÉÛPI&ø²ì‰õùŽc£Å€ä««~')gõºÈ¨ÌèÉ £tbއD«+ ‚A×bFuißzšwÞ{v”¥]¡JRƒC3’ú£5÷…âø\|œ¸ïl®Îª£éôWÿÄé©Î²þÕ/ùÒ-r¥«Ö"aó?¬þ¡´ìÛDSJØŒDò޳Ö±ô‡¿ú/ÿâ?ôׯý ý3ÿâ?ôÕz×±Iˆy±úÆÛ?çôÂî:ûôgþþšô:óôoþþš¥ öµm_Õ¶Éÿ?¤~A×[ÿ£¿óÿôס×ÿ£¿óÿôÕ4zVAéPÖ?SÚ§üþ‘ø\ZïþÿÎÿÓ^‡Yoþaÿÿ¦ª+YVkúŽÓ?åôÃÿÖë¬7ÿ1ÿÎÿÓ^‡Vïþeÿ›þꪭeZ—ÎFß´{_Hü,㪷ÿ2ÿÍÿu{O¿ùŸþoûª´µ‘~in¿µô…Œu.ÿæŸùŸî¯C¨·ÿ5ÿÌÿuW…eif·µöO ßü×ÿ3ýÕèg·ÿ6ÿÇþêƒíh¼mZÝ~É¡œßüßÿû«ÐÍoþoÿýÕ +ئ§W¯Ù/õÇÿÿû«èËÿð?ñÿº¢‡¥}ÂÞ“«Õ+õ·ÿÿû©õ¯ÿÿûª2½ a>‘©Õëû aýïù¢·+Oû aýïù¢·+“[÷mñ•¯ëIJR²T¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥*'¨o¢´Æ4R:©¸>çÑuæ?Á½z÷"¯§§:—ŠÇzÕ®ôá,þ×u5Ð$¤­ö{?˜‡è=Û_F£î2Z˜ZÙÂ÷WD#I#C_Ñò4³µÉu<Æ+0Xk‡·Äþ'î1½W¬NXàas¹d -Ã{Ïñì>î!½ëuÙ¹\ï[ú?.ºéwÙ†è—y’û= š`AKu  ônÝûünßÕÊ8Ò(Ö8ÑQUQ ôWªTÌå±JR )JP)JP+Ïö;~笵Šçû¿GóÕoêÊ·õeAJÅ ÌW„OË©ÑשÇÐúWVf3Éçf3†jû_+Ì’¤JØ('Cï?!ó?uLDÌâœ2WÚÀ—1;• u*Oá±Þ³Õ¦³^ Vby= ú+௢¼=Wªó^ªð¼=WÚù^&žt<©T ìf £¿Ä±‰ Uáxf¯µ¥>[ka%ýÆBÖ8œ¤—L«0n'@†òëçÛÖ²ØßYäìã»°»‚êÚMðš £htñÑ~Š´.Ù¯µò°__Ùã,伿»‚ÒÖ=sšyh» ±ì6H¦¥fÍ+^ÆþÏ'gå…Üv²o„ÐH$FÑ é‡c¢ý´¿³¾ñ½Žî V‚o@þ‹ï#kцÆÁî*RÙªîLo%/èþaS^ßgãø×âøˆ9xœòÅwì6R\pçÃ]‰Ð mÁFöO}O}VµµÍúJ’ÝOc68Û´ÆòcÝãØ³••³2ásSœ±[½”Í%¼ –mr¤¨#^»Ûß\iqlÔ­£Ž3ç‡?‡Õi·¹‚çÄð&Ž_ ÌoÁƒqaê§^„|«å¾JÆæÖK¨/m¥·‹~$©*²&†ÎÈ:ê­/$Šâh±°ÂÑXÉj–ŒU£¸nÅAÖ‡†4BòÑÔÙ~1Óã2W6¹Ä›wrol8MÄг¤"ÍXqí¥Þù*²ßOB“ÎÝ;ãÏ¿Ï hÉXkû6Ûõÿgýu]ÿ«õ÷¿{ëY¤¾´·•bšê¤vUTy’[a@âx¶¾z?*«_ãîfofÁÈž6!,í´aOŸh<þP9®þfu½.ýäq÷73çgƒ(š÷–ñɸC4„0`O=ú:lú úéw 룧í}cÝùú-QßY¼SÊ·p­Ù–g"+݃úVX/ìçµK¨®à’ÝØ*J’ŒKqByvü{UZóuy=Ôqbç·µ6Ö>Ycõ™Œð}«qn öSæDû½Ã‰°^`g™¤ÈCpÐ\\$ò¥934Ž@% b=6À×Jœ8ý¿+m¥Õ½íºÜZÏð>øÉ†VÑÑѽA¬k”²¶±†{Ì•’«Â$ñüAn< ºí—l¿ïçu’áUìçG·ö”hØ4Sâ {ºbNç]ûÕ[ºµ¹éû‰ð´ö‡¶’MÀYd¨<÷Ü$€Aâëm¢úu¬ÄÌÊå$œ%·_(üI ñqÞO++Üwí¿e=¾#í®BÊòiáµ¼·ž[vá2E*³DÝÆ˜Øö>¿#U[+9-¬ú&;ËOöÖOg`üY—V’†”‘¢PÇà7ÜvÅaÒóŒøßa¸Šñq2cÅÝÕûI3"©ð““qBTµBP÷ ouŽsç2²\uV×¹¬í%µ7 mâÅ:2‡b·½v‘ø…Ôƒeñ‘{'‰‘´OlײòG½k‡7¼=7ê>u‘[ìŽ>YãÁK éqfáH|y–)ÖF˜®€ß¿©nñow–™óÖ³&7Eã·ö™|Xä¶n3`ÀI´ÙhÙÛ0å ½+Zù•šI¢Í"F¥•vbG‰$ó$V|Æ2çÙ| ¤¾×ÏÙ¸N­ãp÷¸hùµñ×¥Dõ~<ä°Ð@¸Ÿ¬ÊÞÛÊaÔGJ’söŒt ¾½ùkК‹»±Èøù©áÀ\¼×‹)ÒE{pÒà „“³ ì O uúàì6Ú/JÄÇ\"ÉXK—í³Þļä¶YTȋ۹]ì0ï÷{´ÉX_Oq¥íµÄÖÍÂxâ•]¢m‘¦ùNÁì~F«Œ ÚfùÏŽ¼wŠöæínÞý½™D­!<ÏŸŒ¼NÑG¾yܾbq—«Ó™;{œˆ_¶Ðãçž/€Gš?ù *3{.[ÔQ}Ú÷JÉ .:\Œyk±‰¸Ir·(cFíØ¶ô˜vûÇζ$ÉØAޝ­£±*®.^U•mq<‰ÖŽÆÇbª¯mL\R-ËÜ>CÄiU-=¹#ðJø„Aâr67öD{zЊ®;‹ÇǘfmòW—Çã-˜‹H ¼žD2.®Q|Ïí¹BKÅ#ªãùM€önúïì~/ƒíׇâk|yo\µß^º­»¬…Œöð]ß[[ÍrÜ ŽiUVØPNØìŽÃæ*5®MœâË+<–-yõ­­Ðµ..+ífU1è“¡#h:²‰3‡¼¶Éc ²ÄxPEmi¯ãÇ5¯†ÁÇ‹Ê1¶Ð »¯>ËRÚ¦Ž w<Å`‰¤‚J±HGâˆS tTëäAø×ßÉœG÷!ÿ*ÿë©(ägyU¢tÜU˜H4Ɖí²G}ƒÛZ'%iÚßÚŸµ¿µ>(ŸÉŒ?÷!ÿ*ÿ멟ȮŸþà?åäÿj¼Õ†¢uu=©ñuì·µ³™@~Etÿ÷ÿ/'ûTüŠéÿîþ^Oöª~•®§µ>.¼Êò+§ÿ¸ùy?Ú§äWOÿpòòµSô§k©íO‰™@~Etÿ÷ÿ/'ûTüŠéÿîþ^Oöª~”íu=©ñ3(È®Ÿþà?åäÿjŸ‘]?ýÀËÉþÕOÒ®§µ>&eùÓÿÜü¼ŸíV½÷Lôž2ÎKËøá´µ\æžíãEÙm‹hl?MYê·ôƒ<6ßG=HóËHq—Ø(,Ñ•QßâX€Ä)Úê{SâfY"ºû€ÿ—“ýª~Etÿ÷ÿ/'ûUN“4r=G„†ç© saÔ Ëmà¢N“ãÚXΈm+3¼I£ÝN¶ÎÔ~#)6.ö;zÚ{[ nóòia¶>Ï,W‹ÄóðøÄÏâì™SâP¥“N×SÚŸ2¾ÏÒ]3ko-ÅŪCH^I$¹uTP6I%´÷HúK¦fy’+Tw…øJ«rä£q ¦óvRvî×SÚŸ2¼þEtÿ÷ÿ/'ûTüŠéÿîþ^Oö«[§ò‡!a}nÙ¿i…®Ú×”S;¡à,…ªønÊÆaå]}‘¬MÔWV ‡[^ àÖý?o>6°?YÝê@Ö½×oÀÇ|#ã ç¦%ˆ!Úê{SâfWÑÒ]2×n¶¨gDWxÅËòUbB’9lU€?'åY?"ºû€ÿ—“ýª£uzöÇ'“¹±Ê{/·ÝÜGjð¬oy8·ŽDPÇ2ð‘Vá®7$v$´dì†Ün¦È7TÞã¡êËOglèŨx¡g¶Y-L½ˆÐ.%FŠ>@èó % vºžÔø™•·ò+§ÿ¸ùy?Ú¬rt—LÂ𤶨3ð‰ZåÁvâ[Kæîx«€'á\˧úªêèýl]ìÿYe`↠£·Y1‹#>‚N fbª"%Ãq}Ìf³×²áfÊ}ià͇Å_ÜExV0Ìþ”À:”fš8f‘{‰"íÚê{SâfWŸÈ®Ÿþà?åäÿjµï:c¤¬"ÞÅ´g–š{·AåVvî[àªÌ~AIôV›­ò6wÍØß¤WbÖ4·¶Vi¼[º‰ÕD€¿)Š% 9.Ágruñ?HJ™ |>®Åqƒ+%­ÁKëyRâݬ̫#H#Ý—HæžG¹‰Ô¼Æ&d̺PÉb­¬ìd¶qZÝâ³oU&,<‹Þ›cÐ_…oW+læ5>†:ecÌã`Í*²ÆË<[,¼!L2ìl~´ýǬ–Ùu½ê¼t÷ÝOì¯kiš°‘Ã[®š ã^mÉÂÌòý˜!B D:…kØßÙäìã¼°»‚îÖMðš ˆÚ$0ìtA¢¹^#¯2kŽÇ^_õ&6hÍ–2úãqG!=dzL ¥H€äÇ[žåSìªéÐ7öyŸº–Êî ˜ÆW!·†@àr»•׸ù«+˜`} ¢”¥”¥”¥±\ÿc·èþzËX®±Ûô=Vþ¬«VP¹Z+ 6•8žä“ð­3+ZA<Ìʶт_ˆÙb;5éóø÷õ­×µinË/(•ƒ¤|uÅ€ùü~uŸÂŒÊ$(¦@4ŽãôÕi«JV+1žÿ·_v|{ÞE©kNy#罛˜à´)r;v€õí^šæHÁ‘Ñ}¡™ UüÕb Ÿå?ükxÅHcS  GqúkÅšNâO/05§^J÷lúkÖ¦šº\"k1çç„Í/Î%¢—Fi_sî4•V&b ¶ŽÝ¶?{¿ÑùšYÝÈÆ5ñK\]7çkq ýºî;k¾þ{ÞKCÉŒ˜í–8øsÿµÜ“ÿûÞë9¶€Æ"0Æca ÑZ[_Kˆóÿ¼}ÿDWNüò×Çݢܲ+s‘„$èQñ×û«ÞI4BóÚD1l²Bt]òõøŸ»Ò¤Lhήȥ—Ýb;úê‰q³2FŠÎvÅTOßYÆ­33ççðÚ)lDe£owq-í°äš&–HûióH:?_kGy~í®¬ŒÒnDH‡Åô>?5ø÷í0CmE£z¨PýëÙáÿ©ÜðýÑîü¿ºµm8ŸWÏÏÑ=•æ=o<<üÚø™¥¸²ñf³3tûhï_Ïueo{à ˜üE†U™±ãÍ}ÒG£h÷Þ˜+êËiz*^ë+Ú-i˜ŒC§N&µˆ™â«u 61t¤Ý?(EÝÄxÉbI9Êì¾;w%Œ¢)$˜³lú»lox$Ëäç塾t —ú¶ZÇ$¨—&]‰_œ"K/•”(Q°B±k4xœl99r‘cíS!2p–íaQ+¯nÌúÙUìOÀ|«ìXœl99r‘cíS!2p–íaQ+¯nÌúÙUìOÀ|© aMéÞ¥Ëe¥·Í!¾¹µºÇ™þ¨ðb€óf‹³™B4‹1ç#7.¥=x,¯Pä_¥&°0Ioq¸=›ÉÏÊÊ%í2ó3J;( F=g‰Æãîn®,±ö–ÓÝ¿;‰!…Q¦m“· mŽØŸ™ùרñ8Ør’å"ÇÚ&Bdá-Ú¢W^Ý™õ²<«ØŸ€ùU–ÿÐéReòsˆrÐ_H³VËXãd•äÃ+±+â3„Ieò²… 6V-ƒsvÝN·ö·R4ÛÛ™ÞÉ• KkkÜ£è3d¶#ÌT¤ý”ë[âÄãaÊK”‹h™ “„·k ‰]{vgÖÈò¯b~åKm3 ñì)©Œqg«1ÅIÁt…ÎNwÈäݰw;Jˆ·7dìyr‰Àè #©:QÊÉ’Íb:JÒº{«hÎ>Gi¼K¦[lo ©Vi¤¿ x±^Aš%tªtîn¢ÁZ䡦T,i G'ç(aÙ€>Œ;0Ó ‚ süN/ÖIn÷‚,fElAIèTðÈ#¶ÀEòéK&ë¤c1–¸‹´´ŒkÜ“ï9ø±?ÿߥmX˜oH˜Ž-ÊR•eÐ]eýª^ÿòÿ¤ZåK]W¬¿µKßþ_ô‹\©kJò|gü‡ûºÿÖ>òÈ=käöÐ]ÀÐ\Ãж¹G"†S£±°~úú=kؤ¼ŠLÄæaŽ8bH¢EHÐTQ  z>½ImÈQOF¶b3~?ŽüðLVa3gekµK[+hm­Ó|"†0ˆ»;:°îIý5²*¿ausy“†F¾™b˜5Ä1£0Ï´¥N¼EaÎ"܈îHK¬µ4擉LÀ+í|ö¨>Õ†«Õa¨—fÉÞR”¨v¥(¥(¥(§”ÉC‰°k¹–GÒ4Ž0 I#¸DA²Ù™Wd€7²@Ù­ÊÍ´«‡œE‰úÛŸ䲿‹âÆÌýòé $€u­Ð199rqNÓbï±ÒC/„b¼ ¶ò«rRŒÊËæÖÁõ =EcŸ 'ê[<ß·Ý£ÚÛÉn¶Ê#ðd*X¶Ð¾ö‘žÌ=ÁómÐò}+žÊÅmÉ2±ØÇ,þÉh÷°Ésj̰ˆä’Y|]qt¸a"3Ê‚U ñQ9Ó=;Æõ~W#vnÛÇ{‚Ó4°øS+ÍΡWÅsc†åo'uŒm€^°‹ëK«I±( µ½Ko_Á1 _‡†4²!¼X´xöæ9qÓh½[#å.¬£éÌ̉kz–S\ ‘øúóáÆDbBöì  þ ÈÍÔ¹|Ëco‡…•Žî+YoÁ¿…-Ò-,bB‚E’1*³ª¬c’÷)±ƒÀKÕ™ þK•ÆÌ™»´ŽkÄhäSh¶ä4QÈéÈç–ƒh§˜¨ Þ®€À¦;<ªXÞK¥®ZÞ(ž7y]cWM±!Am‡tàÁ{ä£úšÎÖÃlÜçe)‘ÊÚ¤ƒ‰eiFŸF Ü"V*±ª…U*¦CgŽÆtêc¸ÇŠ+wÉÊèÐÍ`.Ñøž#˜BXòp >>´—1snØ«ž»ÉXÜÛ¿µ<7Gâ‚nG÷å RU{(äy n®³öÃYß S,ÖðÞ,AÒy¢dÊXxRú Ñ;^Xî:ÊÚÇ•¼ÈãrVrc-Öê{F%”ÄÜ‚ºøNë¢QÇvx’ÜW½GÛÙf-z²ç&q2I!yÌÒ¡€E<G„탉χf~*ÚpXªCÆ>æÛ¨rý5ÕowÓWpå²XÁi›r!*¬I©5Â?‘‘Èg.úP ‰JÇ5¼R¼2@îš) –BGºx’6=;>DÖJ¼¦e/ñWfþîÜã® ÂGŒ¬P¡É닺ùH÷Éõ‰JRJRJRJRJRJRJRX®±Ûô=e¬W?Øíú?ž«VU¿«*ÏSݽŸM_Éårñ-“›'9ä<"^JA]»(äÖ÷±­ŠœýI“´è[[tþ7PG±–â_´á:3[‰ûá!r7̹Fà\2˜q•¸°‘ﮡŽÎu¸0D#1ÎÊAQ e$€FƈÑÓ{ʤF¯EXÇsÐ^^ÄEû_Ìœ‘ÖáÌ"£óCäFv*«ÇE‹{þj䉎÷ Lc‹;1õF&êÏÙïeú·)o‹ñ/®üY§ñZã3wÿ¯ääòû«Ù,äà ÂdÊu°Ào¯_p,+ö±è¤šG6× kÝ!Ô,´ g6N+éòY žÖ1Ç!‰‘dî4G‡æU-¶@Š—]ö-ºFÚÝ0èr9 F1¤‘yÈ€Îîyª‚_{ó  á‹pÖÌ-˜DÞuPLñÇ‹¶µ>Õ›{8%žóIáÀ98@H à\!岬v¥”©–ý^a޼»³ö(î¯î¬å¨öa¸%ܯüÜïGC—¼ußÕ·H[[¦G!(Æ4’/9ÝÛ‘y ¨%÷¿0Ñ`ΰw ßF¸Ùc‰.r™K–ŽÖæÑ^f„ž®œþ·¡&Ë1lXófªx'ú_ÿÑ»ås×+žÃ\Ëkuin¯$ÐÆ.d¼ˆŽHHUWi§¶(EŒd6LVï+ï¶YÁm%­Ó[ƒopgŠ^*¤•r‰½32®ÌŒ=ECÏô}¾¹¼¹ÈÞÞßÏwj–ÒÉt!~É'ˆŒ‡ÅtÁ|€Û@º1Ù3ø|RaìÒ;‰çUÖš^#@ªª¨ªˆ¡@UTvÞ¶I<Ü0äá„T]QwrÖ3A¬2œ—3Ýy›ÂyPÈžðãeˆ ³ ®ÐBèár7mˆ—­3/:ø‘Iì¶6wFHf™L#eMÊÚwæc.޶±Çò÷¦/mcƒŒké­ÚÖ[k;©n#TÂùB+"ª«»pg ijŽ!y(‘Ú­˜{K¼BãU=šÞ? À-À_£ehÊ qò²©‚½´AªÑ…ã ×Pdòë°KÜtö™Í[Çj˜ËÇ™n@™ö@O+"Mœq ¦bβQy‘²Xíq°>cÅž9-}¬ø0¬SIw—ÃØV1·'&;ÐÒ»,”Hc¸°ž[›«™,’^â@üäŽR‘­’¯Y@ t ›èæÊK ¬Ÿ5˜0\Ù{×"V¸^R¸weŒ1~S9$ÏóÃí¹^Œ4bê5Ê™ú†âž>šîæÑnÛ”K#5¼ˆ¬¾’A ¾"ŽG[Y LîKe‰Äµºdîí^Ó‘¹{¦×ˆ\Ä ”ª1•‰â8÷Ù!Â힉µ8ëû!’¾Xï"¶…ФÃŽE_†Ú<£ §ô 3oaºFÃòžLü2ÏÌü=¡a¯ŽT(^RqñBù#Ú+„<;©Ûr•Ú8¾³¼¿¼ÇA.ÀYò8뉽 ”I¢Ÿ²Ú*‘Ûi@æ r!ÂêZý"Mqz£êËG´)¹æK«iÒ8 š/ ,S»Èƒ8¬›m!5//L5¥–=±Wno1vó‹U»*Ñ\O"kÅŸKȹm’éÅ9;äLGLÝÞâ§rPeW¢D‘å½äGÃáxVUâK Cl„ ¸6JCò³1ì¿°¶>Ñõ¯Õ¼þ±eýo—?ÁßëŸa®?®yw¾Õpª»ôLc¡°|ÎTÚ,R[ϼKÌ.Ll‹TPˆxAˆ;bM¢‰}®QÕŸXfúÚçÉ{inñ–²·xÑb<•çc¶fíëØrXÝ£&º½sî¢Ægz£©.ñqIìØXŠEpWZ˜2+d‘è8)Ññ!ô"ÙîE¢g’¬/ ,ð¶Ã3ž€”úÆ{Uh­ÈåâG!Ov¾À:iÆ®}?Ð) §#žž\…ü¡K,î[‰½Üù›C½OôÿMãúvÆ+{Hcñ8´Üb;v%ì4£·oŸz˜¤WkǼ¥)VX¥)AÖ_Ú¥ïÿ/úE®TµÕzËûT½ÿåÿHµÊ–´¯'ÆÈ»¯ýcï,ƒÖ½Šð=kؤ¼Š¾¼QÍŽXÖD>ªÃ`þŠòl,Þ4­ dMðS!wë¡®Õ”Wµ©‹Ú9K¦–´r—‘im¯ìx¿\ñ}ÁïþÛñûë4¶ð\Æâå@vE 7óïAéY¥W~ÙÎ[VÓÏ,fÆÎDd{XÌŒ­ ·íß÷Öocµ•´-àëÂÚáÿÙùzO•zZÊ´ß·Võ´õkÜZMtï\(³‘8I‡æ>»Óo¶Áö=‡mõ¸ö¶óÉ“Aå:PüÁ>žƒø(µ•i¿næõ´½¢ ÈC° []ÈÐßé?Âj*lMq$‹4dbÞ8€ûJ‚{…”0Ö·¡Û@hG¬}ÿVˆ%ceoãÅk+‹®g‹ÐðfMöÒ¾Ã1÷HH¶[+¸/­c¹¶žx‘ØF8• ­îòîN«ä½#lövÑär 8&‰dŠD#ÊœZvb¤øÛ,ÂEÑÛ¾öƒ¿~8h.n¡‹Àhxä ,{rBùB€« ùiš÷+ý;Ô™ìž&Ü‹ +Œ…ÄC!Åï8áµ™™ VaËè2h)ˆ±`Huú‚6èñÔV¶³M Ù-äp’¨ü ;ÐÐ=õ¿C­öR.¶·HÓ#µ ÛOàHŠn"VfU'ŽãÉ&¼/ˆm.‚¨Y‹Œe¬øyqK‚ÒKslF…xéF´4=;j¯I¦üM¹e3Žåo×k”–ìqþ12ZG7…ò•™¸öÛxa{ŽÇ³RkÕ‡]=ôŠ£,bây-ìØÎ®.Y@#ŽÏ qÉT/bÄê¥-zWdׯh²Á5Ô oã£ý¤1¬a#ãAAßrOs½ |ü“±KlLv²Ïi.)Ym§‡‡ x¿ T©-êOï¿nõèMö)™Ý¯Žz|zý£×²xÖ¶ÑáÚ{É2XKo Û`cãÉЕ”ò)¯Ãd|ƒéîqx‹ˆðü'ÉI0UžíR(ã‹»ÈdÑ:àTÍ÷r”‹£qvÒDm^êÝ ´–ÖÝ]‹‰i#-²²w#–ý;Ts¤r¸»l~e¹··Œ˜RH­æVï~"JU°N,ŠOyI¾Îú~…yŠÄcã3}ÿ¯õá`ÅutwýK}n¶–Ê®â5››¤®¶BŽE|v;÷ЯäKl™½Ã¼–kl"´IùÉ<“¯$ŒªCˆžÍ uÞn÷g¥ ¼1,¢ÇʨT©Ô{KµÐØô¨ÏýŸÙ1Êå ‚ÿë~qOñn!8öõZí [tÓ“ú¦ñŽ<#áþâ|an(|fzæß?•¹âêk¬Šãlñí}#,R*ƒpú;Ô@CØ´ ê¼ô÷QÜã±ÖבÛßå~¼ÉʶP½éy!¶B@]q¦$ŽÚ×'ªX}㥲ä²-cš(‹ÒJuÑMwäÝõ¿7¯eÔ¦/¤l±—Öw‚êöêK;_fnd‘ŽÃ’¯¸¨]®¶}’I达˻8ããÝœן5¢%¥cÖÒdeŒÙbý®·’K¶µºY^EÙ@ y¹7‘NÇ.,@âH>.ç¶ÄÎ0±r²,VÓû[˜ƒ’ÀÆçÂä¯È<¥NÉå¥5/Œé±8•ÇZeò‰ zð‘‹í‡Z@dhó Ø4 ޹跺¶“#’’Úöa=ì-"p¹“Ÿ>GIå'°<8ì(ùn³‹lyž>|ºü÷­Åf´’i¬à–âgãV’aü6#ºòŽmük5)\ÍwÚR”IJRX®na´·{‹‰q Û1øT.oª­1a¡€‹‹½*ªë̇·¯o†÷T,–Zó-8–î^\wÁÒ 'Ðôúöµ"„þo¬¦¸-oŒ& ÍùÎ5®Ãó~?§¥CÛõbÛ—‡˜òÖüCâ-ê¢éXͦg)\mzöQ¡yd¶îб]/àw³ëñ=iÕx{¾Ú|mùf^:×Ìû¿Ë\•hÔ´#Í Ñ\D%†D’6ôt`Aý"½×‚æ{W/o<¹-•$|»WEé{»‹˜&K‹ñvÑ„Zòö?ÜúzšÒº™œOÒ”­R” R•@ëÜöWÕ=&6o#[Ý´Ö®ÚŠà€ÝŽˆätú“èA*Éœ"g ýsþ®êé.%› †‘QŒw—±6Š‘ØÅðgïu}˜þåþ£¼ÆÇÄKÙ—íäš1»†—ä;®´çjPIT°±ŠÖÚxSŒQ D]“¥@w¬ï|p†z—ÇEÃâb®"+[¬Le·º„0ݸ€—4×¼ˆé¾797Gäý¢ÞßõŸfû•€ñ_×­Ù¼ª8‚xÚ`Û…VXwýŠ;ˆ¼9ñØ «e ì2‘ÝX#Dî*,cäÁ¶ŸÚ/1³H4FÃÆü¶¾Mxl§\0 éB‘TOJÝJÝØñù \¥ŒW¶R‰`”-¢ è‚u`AHAŠÙ®7‰ÈÞôeüsÚ~®Å^(Üa£ åW=—ˆí¨‡êNʼn,k$n®Ž+)Ø úkhœÃzÎc/T¥*RR” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” ÿÓïô¥(¥(¥(¥(¥(¥(Šçû¿GóÖZÇ:—…•FɪÛÕ•oêÊ:‚²û4ß´þQ_}š_Ú(®MËtpî[£}¬žÍ/í?”Wßg—ö¿Ê*wmÑ;–èÇ_kß³Ëû_å÷À“ö¿Ê*wmÑ1KtyôW¡ŸµþZõàÉû_å«Eg¢ñ[ty¯U÷ÂÚÿ-zðßåüµh‰Z+=+í}ðÛå_x7Ê­+ÄI_iÄü«ïò«alI_i£_tj˦©D¾Ò••ÈÝÙ¯ ;q+.Ã3ª¢úú÷Ùï®ßËS)mÞß[c­Ì÷s£ “ðw5DËõ•ÝðhlÁµ‡~øo´m˜ôøvê†ÉË‘¸¸äDÞ# )‘8ö4Çáó­*ÂÚ“Õ•·ý~Â9Ôw/m&´>\[¹5¦ÍÓ÷2$SÛ­´£g"ˆüHÐôûþ5¹õL°÷³ÈÜÃð !"¯Èéð­«Ör«²ö¨Øc’èkZìÞ¿î¬ë½1ýQü¢“iêŒJN˜²’5µùX€%´ë¡÷k]ê±"*HUdYüåÞð€jÔéÓï*ûU±¶š@<ޝ‡`>úñù1erì¯ÉPHcÚA¿Ñ­Uf¹äº­J™›¦2Qqà±Í¿^­ª•‘Ê:•e: k9‰Ži|¥)P¥(¥f·¶–ê@‘!=ûŸ€üM°bns¨”_Í º  ¹Ž?pmØz×›{(lˆ|{²¼‚|¾#åøŸÑò­áwNÁÊ·$Qî§oå?yþJ˜œ írì‘{¾¸ê %<šÞX-#:ׄÊïóÍ!߯›^€Ôj™›ú>L®Föö îFͯ¥Ig†2 XÕ¡d^ȇ³ümWM£1†W¬Ú1Øaôí[3Okµ{«Ûˆm­Ó\å™Â"ìèlžÃ¹ôÖ(~‰±î’G“Ëå/¡m}Œ—24gþÒHέßDvìFÿ ÜÑWHc¦3&.9%ü×`¨ÉêŠõÝgØûÙveTê ¿Kdmí®;asqe/‹´7>/ðd)&j¥{¯%n‡Ò]AiÔ˜(îí-¤µ1àx™2ë²òU%4AS¡Ø…;Q’×¥pVœü,ŒXTèwÑøü…e•]¢uø9Rõ¾'ç¯Vk6˜˜žšÛz&'‡O~¤ÇåA~¥)]Š”¥(¥(¥(¥(¥(?ÿÖïô¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(Vê[«ËlŒf 'X– Í«nqúŸy·°>zøU¦©}Zb˜ q …x–yÇ™µÅ‡”}Äú^Õ[òqYY/¤1ºÛ¶”·‰¾½ÿh|Ã×Ôü¾ú•¨ Þ»¸”ƒóº#ƒÜË{ðøz|*~•œÀÖº¹šß¼vrΡvJþ ²EkC˜‰¦Š £xfÍnÀ|½í¿¸V{œ¥ÂAq8ŽG€A։ׯ ­˜åŽhÄ‘:ºFS°M;øHЗ jò¼Ñ4öó;òC)·Ü–·Yìíî-ù¬×p„a |È÷§º¶©Q]:ÖfÑʕӭfmXÄÊqÁý_†4ƒeÑD‡c]¶ÇòzWˆ-âr~¬ÌÊ„ix3 UWàŸÂ§+C+£É;!ÚPJŸ»åSººî<¯(Òy­¼0HF§™»èöÖ8-ã·] î}æ=ÙÌŸIääÿOú+F°¿¬˜+á!T³$ü+R÷% ž”†–f:X£˜oÐw¬)e5èY2D l¾êþqüîÚíé݇pj‰}7sß¶X¶A¹q°ø>½û|»7ÄVÍ­”6Œ`™\äs¶r>$ÿ ÐíÜüëb”jR¡áê|̸%úÍ¢â#xÉH%,uµ˜Ž ªwÈ¡rº#E´§±Wÿ×ïô¨û‹|ß¶Cí¾Ã pÓZi—]Ùˆ¬Ï—  å¶ÒkØôôV—‘ÞÍ’ÊÞÞ.÷$÷®öï ‡°íÙ¦ýîô’O / K,hó?•˜íĶ—æx«€'áP–x†ïegŒ÷Y­ð÷rÇ ø2:DUÔú†RAÁ"¦,l,ñ–qÙØZAikøCb4]’N”v$ŸÓ[sÞÏ Ä±&2îtKs2ËDÜÖ‡'™õÙ~l+_%>z+…\^7sYî²ÙìapFµßÛ·yJPGÙýq%™kßa·ºiTˆáç2$`ŽKÈð,ÄÓqP¼€âÜvÙ.cÉ=½ÊÚ]ÚE;86ï-³H±®—aÔH¥É!ôA]lv:;Ü¥=ŽþÒò9æêl­ìk½Á_w¥=öþîòIáêl­”m­Av¥@ÅáfïëÜŸ_—jܶµ»µ·¶…²]rfšê$ñ%R@xaH%{ñ=”lò” ‹ž ó[ʶù,ls›‚Ѽ˜÷uXuÙ ‰/¿ÏØö¢±ÚÍÔƒÇKËSxq7ƒ47’/ ÷yFb>·rtÒôózÔÅ(4ÍÕÜVèÒcä’gidKiQ”Hû5g(IbO@SȯmÅþVE—#†ÎYL{ˆþ¯{­¯Ï•·Šƒ¾û ÛzÑØ)A®×öiâr»|)R 7 $~âÓØã‡#•6n ;'u]͆›) ÝÓ‚‚EŠÌ¾ñõoQø JLW$KæÕ#œÌce•†åjÐl}ü>Ц¦êÑU‰íΔùb¸ë¿ý[z~?멪¥y ãIí¨ˆòèÆ<©p€çþHûÿ‡ÇÒ±a#ŒäfF²˜Haá¼2±ê£Ê?GCó¬¹Èž[Ô ¸1€uf$_SêãÌ?Gqê;Ö DŒÀ‚CÅ`r‚¹¨=½Ø›Ìþ~§ñOòJRL4^'‹óà RòçÄüüÛ?Žˆ¯>NÐ'‡"Ü¢z¯-3oþÖ÷¯_x|ª:<Íí´&užþÔ~Ï!q÷uøŸ˜ùU† ÖñÊ@Rê€Á€Øù_Æ­Yä?ÿÐêI“’ìó~(?ý×ÿ¯òmAmp¨É ó.ûú»~›ý5³Z²c¬åbÆW'eãò1üHÑ5\Z9 cE/ˆž‡ßmk½Wžúë"Í98F6æ@@õåý±õÿISª’Éá-ÞXIf’5-öNAR;v=¶Gâ{üw^‘4TE ŠUQ ÈVõ¸¥­gŽ‚Ì—]É;o”òh»ðÞ½>áøúÖÝ)TIXnç’ÞÙåŠÖk§]jJnúíÍ•~þäzVj†Ë~¢ËcócAÖ× è!I87ŠOÈ4J§à–$50/W˜L~i#\Ý­¦DDîcŽhw ÞRcbÊ\(Ÿ¯v×ÄT­Føÿ}z[¦_CÛå]ýœ©”…+^+¸ß³§ïô­Š¤ÄÇ4•[úA‚Ÿ£ž¤IâŽTˇ êXË)ïñ à@5d­<®.Ó5‹¸Æß¤irœ%D•ã,¿É:>„o¸Ø=‰¨¹~ÏÝ {+d#ÆÂÊљʟΠà$öáÆË<[Ø<ŠÇàsw˜N°\\60Úáúj×-sÀIºñFdR¬¢6&%È}™7®Ç•ðôö1®èÁ'µ¥“X ¡<‚ˆ%Lœ¹“µ1<Ùw¦ŽÎÖÑmgöÑ?l›RD ")|ÿkäÀ#òP€("çê\õ±ê«ùíñ«À<¤@…Þ[¥[d™G3¡ó‚O÷Šèqæò1}ÔW~Ô™üo³pàa›„qx›ß%ðÒyµÇJyç®#ŽÎå·Oc-_(Ë’Œ«—¼Žây&II^'ÈìT:]‚@ÉŒÂÙbND„…A¶ÙÔh=u±Žéìf*öâòÒ yÞGf’y$d~rp ÄF¼ÌHô ¾S¨ºª+N®¼·kh0/)dŠ[†¹U·I€:hÂ7¯›ÞÖ¼œŸc?Ô¹ì^^þÖÆßt‘¾0³—„ªÜÎð¸f¹H4B®ƒCqÓX-º{jùFX$”e\½äwÉ2JJñ>Gb qÒè4z\¿G14­<–3›§ðùÝ{tâwðغr—Ÿ6Óh÷'Üþ­8„|ÝIÔ‰¶ÄÃ*[¯­[qxë$iÞÏÚUÖXöD;ðÖמãÉuŽbÞÚkø±˜©n¬ñYWYägRÒZÜÇš%#`ðäK*Yxó6ȼ'×Zð¾ö¿köÞ_Y\ðñ¸ðåÃÄãîy5­qòëjÓ£~™‘“#¤¨Êr÷d2ÊÜ¥í{‡a¶œ{ÐcºêLÆ5r¶÷±Ø›«h­.±+ø6ÑÜJñ±“gn°ˆÚF}ÆAí·[%•ÉeÆJk»ìmõœW Ö>Ý£ŽuðÕ™Ã\0 Å;Æ6ï¾Ã_7ÐöwÖ·2Y½ÚßÈ–ª^lƤKyRDBÜÉBJâYK³w$ïs¦1y¾ o¦·+’{MݤÚpÑÊ„2•e>£åRÖ[PÒ—EøH9oñ>¿Ë^oç ¬™£ËÛ™ ¨p«£+ÊŒ<ÇÑ—°üO¥fµi[9•§h¼ ;Í2KÇó“ÌÿuhYßÞæ¼;¸¢¹ãpsop¨»~ãçD|tkrÅ<;9ÛÃá'€ûodögþ?º?û? ¯zQP¥¹ î–Î]Iûá“»¿Ðv?Vû@E”‚v #·íG§áðªÊAíJž2Ï"–!‚ÝŽÀ9¦™¿ñ«=²,v°¢*¢å#¶¾G¸ý4¡,´¥+D4r?ò§ý£[Ùù?ÓþŠÑ®mOY0R”ª$¯CÄA ŠÃ>BÚÞ å,òˆ$©oLêÄ·¦SéèwéPv}ekyž·Ç sn’±%Ü‚6~ÛN9žÝ¤ðÏq OazRm8„-²Ë{†·áp$K¬òøbôpℱØÞ›Ô±ó¡^-³¶7WÓXÇ?¸¶Z Q£¨:.ªÀMö6¤úówÁy®9:ÆVEÇ#y´vÃZ:½ï}ˆña±Å@Ðc¬­¬áfæc·‰cRÚzP;èÿu{›¬Ò^7ß[ö2Á!$¥?/º e½¶†ê YnaŽâã—ƒ¸'¶â=N‡s¯JÒ›¨q«iÌrK{mqËÖÆÚK´n'Gf%`;öïò?#U½+hÄ™t T#¨äÊXø°â2²*[2Ín-üYf«)F$ìÜBw÷Ÿ•‘AåÈá³–Sâ?«Þëkóåmâ ï¾ÅƒvÞ´A>rë*>ã;‡´öÏiÊØÃì<=¯Ä¸Eö~~牳ååðÞ·ð© œ«¢ÎçÛ/mÛØ^¥µ›¿½jžÍ›‰‡xßœŒy®›²÷ò.·1§ m‰ÅôÔ+=ý‹ãÒ(dkWž  ñåTð¼Ê¾„ìvî7¹’éìfZág¼‚Fp‚7 <‘¬È !%U`%NíåpÃÌݼÇr·6òÀæ@’!F1ÈÈÀ®Ì¤?x …+ú=ÆøMÒap˜¬DŸU%÷¶Ù?)²QøB7Ž@#]i¥†FäÌ9p×" '@êKûüv:9qñmšP’Íì²]x ¢yø1òm‚¦”sä{)¢t¾&<®8gK;M{7¹D°ë`p——ˆ½‰^Íî’¾ïjØËal³qAêÏúž_‚æH‹&ÃÆÊÞë°õøÐSïúŸ©, bo0rÍsŠ‚ã ¶’Hî®™ãÐ?Š>̼‘b´êvDm¹I2B:Š[O¶8,“ØÌVé¼Þ$N$à“cÙÉçÂ7nZ ÖÅÎkìÞ.±øØ°8‡i’æeNƒŒ""1;XÈ㢠„}=Œ‹76a`ÞJþ#žF@ü|Ö2Üø(^@­è…/Ô=KIt}¥”_Xäïñ^Ù5Á…d<ae’â=±ñ—oâw*O7—b.¬êÃõÕÖ+kìy [`nGw¸[~!¦ŠpiÁ,ùwPm`‡¢°6Øë{+kYí£·ØŽK{É¢˜x™UÄ…t‘Ž%ˆÔh5¤]c=ÓÞÏqn–×qA=ÄW/9 ˆÔI2¡\ €« 8'o"è!òOÔ6°ÞÛ)ÆÇ=…ÃÁ6N[9š×Ÿƒ ¨4rСR³2 „“ï€/•[— úzl¤ùm®ä¸¸wi¹ä. Iψehùð(Dh Ä„Q­*É@¥kÍgoí=Ü{4ByùÈÂŒòÓ¶ýÕò7sÛÊ~F£îºŸià_\Ǹ—Û"¶ö]pöK‰9Ürý¿‰á¯ÓïgZÑ Ç4Ëq!Õ<‘³³”­žçÐ “  ¨x0mqÆK?’¼(âQoKh@wØF¡ÊzŽ;‚›‘Ô¥­…ìv[øò´óx1„ñ$oyÛ^¬t6OsA<ùûû‰m­l£ÆÚs1µôó«O }ø¢PÈAâ]í£ qiˆ#hmâ‰æ’wD ÒÈ3=ãijëØò²RJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRƒÿÒïô¥(¥(¥(¥(ŠâqÄI¾"²Ò¦'˜¹m^ 8ÑË^<3V9aI—N»×¡ùT{Ù4aA<ÉíµS믗º믞jáášxf·Ö%e ¤#`B+ïWíQ„\Öq\ IâŽU`:†ý5sÒxÛ‡ä©$'dŸ ´þã½~U«À§Q6­¹ÂT¤Ææ0ìlò6ÞʧÄu™BrnÃ[;õУôW¨z½®ãki F’_ 1Ÿopï‘û·ßÒ¬9.›²ÊìÜ ¹þk,§ËéèÔo_*ƒ~‚^Ã-½Ï‰Ê¥â”hð¾aê@õõ®]JgÕLKä*‘M™c‰ù6Œðµ£kCÑ“¶¿ôÕ¢ ¼dAQ¢¸=¿l}he¥„‘,72Ù–cÅnÒ¡î¶Á>Ÿýꤔ@  h±ÖÏßÚ±¬LsKíh\dZÚvWƒq.¶û#áó*ÿòö­ú‰½ŠAvò‹5eíö«ô×¾¬_îì¿w§z™ÏpÍy –($_G^C¸>ºùv­:ÚºïoltG—Ð’Hì>'¿ð÷­Z翬˜@dò¹³ea6 4žÕ‰+MÀ=¯e!Z&‘9²8‘¾þ‡H^äìñ—wy32¹hš(o®b¶^a¶ÁLÊÇî€ÜŸu´;·¾¢ë{/( ÕÕàâx)ò€~gðø}⹎C+’ê åñYå’V Ä ½—â{ÿ.ªÕ¤Èê^»¾È™m±Ž[2… Ñ’Ü; ìv#Zì¨~œé ßTÞx©;-¸” îx€ƒâ{6Ù›ð?½oué_¢fòÝõox oÐ :ŸÄè}ÝýEu¬ã†$Š(Ö8ÑB¢ ÐP;ÀWVž”G5fUË,Ø[ÛÞäﯤ‚E•ei|#µq>Iêtå·¾ä×™ºKu<“Þâí¯fv,d½OheÙß2oŠïzQ¥:ugð+Æ eå4¨ƒDŽG¹×Ëç]{õF¶˜ël}ªZÙ[Cmn›á(gg@vÉ?¦¾²5ÍÂÙB I'¾@Ø~$Öò[^^±©¶‰NŒ“FyûÕ?Çç÷Tµ…½Œl°©Ûwwc¶có'ÿ¿ZÎúü1R!ž8Ò’(Æ‘*ê”®UŠ‹ÉtÖ3p·L&6úu@‹%ÕªJÁvN`N¶I×ÞjR”öx<^:ÌÚc¬ °·2¬Æ;$öp\vxk{âù£±Ú—Øk\„RG4·È¯(˜˜/焆 @£‚CÝR{ë}êB”ö=5a¼ŽêŒ«È›ÐŸ-u2‚;£ÈTúüGo_Z[_Ã\Nв¼¬¥ùøœ¹¤¾ÈP[`)â yGØ¥ø,Œ×ÊY™Ë,QÅfU>èå:É?2krßu±ø™›éýŸŸ‰â$ÚyzxœcãðáÇïåR ‡› %´ ÔÙX¤‹—9Ò;Rólìr£^ƒˆ_¿g½-pŽ×™|­üÓDÐ&¹ð¸¡ø*Âozp¼ÆõËZb”pc ¶¸Št’ì¼vâÙD—rº”{*ÌC?ïÈ,~&¢ÿ!zM»ËÓx©ä=Úk‹D–IÅÜv>¥˜’OrI«(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(?ÿÓïô¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(1In޶ŒNù/c½kožýa6÷ ²€\$öÙ,6>~‹[t©Ì9D[œRñÊ…ù~v„ ò.-¹"´ªŽþêIäcß^éÑ­êTïHÁáŠÇ?(¡gH^f‘ÆT1þ1ùkïÕÖcܶŽ6ø4kÁ‡àFˆ§ÕðþÞãÿòdÿj›Ò9¯UÝç.¦ uŠ’Î oF ]G.>¯îžúô×®ªÓ;{dw ¬ƒ{â§Ë¿Nàìì~É/÷}Ïñcÿf¢ï:G³p¬YŸ›:$hÌ~e•A>µIˆ™È¥Úu¬ëÅgXå{$qcúGaü(3øœG˜Í¨ŒU;àXhè¯Çï"—_F‘•si’`tJ¬±ï H=¿~НßôNs9­¸¹E–¶nDë\{1?€ª[N-ž1ïVô­ãvјY2yŒm–2;‰/‘¢†=³ÛŸMlzìÿ=rÞ£ë묃=¶0µ½°$xƒ³Èº×è¿¥Gu6;"¹Ha’+¦–B-ÝX²¹Ö€]våÛCÔÕï¥>‡ Æ.ºšFŒž@YBÃcà 8$|·ÝßÔR4㜭ˆÄ()ÑY^¬¹É‡d’žíýØûlèoluð1½ºî]5ј~³çStc =ä§Eûï¶Î”o]‡Èodn§Se²ÛF’¤ ‚5‰gp¡@ÐP7­k¶«Ôxœ|Q„[8H¶@ÇøOzÖ'·Ù™|(æñ_-B¦Nßâƒ_yç:‚Ê]*^sᮾù|*N”Þ‘,o¦Uö‹Äˆh‡[tî~ZfÞ¿‚¶mñÖÖÌcç(õ–O3“­zŸº¶©Q¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)AÿÔïô¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(?ÿÕïô¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(?ÿÙprocmail-lib-2009.1202/doc/article/pic/cr-system-joe-job.png000066400000000000000000000400121130547513300233240ustar00rootroot00000000000000‰PNG  IHDRŠâXågAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<`PLTEåååÿÿÿ_Ö¯v”v£Ì£Í–ÌÿÌÙÿÙ°§ê×”äËçÿçÑÑÿHB?…z›ääÿòÿò!Íœ´ïàúÿú@Ð£ØØØïïð·ä·²²²|ݾõõÿÃôÃÌ̲™™33ÌÉÄÅ’?0IDATxÚb`£`P€b ‚Q08@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@&ÅQ0H@Ñ:)21!‡OÑ( ffkˆNÂÆ§•A‹áÖ&ERR Tt€b M8À]KßRfÐh1KËâ »ŠÃ €hå­MŠƒ2-2&E¼ €hæ«MŠƒ1-Ž&Eü €hæ©Ñ¤8(zC')í’"ãhRDk×&E¼ €hç'DRDޤ®6JÏ]#.¾¤ˆ¢Ìd‚«Ài$šíHÚqôá#°ÚN#É0á÷&v/¡:Ÿ á1"B[´aXF(Ñ¡ù„¢~4@1Ð8{Ř0CGRDŠ<&ìáq€=æ°”³(*‘ƒÓF,’LhF ÛŒª¥}‚­‡Ã›8I‡%ÐØH\T1A\Æ„øk3D>b¤l -VŽ ‚þÿè®Èábº[RÄêÿQÔûz;¹ŸTש2®’ä¯À(³Heî:AêÓXR±*Rs¡i&f  -K­ïÆ«ÎЉî€[yˆ¥"#F0JŠL8»JôÚ E›™1†Ô½eÂZÉ!%.,6c7]3)2áŒVF‚9 kð0áM)¸" ÅŘIw3ˆ‰»d¦E€¢sRÄßH")á HœÓ*Ø›GLXËÛÑ™¸Ú[XmÆÆÁ,ƒPŠ8¼‰ÑóâXK$FJ’"jà›¹ÂªòN(@ @Rdb•qkÄÎ#MX &,‚I‘­Á…«‚½Pab$&±›™ð6(¨™ Æ3µ“"@Ñ;)2!ù“„¤ˆµ‚G-©°–xæJIHŠ˜)ObDîmcËx$E¤ÀÃâ \Fa A“"jùH£¤@4W$µ­HDRÄœI‘‘ _°`-“ %Eô¦¾qCÔ¤ˆ«cDFRÄÝVÄê1|!8“"@Ñ2)âlòál+âÔˆ>ê‡ÖÀÒí½€#.)ÂG_°ÛŒ6ŒÃ„)ƒÝI„’"†RÜ › W‰ŽœW[—Gi•ˆvsÐŒxzz8zÐx∠ÇÈ¡qET3±ÂØú·¨Ý¬Ž£›‹-ýãˆ*â“"¤È„¿q#IájÄ2á br4ˆf+s°Ž, †bMŠ(ã×x:*(*±'E&Fœfâë áÌaÂa3fΖÇà©7±·1\Ï„9žM0)âž8aÂÑQÄÄø4PV(2Ö+âk°`®eDç <|ƒs'–ÞÊl–!n‚% º6t›1š‘h‰É ¼‰‘¨žF <ø| † q%-ìÃP8Û&X‚"VâDÃUÜHl´Ô€*†žÂ°jÄšño£/¨Q:šñ‚ÝÙLè=dÌ61Öqu 1Œ@÷&öÈgÂÚ\EIæ¨~XÄ•™pJ1áL"Zñ €†Ê6+&,,ê=QݱÃ:© ˆa¨¥Ä!™FHRÐÐHŠL£Iq† •@ •¤HýM+#-)ú¾4T*hêo+¥I”` oç¤2 !Óm¡zB¤I¬0 æ}ƒ|‡8@T2   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8è)Wå{h4)úTˆ%¥áL‚˜bCdz4šs:Ä—D±sð+Ô €F“â€Ö¸L¸Ïßd"*¥•ІFj Ñ¤Hÿ4H¸z%2éĆ@b Ñ¤HÇdH¤b“ iÉkÐ'F€MŠÜì#[)éIk§E€MŠ´hþQh˜h˜®wZ Ñ¤H•ˆ§ñGb5J[æÐ Ñ¤HA*¤’*z:{)@&EÚô@ÈW>˜œNW@£I‘v=ŠuѦX¬³04šILRC݃.sÀ@&Å‘”iQ 4šGjBt~ Ñ¤8:ŸÃÂ[4šGn‘8È|@£I‘ …‡<à‰aèõlŒdv_Qîâ¥~‰6HÒ"@&EjÄ–<8=âÔ‚rÛ.>ã˜p‰b½ážjåÙàH‹4š©‘å ¦DÄÍd%EFZ–Šƒ$)ÐhR¤JR„&Dˆå‘+V& £îB…aä+JÁ*PêtÔ뤑1QcLfP¤E€MŠTˆ)PÚƒ¥AyFxÑ [ˆv'04yAœ IbHå)nD…„4(’"@&Eê$Eh2D©«±v60n™gBjK2! Aä&"¼„eB½Ãž Ÿ¡žhp$EqRÁ k*"JDäf#rÍ„¸bõšyDEŒ$‰ž‘øLhäPd Ñ¤HÌP …¢@&Ez¦F&ª&Äah4)Rܳ¦•ê–h4)R%92­ˆ²Ä8œO  Ñ¤HÅôˆ%Ib';91 ï#ëh4)Ò&IâíGUQû«hÐ%E&eñ—q@ܑУ¥{#sЀlIëX—ZI‘‰z}<ã|Ôid{@ƒ/)2Q+)ŸX)6j!T:b•#…¤€dIípVøñpˆ%÷ð¤È„t˜"J™˜Ðö.!Öbè_±‹¬“6­8b&ê†Ï`5y €]RD98 ýnd$Œ”"‘¸ÈE&Œ /JÑõ ”ŠÈ˜Ý ¦|9q €yRD­‘™°&EF|I¹ˆÄHrØ’"åý, ÕX@ƒ+)¢VNhI5ýÁT¢'Eäš‘³º¦vRd¢Ê‘ h%E”ª 5)b)±4ѪD”´ˆ+é–ŠƒàK‰h)oRDâ"'?D ¯Ú±éëCÞö4@mEþð@ ¦¤ˆèåbt‚™à•/¼‡É„"‹¨{‘43¡u Ñô ‹؃fäg_R z%E9 [+sŒ†"ù˜w”¤ˆ'-ý¢-“#5OR / æ¨o‰Î£I‘ €èœi–¦PÄXtƒˆöñhRd º'D9Z×ÕôLˆ8„I÷ñhRd †IˆÃ#52áô1É>†'E`QŠIaPd% 2µÖ $À,(‰116_R †K‰C>92áñ1©>æGJ_LèÞ´AV‚"¿\c‚#&(r˜LnR †LˆC<52áô1É>æÇH'Lì¨I\þ JJXÄ/¬2ìˆâ E ¹hCˆÁU¢~PóФ˜7• )•’ˆa S"jä`¥Ê½Ûôi+B»Í¤g@~l)µT„>LÈ’L&xíË„’nPëN&¤Zš n4ŠÂEùa ‘ JEr}<šá €IJ$;)bè g-NrÃÇ£Iˆap$D¤n Ö¤ˆ=µ xR¤ÜÇ£IˆaÄËÐMŠ”ùx4)Â@1 Žh!ù-BœmÅIŠ”úx4)Â@1 \´ Ä Þ4<1òó£H (ø@ñ Mˆ˜>MŠ@ ƒ¢€@l#܃pº…Š>æ§eôócŠðóº¤@ ƒ¢€À“á)ˆ'Dü>¦QÊàÅ>;?Zr€“üDè§[R †AQ@àKŠÐ4È?¼ŠDIQ^L€ŒÁá°ÃTÀÅ *ະ‡XŠDÍOF‘J³¤@ -¨ñ‚')2Æ…9Ôö1?<¥Á“#&%)ÂkqvÂ¥"J2dÇHŠˆ*&¤šÎ¥"@1 ŠbH%EšøžÁÖDJŠòXJEDR„èÂÒÎCM\ˆæ#?ª4jRDJ‰tl+ÃD ¶x‘Ö ‘°1’";ž¤ÈŽQAcMŠH=¤4†­~FJ¨¨…"={ÐDaRd*”'EŒãvÐÏÃ\×5¨| ïAË£ô‘‘XÈ=hxý ç°Ëc«¤ÙQŠ6~DqˆÔ;A”†è8 Æñ%E€¢BR$:rdñÄ ÙIG¢#BtPù˜V#ΘɉŸVc†”&E€¢RR$&rðE éI-y‘”nQ >æ§Q:äÇ™:dº_R *&Eü‘#‹?^dI()IIXÓò ð1’"?áÁ8ñ@Tè¶7¢…¨¤H›ÓI4•F>]Á@TêAˆY‚ñBtR¤E¯˜Ô¤H&EF€¢bwäŽYbªR:ÂVÑÈÇXÎÌÁ¾‹Ž‰i¸&E€¢r[äQ@ÈÊñáIƒ.)RÛÇŒgæ`Û’¤‚þ€J9_R ê÷ Ñ↨h‘ã“Åè— èU'¸+lø­‚ÆrôrÉDÔ†cê'E&Z'E€¢8)ÊɱÉá‹¢ >D}…t ÷À&EÖSßÇhI‘ %Ù¡ÿ€|6ý“"“"@Q%)b‹9DÄ. M§Ásµ7PÝÇèmEä4‰5)Hk‘‰:i_R j%EÔ‚)rˆ* à3¸n¸Ã›©äc,mEvìç+x©H…´ˆ/)uÚŠøû“„ XÄ Î»QÜCec$EÔ®3Jô#NEdŽ4@Q{¶ÄØû“x hÄ0 ¤H%™qE:t[ˆI5nˆ* 3$® ¥ª‡Ò7Í“"@Q9)""‡pÄ Ý–¡“)öñ™m¡u @4HŠàj 7D¨3ä’"Å>MŠ@@´IŠF¾ˆA- †Ð*nùx(ÌAÓx0 €h–ñVWèİHŠùx4)2Ѐ$EŒbØ'E‚>æGÙ.ÀޱïuC|3>ѳÅð0Ó@¦E|I € )b) †yR$ÂǨ›O!É΃íò+@Ýë‡%µ0áHDLd¦&&:%E€¢RÄV@ ï¤HŒ±$Evb’"jr„¯—@‡Ý>?ÎqwÆ AL˜× 11Ñ%)½“"öb8'Eâ|ÌTÿ²£%E,'•`-™7!ÝÍ- ‘/ûA¾;õ. ” G„ •Ò"¾¤@ ´Ž¢ lIq«=#ÓJ‹dù¹TDNŠ8ÍÁQA£,ç^kÁŽ%)²ãKŠìèI‘‰‰j54¾¤@”&E´™üƒ³€À’áIp°¥EÚøg[‘”¤ˆåªJÄÕVä&E&*v\ð%E€¢ÆÞ¼‘CT1„’"|ŒÔƒF>øV(¢j‡LáZÎ…˜EeG¹³’ åî ¤›‰°´1AÐ2)µö¶àŒ¢ ̤ȄÊbTõ3 |LëqE*­¬¡4-âKŠMŠläB(”BY „ñ1"oAÓ¤ÈF]ˆÕÇØ’"I>*;þh˜ˆ²øb@‚h©m§þhÁ™).i’Q|Œuo I>MŠŒD­R5vÐKEBM“"íÒ"ÜÇ‹ÄHõñÙÍD³¤@T,ÑÊ ä£gR¤Æ`4M‰`£tdÈòñhRd j—ŠðÔ‹¢ œI‘‰‘q°—ŠÖR¿š,Ó!˜h•ˆ¥"B#‡¨WRdbd ¥"Òfr}ì§CPÉø’"@QX*‚Ú… xcGV–¬¤ˆZR6¬HÕ”ˆÕÇ„×+’PAÊÓ!èˆòRGj\(^€MŠ”'E€¢B©ÈŸ!T*2a©³™PR$i>iI‘ì´ˆ/)¥¥¢Cãf¨´±—ŠÐv"þR«G“"åI €p—ŠD÷ `­§¡ÔƒfÂð)¢½HºG\R$7-âKŠ„»TÄ5®Èˆ>ÊÆ‹“¡ÔƒÆ2®ˆÙ›!ÞÇ£I‘ò¤@˜¥"¢Uφ޾Gš}Aš{`bǘ5hKE”$&6ÛÂi-2!Ͱëcª%Eä£IØQî@þI €¨³2GŽúsÐT/©»2GŽFsЈMøòìˆc!_R$3-âKŠD…•9r4Y™3XÓ¢¡ÕTIЍ'”`¿êy¸%E€¢F©(G…R‘qH•ŠrT( 'EØ6çÁ˜ÉK‹ø’"@ ’õŠ4ݺ<(×+2HŠò(IQ~$E€¢´T”£ÆzE´ûîw©(GõŠ>z¥"Yi_R ªìmÁWR/|C'-bõ1©IÓÇ=hFâ ó¤@”—Šøëg¢¢…¦i‘ê¥"þš,Áû ©ˆ ¥"e=hh¼ ™´ˆÕÇ$%E¬>ŠW“3Q7)UŽúļcŒØˆG ëhêßD&EF€¢Æ¡v¤Ÿ×?tS"­|<“"i_R ÊKE9ü‘Cd´ •”H+&EF€¢a »’v‰´óñhRd ZUÐpáaU$ÒÎÇ8*Ár8ÓPN‹ø’"@Q£T”#£ŒšE"í|Œý l)oØ&E€¢¼TÄáð*içc~´†ï‡Fß|Ê>6Ÿ’Ÿñ%E€¢F7n†U‘H;ó£ÕÀðƒJ˜ÐS(Ó`*©™ˆV4ž2b‰´ó1?fü2!6è£$Å¡ÜZÄ—ˆ†·Yá(#†r‘H;óc}ìèÝ–ÁX*R3)­’"®2bh‰´ó1–42ÁfTmEj&E€¢s©8Ä‹DÚùxHŽ+’žñ%E€b mä ]3Æ7äS"­|<šˆ I{’ Û5cÃ!!ÒÄÇC6)’–ñ%E€¢RRÄŒ`Ä€ãf؉´ññhRd *&EŒÈA‰˜a”iáã¡›IJ‹ø’"@QœùÁWÜÀ¯F ‘&>MŠŒÄ@•xÁ9Ã4%RÛÇ£I‘ €¨-¸"gH'D¤‹Œ˜hëã!œII‹ø’"@1P³”À9TI‰°«„&%¢ßxI &EF€b v¥…9”$DØÕœœ‘aÅ!¶ËW©í㡜IH‹ø’"@1P+ÚøqDY)–YXX8Á€iàªgœ·¯RÕÇ£I‘ €¨w˜‘Cb´ %A(€$D&Yƒ-)RÅÇ£IˆÊч;fHK‚()q@"±wR“çãa•‰O‹øâ €h…Ø"†Ä$8R" ×£ïãѤˆ¢-fHL‚H)\9äP1I‘°‡wR$:-â‹J€b ]L""#²´H$9)âöñhR$*)mc3¨ñËB,Ø"‘œ¤ˆÝÇ£I‘¸¤@ t_RR"ÿ@¦DØØ6êH7RÙNÕ<Ë>"Ò"¾è †Á›¶HÄ(™Ð[ºŒ£I‘ªI €kRð"GRDºÝ|4)’žñÅ(@1 æ”È8Ѐ KÑ&)e›…»¨ˆÖNÕÝZ”'E€œIqT·ãi”QŽ)¡Fª`¢Òlš'E€bœ)qÐ&D¥D¤R‘â42 )‘HÓðE+@ Ƥî;ò”HÓ¤ÈÄ?^‹21¡ˆB+X¨(ÊÆi&øPL¨Õ=”‡ºÓzÐ$E€b”)q`Vâ—©?ƒÑVdÇ< šÙÙQ“œ —AV†züLŽ ¡îi_R Á—pUq)L3Ò¶TDPLÈÕ6Ú‘Nhé• 5Åb?脉 í$”A“ˆap¦ÄA™)úŽC¯ QXìð íðEô¤ÈÄŽqêéOÈÉ”i%E€lI‘sð&EšîiàGíµÀZtLLh ” k¡ˆœ(‘•1¡ŠLL¨ é?´ˆ/)à M‰ƒ.-Òxw ?RÇ‚ ÑIaBjB²#uRЛ•°²Ò“*cBIºLðƒŸÝA•hp%ENÎÁši½Ï‹ŸŒÈe¢fßvà“"@1 Ú”8¨’"Í7òcZ¦¡”‰± _R Á”99iZ¤ÃÖW~’'æ×é³THŠÄ0xSâ I‹ôØ„=ä—C—ñ%E€)H‰Ô*aÅj…ŒL£ôZPS"jAOyüŒØœØÊN~F¢“"Z ˆ­‚¦|×Á LŠÄ0èS"µ›‹ dÁˆ½PÄÒsFJ©ŒHE#r’D«I] iIíB?Œ’r¸%E€è¤HDJ¤<)"šD&ED­þæÇ,÷MIŒ¤ˆ®…˜¤ˆ²ú }é+;ú‚mÄ\529hÓ"¾` †ÁŸ)O‹hI‘ŸRDî9c4%±$Eôæ(>UD´¡‹ áwK¢®€“ˆTÃ$)ÐÀ&EâR"¥i‘½SÒvÄ›q5ù1(²Ø$ˆk+ó |I €†BJ¤4)¢³Àú(Xh,,HCâȽ”Ö úˆBEËÈHŠøÒ"Þ` LŠD§D*õ\ÓœóðOŠü˜Éÿ)HÄ0$R"ÝÒâ@¥Äá˜YùQ’!++¤@—IJ‰ôJ‹Lµh%EHZ&=VøbV8OÃI‰¬ƒô¼ˆÑ¤ˆ')"‚)‘ €èš™ÈO‰Ã=-·¤ˆ5%â€b _Jdbâg"?%ó´8œ’"(-ò“X$@Ñ/)‚ªc¢ %Ž&Å!”ùI- €è”¡w£1‘ŸY%˜F“âPLŠüÄ¥DF€¢SRd‚9‡‰ü”(ArZdƒ!\@`Ƥ°nì€ Æ†URdgâ'µH€b _J„‰‘G“âIŠ$‰@@ôHŠ(—2‘ŸIN‹£Iq “"? ×LR"ªs˜ÈO‰¤¦ÅѤ80€Ÿ•‰Ô"ˆæIó.g&òSâhRJI‘´”È@ ´N‰˜®a"?%’˜G“â&E"##@Ñ6)b¿Þž‰ü”HZZMŠ”YY™HN‰ŒÄ@Ó”ˆÃ9Lä§ÄѤ8„’"i  €h™q;‡‰ì”HRZMŠ”ùùɸ €h–A ÿp:‡‰ü”HJZMŠ“AEéScD»¤ˆwkù)‘„´8š"%BéI €p$E‚rà]‰‹ L@I0ÄÂ` ©’Áʬ£É/ŒÐ“þ¤È„#Å1áK£L’ ›R“"@ ½¤IˆLÄÌ+a¶a-F!0‚$>hBDfBJB&hz„¤ÈKˆ$LxhBS1”åB (Ý1AI$%E…"βOº"”IM‹4ä’"$%7žÙƒ'F'EQHqˆÊ—LLˆºÌ’‚•Šp VI~0’5)‚ËF&XÝŒœáR_š:I‘‰‰‘ àé 2 BŒHJ`“´¥LpgbDh…(€`¸u0•HÂd$E€jIV$ò31®£± æ0!’"¤ÄžQ›‰à KR„¶au2¬fF)Á53<-!<ÕÑ&)2!¥=”B–ÑåÁrpEðäȈœáÉÍd¨:D*'7)ÐKŠˆ"‘˜æ"Žn “RMtR„UÐØ’"RÁ­ ¹¡DäòNI‘ORDªW™±&EXÉÆÄˆž‘ËV쉜‘¢¤@C+)¢¤DÂi=)ÂÒ qI½‚Æžq·¹0ÚŠ\žŒ0FRd¢mRDK;ðž.zRD/0™°¤5<å-z›”´´€˜3H „a æþÿ«.kšFtÙƒBQ<èÁÐfDÜKñ9øåã‹ R´â|„ÑSVÕ(~y[eØíØ"€$è{ì xv5÷-IÐAÖÿ/s0ؽ’RIO( ÂÝ¥æ­æ–H“=$ía,™fÑü&Å&€&E`BäGOˆàR’ùIKŠL`$˜˜°%E 04)Â=DJD‰¤'EôAZNüKE¦žƒÆ>|`̦±É bº r¡¤ˆ­H„VРTÈOfR„’¥"¼TÄLŠÐ")%J‹#=)â>·”‰‰1Ó" dâ#;5’–ˆ@Rä‡TÏÐJLAY`®¨‘jk°„ OŠ)QkJAK‰ŒÐ”È\91ºˆ=)2Á'ÿh¹‚ ©V”+sp—xÔ+IJ‹DT©È¡ùi’œÁ¥"?¢p “"8¢§E”&"¬’FTʰ¤âÃ'HmElE"¡ÑÅÑEbCi €–ŠPÔd„'E~XR䇥F~XJ„Pई¥TDNŠàÔ(J}(IœÑKA)[‘H`tq4)¥¤@D$EX ¯©!˜’ùMF¤”ÈM‚0Œ™™ rJ2ÁxGžep‰ø›‹#2)bo ¢ B»ºLH4’nT’NI €ˆLŠðB‘‘ùa2öB_R„w¤!Õ3´’†¥K&ô™M&Ü)_Z$")ÊËC0þ¤(//7)ÊË£'DyyHºƒÑtKЏf›™°ð‘Æn&“™Ð™èT,þ¤ˆY?³Ã8ü°B5E‚™è…"j[‘ ©~d‚wV˜õ³zજ t]ˆ)å¡_R”#|¥"FRä†%ÁHŠŒ$%E&Ìå8L(‹è•ˆˆ¤ˆÒuYø¡i‘©ÿ % 5´Š†w^P“"ÒÐ"¢×+Az5ƒ§HÄw 1¥"–”ˆ-)2•¤ˆ4vÍ„>±Â„®HË0W†!TÑ1)1IǸ"?Ýf[0‹DbR"µ’¢<Á¶"–”È+%Ò¼Û„YÜ1aV¸LHS~L˜Å%Ž`´LŠ„')bγ Ì¶àL‰4HŠ˜E""Q’×m‘—’GMŠò¶<¤am‚iyOJJ^„¤@B@J F“"” ¦ Ey0!æÈƒ ya0` Æ¡bº² µ+‚4‘‡Ü¦ÄºÜ=ÑÒ')Þ¤È÷:ÎA“S$âOŠò Äˆ’å¡lP?”ô¥¡<˜Ç Iv°ô'I”@„èµ@™ \"B’$ArA‘0(‚Ò °0Q¹Û‚’À˜°õOP’"º0š.ú¤E€+s°‰„S"ž¤(ƨõ3”-® å3,QBS(ùAÒ ˜’—‚×ÏòÐÔ¡Àu³<¬ ã€*hHÒ“&É_+¥"b-JI‰6†ƒ<ƃʦGR ¡•‘‹D"Ϊ™å…p'E †$?¤B‘–¡©šAe¤<)ÊCyXùÈ…H}(I‘ åaIr¸q“”h(%E’*g‚IQKR„Œ0Ê#ŠHIÜV÷SPŠÀ¤(HŠˆÆ"·¬æ‚—(¢,VÄ2éIN‘È8 SãhR$1)íf[˜H˜m&H¼Cܤ_D«¤È„oo <1Ž&E“"@Ñ()2a¤D‚IQ_Rd"'%Ò()2±0áÝf-G“"‰I €h•™H›ƒfBÞ eˆ›Ÿœ”H›¤È„ž±ïÇMФ&E€Ë!ÈJˆ´IŠ tˆšqž1šIJŠ4T’"ãàIŠ ´ÈÉDÄÄŽÔ8š±€Iq, 01Ó"qÊ)ZÍ8¢’"@Ñ?)ÊËËÃI$E9 a¸Ó"''ñiq45í{€"=)B×+2‘]*B!m’¢ЦLd‚ÜLJZá©‘h¯ÉI¶”–c0&E9T@‹Ú™¬´8’S#Ñþ Bµað9ð 1ˆbÒ™C^Œ !ÏÃ" 4˜aAjfy)(/"d‚ yA~R”èÝNäD¤EVÒR×MD{ €ÏA#ÖãÀ׊¡®Ì¥=x"”GIƒP$% ÂRÓŸ8Â’$ÙIQ' jJä$?-ŽÌÔH´ˆðÊø œ™k·Ái V*ÊsÀ rRÄL†Jšåái‘ܤ(‡P/%BÓ"++9iq¦F¢½ @DìmTÉÈ+Ä0“"¸dDNŠÐdȃ¨žÁflIœQÓ"µ"R#"%B DVrÓâHKDû €¬ÌA¬TDO‰ˆú–Á4„Í/a,õ3C«fxZ$/)Ê ÈEä”N‹L¤Å•‰ö(@^$%¡u4l bM¸j†&IH¯’åá…"´û"(`IÖ_‘'·‚–# ”`°§DNV&HÁ$%ÈMS#%5íK€¢í7´+MÓÙÒ¢œ,‰ÃˆXS"´D¤,-ŽÔH´ˆæI‘‡ÆI‘Ä„(KZRdœy„™¡iQ‚²´8R#Ñþ OüÁ+h%E9’S"‰I<¦-%BJD ŠÓâ°OD{ €†ôr9Ò¬©I‘GJDJ‹üG×0NDû €†rR”#šq¥DHí J‹üüTˆ±áš‰ö@ ݤ(G 1)bO‰ÐÚ™Ÿj‘6,S#Ñ~ !›å($$E\)R;óóS1Þ†_j$ÚC4D“¢uqIwJ¤Ví<œS#Ѿ !™å¨(KŠLü4‰½a”‰÷ @ Ť(Gm€?)âM‰üü4ŠÁá’‰÷@ ½¤(G€;)H‰ü´‹Äa‘‰÷@ ¹¤H›”(‹3)XJ&©‘xÐKŠ4Jˆ²8“…DhjdI €†TR”£YJ”¬)qÈŽÄ» €†RR¤]BÄ>È„‡n)q(§F\ @C')ÊÑ2%bOŠƒ'%ÙÔH‚“h¨$E9šPBÄÞmaT)qh¦FÜ @ CÄK @@Ëäˆ7)–”8ôº1¤8 €†RR¤irÄ“SJb…#)î ¡–i™q$ÅA—‡Pj$Å‘4“"½’#ÓàM‰C$5’ä@€*I”Lè™°§DZ-‚† G’@C))Ò'9Ê¢$El)QBb0Åÿ N¤9 €†bš–Éyâ… WJ”‘\±?X GÒ@CµM£¤(‹šq¥ÄÁ–gr$Ñ=4„{ÐÔO‰hs€L8ËÄAZ .W‘ê€:IQNŽM39Òr 5%2Á?ÿàèCî‘TwÐÐJŠØR#•"r·¼Ù5"ÁÛoÉ‘d'ÐKŠÝj§DY”(: pÕÕ¤[@C¬­ˆ­MäˆHˆ(ÓÑC-žÂ‘ ›hÈÎ¶Ó õ’#rJ”eF` ’#9–ÐPNŠè‰‘Ü䈒‡WR äH–}4T“"$9ReÀ-%»¤HÿäHžU4”“"öù âðLŠtMŽdÚ@C;)b&Gr"jJ¶I‘^É‘\ hè'EJº,XâðNŠð1*šN®N€I‘‚F"FJöI‘–é‘3h¨'E¤ ª‰#%)Ò$=Rf@ ‡¤NT*GTR¤nz¤Ô€&IÒk¡B‘8ò’""=2Q¦ŸR7ÐPIŠŒ„š‰$5eñ¤Ä™‘$Ú¨a;@ ™¤ˆmr…Ü ¾„8’“"jŠd"V%•¬ !µ·…:ÉQJMŠèI9¹11a¥  !··Wj$z@BMŠ–”d€Š{[°ŽDîÁ’%˜G“‪{[ÈLŽ„âhJ(@Cùt¬U5¾äHD‘(+Ç7š(ÐWĺžË–@ *!Êñ‹høÌAãØˆ– ‰|£5ô@€fIë–@DR$\$Ž6 ÐðKŠØŽ'E"ŠD*&EÐÈÃÆB0EFÐâ&~dgšp‘HQRd‚aÒTÛHO›4„JEl©÷ü ÚX8Á”ÈÇGöhuÓ¬@iI €†VžñLBÓFš@‘HbR¤mšYÅ$@ ©9hÜU2ö²u‡*QE"qI‘‰žÅÓ)#hhUÐx’#ζ#<5U$LŠWP ÷ò €†vMlO_RD-ñ&ÅO ù ¡_A ˆ*q&ÅÁ“†kr !U*R–‰*±%ÅAõÃ/9ÐpW$))b)1’â`.‚†Wj ¡uCu“"¶"-)ŽÎ†ÐÐÈ­ ±‰Cnzød€ÚÝ’’&QE"RR2÷è “Ô@C~\.DpQE"4)»°4@å#FjÑ@Ãa\,JxK QE"I4<)Ž6ô¨hÈWÐrr˜SÒ’"¾"”‰NZLÐE5ƒ")ùü@C¾Û"‡%9b/‰*€”Õ]HIRM312ÁŠIØÊDF& º ¦¶v‰dD°GÖ¢1€ãŠXïÏÀLŽD‰¤¤D”¤eA—.012"Ö!Â’ š,Š&&xrDV6‚ê~€ÚãŠx1ëj¢ŠDY&RÚŠðD†œîà3sð%±Œˆ”†Ô²dBÕ„’rÉKŠC;ÝÐHŠÒÒÒxÆñ.C*‰))Qh›4eI)eÀªj&¤´¯  $EÆ‘µ¦ €†B:<}g‚  É‘ˆ"”e!JS”a¥"´fÂ,îàÉŽ‰ _©8‚ú.Ä0$"¸T$¢Ï‚79.!f%ÁÄoÓ!wNë`&&F1$%ˆÎ ¤mé¡ ÎEBˆ˜¤@ C!Â*hÒ*h4E|Ä¥DY$[¥ÔûL¤'®¡œh'Ed@p\‘pz”% Ø+0šéˆaH$D|0Q©‘¨tÈ„ž21ެ  €†DB'Eü„ËFòJÅ.GNJd †¡‘‰ª  TÑä'EÆQ@{@ C"!BKEãŠúÓ$ÅÑÄH@ C"!‚KE"§ü(MŠL”¤E&Äp6½g‡úp8@ º¤È‹Óg¡RüÄ&ø¨"Þô1º° ÃÐH‰¼ÄMüQ¥‚æåe"7-"OïÑ9)ý¤ @C*)’Ûw&¹TÄž%IK(IiŽá ÇP–™Ô”È@ C#%ò\!Fx” ˜*ÈI‹L裂¨«pK‘V1ÁÒ"Ù'ã “EÄ04R"/1'‘P­‚æ…¤FÒÓ"z©È„šZ˜‘Ö"-C© ‘‘ €†FJÄ‘i2®·Kb”$®­ˆXœˆšbà51æ2SÕ0ZF@C))âå¦ê¸",!’Ó\ĺ\‘{íŒZ$’SA¯õŒÄ0tR"/Ž+Y¨=ñ‡× ’D§”õbˆý,¨‹ÆámE&Öð[U @C1)b­•©ZA3‘éÒÑž‹»hè$E~0ÀHÔWÄÞw¦RRd¢B*¶cãÄ0´R"zr¤ò¸"tHaR¤0 ÷­¨4DJE~t€‘©0®ÈÄ$+ÇG()JÄ¥#b»@ ¡¶"–äHí ZŽoZdb’Dž?¡q AÜ94"@ ¥n fr$ióÁ­~ „ˆ--Bªm&ì4õS ü®+Æ‘h(+b¦F’¶¢â«˜e)%-‚“jýŒ¯%G^bB½vm¤€zI99’´1wqˆ’Ái”þ˜°7‰ì(3aIcÈwû1Ñ¢@Ò €†Ê4î‘‚qE&&ԔȄ^ ’•GY €†ÊÊÜÉm”›øR‘ ‘‰‰Œñö[$G“" @ •õЏ“#úô Î¥;XkfPr„&A> q4%ÒÐPÙP@Êt ž’h‹ ­•8šÐPOŠðo|ãŠè¥"¢fÆè¯ðŽ6 Ð Ü|*@@™~!°°ç 6à³i´L¤5 ¡²š@B„ÍâK„R¢ÀhJP@Cåt‚ÉßaÝ8/V- Áz|“©Õ4áÍ/d‰£ ‘. €†ÊIbS#áMX£Eâà4ˆÏW”$)-’Z*Y$JŽ&Dz€Ô§ÎJJ“ˆ_™ƒR$â6p4!ÒÐ`?‹›¤Ôˆ½ÍƆíb5 q4ÒÐà¿¡@’´¤ˆ™IœI+G"½@ ‰{[$%IKŠÉ%)N‰’£ép@ •Û¬ˆH8·¢^¬F !JަÃÄ0„ÜŠ?9b߃…åb5<)q4  †¡å\PRÁðm DºX 9!¢ 9Z0 †!èf\i†@rDK‰¨Æ¦ÂÄ0TŽ#ùàKŽ Qr4"@ CÛù’XR?ŽäˆœGáàÄ0Lü!‰ 0“#jBøÁˆa˜ú 35bi%Ž‚ÁˆaXû[RóA ˆaØû--ŽFù`Ä0<‰HŠ£>x@1Œ‚Óâh|b@ £A0  Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8   Ñ¤8  0!Ðr5ÑðRlIEND®B`‚procmail-lib-2009.1202/doc/article/pic/mta-ube.png000066400000000000000000000454061130547513300214210ustar00rootroot00000000000000‰PNG  IHDR•îù‚ gAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEu’uèèùßßõÚÚô¨¨ã99Ì==ÍBBÍÅÅ펎Üqq””ÝÆøÆ¾¾êk…k66̳³çiƒi™™Ì̲åååggÀÀÀêѺÿfØ­žÌ™þÿþ))¤€€€™fÿÍÿÍýÿýÎÿÎê÷Öûÿû???üÿüÏÿÏÌÌÿ33Ì™™ïÿïìÿìòÿò÷ÿ÷áÿáúÿúöÿöóÿóÙÿÙøÿøñÿñõÿõÜÿÜÕÿÕéÿéëÿëÝÿÝÑÿÑÖÿÖÔÿÔâÿâäÿäÛÿÛÓÿÓÐÿÐæÿæÒÒÿÛÛÿÔÔÿØØÿÞÞÿÖÖÿÐÐÿááÿÎÎÿääÿééÿììÿïïÿññÿÏÏÿÍÍÿßÿßýýÿîÿîôôÿØÿØôÿôÒÿÒùÿùööÿçÿç÷÷ÿùùÿ²²²úúÿüüÿççÿææÿ¤Í¤eeL—½—œÃœ™¿™–¼–šÁšÄ•º•ŸÇŸ“¸“’¶’´§Ñ§«Õ«£Ì£ŸÊŸ¨Ò¨¦Ï¦©Ô©¢Ê¢³¤Î¤===¬×¬­Ø­Ž±Ž®Ú®Œ¯Œ¯Û¯°Ý°‹­‹‰¬‰±Þ±‡©‡³à³´á´†§†µâµ„¥„¶ä¶·å·ƒ¤ƒ¸æ¸333‚¢‚mmm:::^^^¹ç¹ºèº€ €»é»Ÿ»ê»¼ë¼~~ÿÖ›„¾í¾þþÿ½ì½|›|LLL¿î¿òüÝ{š{¿ï¿ÀðÀz˜zÁñÁy—yåÓ¿™™™ÂòÂççøw•wÂóÂv”vÃóLJ‡www‰‰‰OOOuuuVVVTTT‚‚‚‘‘‘IIIÃôÃÄõÄrŽråå÷ååøææøááöãã÷ÄöÄââöää÷ÝÝôààöÙÙóNNÏFFÎVVÐÅöÅÖÖò]]ÑQQÏ``ÒÔÔñKKÎZZÑSSÐHHÎ××óÒÒñggÓddÓÅ÷ÅnnÕoŠoÐÐðkkÔrrÖ||ØuuÖÎÎïyy×l‡lÌÌïmˆmn‰nÊÊîÆ÷ÆÙ„„Ú‡‡ÚÈÈíØØØÁÁëGI ššßŸŸàèè踸éÌÌÌffÌìÿÌÿÌÿÿÿo—+GŒIDATxÚbø? FÁ`Ä0£`ЀM•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€¡©òï_ZkH¿ý<áF ú`pH3—±¨E v£Hv=¿`wvç õTI7?=³0ÂOdEŽT ÏÁá4þìM^†À#€”ÙЊÂâ©’~9 €èXƒc‹H “%Tà/š™ Åɶc±KyŒ’1UÒ:FÿÝh4UÒ$UþG®ßé”jþŸT @C+U¢iûKØÌ¿ØE$UþM•D€M•Ã%UþF© 3f’ ÂÀÿ?zhjŒôP ½» âø+)”+ˆua)ÂÙéxpl4’!y€–[Wâv›ÀtvªŸä­Q–¦¦Ñ=¼¥’ôå¨'‡É@ž*ÿ¢…-zªùOiªü'U"ÙÑYF‰E*ôvþbi#£–!#NW¡K¡&Ûÿ˜Iæ?ºùÉ[€c׊¤3#QÐ H•˜Aˆ+*ÿb„Tù÷?ÞTù5¢F ç*±”²XúiHéÆE*{°¹ 55 ´¢ OýÅp:†j\©—V”$ø#÷R}S%æ˜2ZE‡‘ñ©*ÿcæÄHL¸Rå_’R%Æ€9Î1tÌÚ[Ç‘*±dá¿A‰7dq$K|Zá£v¯h*h€ËJ £…4Öúø/•R%Z"B‹¬rä×à8S%zòÃã*T)ü©’@ÈâH•x#½‰=’¨hp¦Ê¿h¹[…ü—p¿g7©ý†%‚þã–£bowªÄé*ü Š’T‰àøS%Z5@“¤@ƒ,U‡:©Wõ‰+UþEoYQ’*ÿR+UþÅžU¨’*±8ÞT‰Ù:¡AR A™*ÿÂ[ô¸+ä¿„Ç@ÿâK®X*Uj¦Jœ©€ÔTùŸ©5À ”•tH–4Så_x‹_3‘*©ò/¦Áø†Jè”*qº {OâT‰à„Ú•맨žTh¥Êÿè£Å8R%²¾Tù—PQ‡QSƒkCz=ƒ#U¢/ûÄè)N•XW­aóQÍB|®Â>f„Ñ"ÿ‹%d ûçhŽ.é\c^”€ðU¿èõÍÜ«d±åeÜ+‰ñµ~P'ÞÿâHkÿâÉ"1"ÿb™ÛÁ=—þg{«þbŸbDñã_¼ÓeØ|‚b¸œ†ÍhZôvhìÀ•š°ÎÑýEmÑàÜum£“þb®ÿø5çàÙ9 …sózÃaW¡ûuî3Ý¢›Å'X›çQ Á¹ô… €F÷8ø;„6¨ÑÐhªM•ƒÐhªM•ƒÐhªM•ƒÐhªM•ƒÐhª°4ùw4]â4š*GÁà4š*GÁà4š*GÁà4š*GÁà4š*GÁà4š*GÁà4š*GÁà4š*GÁà4š*GÁà4š*‡ À¹º‡jRL ÑT9$“%&ç/n¥‰2"08R%@¦Ê!(‰9¨ï/y‰} @¦Ê¡™*‘wË‚·Z ‘çÿÅ8ã v^% B9.óÿ_TUh4UÑT‰œ>ÿ¢AÒBð/¢rþûžˆÿ"4#©%c$Uh4UÁNÎ_äÖ$"é¡ýý’*ÿ"ôýý†Íý‹¡j @1 p0®1$³¨ü‹ž(Ñ„0ŠJ˜F¢üÿµþ;à‰ò?@1 x¢M—d™ˆ½è‘›’HE%ZÛq ¢êFhþ‹’*QT  A‘*GÓå@÷èÿžQ! N•°Ä9š6¶pø?¸îO A*G“å(@4Råèv¿Q€ hЧʿԱé?: íü¢ÿ Fÿ—„á¼AWEr@ƒ=U’•q&:ìw}"¯†¸m _¾ÀšÎp¸‰0ï/B–”‚ÝõÐl AÒ®Äf©›(ÿãK”ˆtƒr­ NˆN”˜y‚ýj¢„ÿb‰øÞ8@ ò>øßÿ(gàýGxÃrä2Ò=\(Z‘Ф3úЭE8Æ~<9zÿ‹˜…F=Fï/êô2â`½¿Hc…i“ÿ›Pѳá_úf\ €Çx%¾êå?®Ùˆ¿èŠ`£nQƒQæ7ð•†èÓW•ýÅrg¬lù‹Í (y¨OɽœHY Ñþ< Žvæé_ô:ú?ÊÑæQü7R%@ êT‰(òPSJ²ü‹¼ÿ"×ÄÿcK•¨ ¤õ7q¦JTƒ0Rì_ô\ó÷?®T‰>gMNqˆjúdâôiH,ßÿÑ* Dr¤Õuc$€Ôs;Èlw*ýÅ’*ÿ‘*Q…Pe1Rå_bRå”2Í,ÔT‰z…$™uô_c‘²j £rþû=õþGÏ@ƒ!U`ÖŒq€AøÿG_èZ—N]u3§åç+:9lÞ p(L(׎eH¬j²µ ¿-p7R8j„ŒD€ž(ÿŒäT @ƒ#UŽ&ÊѲÐ Ø·ó#BF%þ²ÿÙ(—ža4&°Þu‰ud €ÁÇ¿þÂ?$••øÏÎÀ¥Å¥c#ŠÄ&K€"7U µú£Iðie%ÞăkÑþDI(™Ò< €b ?M QÉI£e%©e%¾³3Ð&¦P6DþE™ý _øùyÙÓâ‡Ò©š @1P˜(©à¢Ñ²’Œ²÷ÙHó[ÿÑ—b Ì@¢&俸k~ú$d@ §IŠ4ZVYVwvúŠû¿èkñÆöÿbLÕ£-§¢c2@Ä@DI‰“FËJËJ¼ggàJ”ØküE]ăÞÉÕÒ$Ù.-+IkW8;i=Ê’ÿ¨ ã‘—€"ŸÎöÿ/1E% ’2 ª&J²œD¸¬Ä6¦IjÉó—âÄOgW æQtZ$d@ Ôv éNúKLdb‰Î¿H˜˜$…5Qý…&•¿ÿÉt)&àt©ã•ƒ?MR–2ˆŽ!ÍE‰‹Lô$Nÿ™,±NmB’Ä2]A’ ¸\1¤ÊJZ%d@ ´r09e%¸ÌÁÄH«»ÐJÊ¿Гåß¿X1þ#ÒßÿȉŠWà04W ©²’fÉ#,LNYI(2‘Ê™¿$‘Iê/Zyû£!@‚+`Ù½Ì&ÉC¨¬¤a2@Ä@+×UVâ¯ø0ÊÊÿXÊJÕ/jrø‹dÖ_r\«¬$ÉC§¬¤e2@Ä@#ÇWV’ТÃUVHR˜&¢“6ÎÖí¢»]$Tà„Ö á\D0¸Q¶AþEšÿ‹¼¡=cÐ6 €b U¢¢zYIA‚‚%),¸î¿ä¸^F’RVRgÍÐ_\«6mCBÚ-Œ<—ƒ8oyW=ý’2 ¥I!j—•XieåìƒKPÓÿ’ã håOìX C„Ö ýÅ97N0¸Ñ9Ç`›Þ¡y2@Ä@«DIÝv%ö‘ÆÿˆM”ÿq”P±°HrI&ü'e( Žz´®ÕCÈG££]¿Cbª"˜ @1Ð(MRµ]‰+ÚˆO”¸“ñIŠ&ü¥¨¬üKèæôËu0KTÄA8H˜ Ù…Èd¦J€b bšDI”Ô,+‡ñ\7k†þX=„|æÙ-k11O¡8M’=Œ@ ´)(éQV‡uAä®ÂyÍšîËuúÝxN«£Ú„6ì$D-@Jª Ú”£e%¥ø ™Û¢& ÚV€b MA9ZVÒ®¬ªi’„Q"€b MA9ZV’PVþ¬e%uÓ$ I €hSPŽ–•$”•gY)DíDI|’ Ú”£e%)øßÁXVR=M’$ˆ6åhYIJgç/5ÊJ¬Gµü'×!$Jâ{;Ä@£49ZV’ÒÙùK²åì²/ÏúK³4IBo €ÐR¥P'QŽ–•$ ý¥FY‰c9©’Äd@T"!%I–TI´“`ik¢-+I/+a+þâ-+‘ïÑù~`ËÔÁpä3ÐQ7á"-Ú@¹Ýžôd@ƒ¥„#Uã$|åhYIÚ :b5ü_ÄjM¼ŽH‡²à<…y$Æ&H‹6à &OJ2 !$OªÄï$üåhYIÚÌÎ_DI K øæÁQï‘@^Žöý®”Ååh·­ Þ¿ƒ#UR’2É]@Xz;D¹ˆ@A9ZV’8³ó^^"ªqœiò?ñב¡R ѱ©'=V™$Gœ€“”£e%‰³àáå%¡²õÂ!Ì[ЯHC¾I)ê­BˆõE8“剒ø$@xúà¸S&á‚’”Õž£e%ÒaˆíÉîGÿ%±ËŽ 0“5Æ ‰ö@èƒcK™Ä”ééé£e%I+†þ¢o&;Uþ¥\å=Ê&¡ˆp-a QP¦ ¥§¶+I[Æösxhà¥=i„hû#U ÍŸ/eWP޶+I^Æömür`S%R2 RAIJ’ ¬©[ÂBJ•„ ÊÑ>8ÉK~ÿ¢mLøT Nd§I! ú„µ¹¥€DJ™Ä”ƒ«¬ü;4ÊÊÁ³f)ZZRe €pµ+ñõÁ‰((UYù÷ïP(+ÿü<ë+‘"Äjœ:“ÐDhndÖ>8þ‚r••ÿòü ‰£û3Hz;¤ô{¨5 @ÄÌ8¢$Lâ ÊÁSVþåááù;*p,CEƒ-UL˜T›„ ÂÎAM˜Ä”ƒ¦¬%Ê!RV¢%ÔA’*1ÉN“$$ €b *“ %Lâ ÊÁRV‚å»Ñ²’²TITʤæ|@1YtÃû?Ä”ƒ£¬6)yÞ½{wˆ”•h3ãäLëà”¦JÓâD c“0 @ħJ|58FA9(ÊJpš¼ÿþÅ¿C#Q¢ÏŒ“œ eˆ/ ðó'/ïŽOo_‘”4ñ´&ñ ËàO“ÂBÄOBUR%–49ÊÊ¿à4yñâŇDŽ&ú—¤$)ƒ à+‚à©òù£;×.›0ñ÷s°¯Œ PP ‘0 @TH•éX倗•!iòĉ‡JY‰¶˜è4)ƒ‘&‘,Rª¼}–™¨tI¸NÚ4¨à"%Iå©{šð²òï}HšUöS ð¸H=YþE-#ÿÂéÿȉ©Ü„µ&q—•HmIäkÞaç–a9wwÕ=Ȫ»‚PÕ]¯º!½î¶¿Ð^÷„Éàæ$ˆ·dÉ *”•øçv(H•@Íh©ò/ÞS  K‚ðM@£¥J|i’„T @ØæÁE¨YVJa”•°JgY‰;Qâ¸ü/žª{"‘Uw ¡ª»^uCzÝàYP¯{òLpsÄ[±bõ`.+ÁÅ%1©ýˆ@¼)“È‚’”T @XkpÚ–•ȉ[Y‰#QÂÏwÄÜႯêî'²ê.%TuWënH¯»û/´×=s6¸9 â­^½–Öe%e‰dqe¥Ñ)“Ø4IBª ²jp ËJh›WY‰Ô’ü‹íìð¿hëÿâ­ºûˆ¬º«UÝ ðªÒëîý íuÏžnN‚xk×n"¢¬$²ûF£T _xªüûŸp Ž6d™2‰N”ħJ€"«ÇRV߇·)q—•ØûßÑ0T”@ÕÝCdÕ]F¨ên‚WÝ^÷„¿Ð^÷¼%àæ$ˆ·iÓ"ÊJbpÐ(UÍ ”*q$ì)“Ø4IBª ²jp,e%ÎñJ)ôñJ4>ñóàXËÊ¿D. j'yIzÕÝ ¯º!½îÉ¡½î%+ÀÍIoˆÁ_V‚ !\V 2‰N”ħJ€Â:^IB»ò/bF‰…4·ó}nç/¤eù÷/Ö¹eåŒvå_â–µ¼$½ênƒWÝ^÷Ì¿Ð^÷ŠÕàæ$ˆÇÀÀ@ã²’Ü!tŒZ”*qêÄŸ –ŸÃ÷í‘&IH•„õ ’úàT_3„«]‰ãÞÿD- j&yIzÕݯº!½îÙ¡½îÕkÁÍIáËJª•`ƒ¤JÉ9e›(‰O•„­·CZœŽë+ÿb?&ê/5Vóæªº»áU7¤×=ï/´×½v¸9 â:ÄE÷²’üSýÿâßLF°‹X!,LÝT @dÍ8Ò¶¬$cU%Vófªº{áU7¤×½ä/´×½i ¸9 âqqq.+‰×'ö(!²Ï¸Â­“ø‰èÊ*§J€"«¨²wDS¾š7ƒPÕ=^uCzÝ+þB{Ý[ÀÍI‹ë!á²’È5Py&R2 rT†º© €ÈªÁ[Y ŒBŠWófªº'ënH¯{õ_h¯AÊʇß謤@O„ÛtÔM•DÙš¡Á³oç/¥«yóUÝ3áU7¤×½ö/´×ÍpÜœñÞ¼y=\ÊJBÊhš*ˆò5CƒdßÎß¿”­æ- TuφWÝ^÷¦¿Ð^÷!.psÄ{ýúåp)+Qjp!:§J€"oÍõì§â9C)ZÍ[H¨êž¯º!½î-¡½nx)+_¾ä#XV{dÝR%–z2 w @äÍ8B¤u©•,)YÍ[D¨ê^¯º!½n†¿Ð^7×CpsÄããã#XV½áƒN)ò/–Á%Ô•ô¯Áˆ¼5CÒ¤ŠÊ”•Àˆ¤`5o5¡ª{¼ê†öpþB{Ý߀›“ ŸàÐ)+§ÿÅ?ãHÿ €hPƒƒ%)ɒЧý%5o¡ª{5¼ê†ôºý…öºß¼7'ApsÄ%TVí[¦J‚³–¨É€ò6©© €È¯$"MŸ,©RV8>pÕÝF¨êÞ‚š&>ü íuƒ¤â¦Êß„ÊJ¢};©RûÙ•tK•DÞŒ#5%ùe%r²“ÀhrR Jf…ñ†CY9Ð3ŽDl £vš$£¬$2%J¡ƒì”ßÁTVôŒ#@‘Rƒƒ%©ž(I)+)JXSçà9åwËÊ¿ƒmÆ €ˆq$TV’&‰.+ñ¦G|í Jšÿ²ò/}f‰w!@‘2^‰§¬¤ QQ¸®sÛþ"' 'Q:&LN˜ØTIõGR\@ÄŽWâ-+)I“„ËJ¼)·.¤ÁÉ¿èmÒK˜C£¬¤ÁŒ#I“ÐDÊŒ#®²’²DI ¢ð×Àxæ_Äàä_¬íÓI˜C¦¬¤îŒ#‰“ÐDl Ž»¬¤0Mâ-+±§l•8Ö268ù—Ø2øïß‘XVþýOëGR'¡ˆ”ó+±–•'J|÷)H`M68 :,'µAçÿß8ø;ËJ\©’Z㕤OB±©GYIyšÄSVbIzx{ä˜ýé¿yÅ¿x[­ôL–ÿ ¾²ÏÍ&"Ô˜q$c €9 oYID‰ó¢Í¿„ªW¬ýÔ¤ù<¯H åŠ3édN»²ò/q[w©4ãHV ¬›6„ˆ*¯©’&q–•‰÷<žNÐ_Ð’ BgëÒ¯´ü‹|<ì_üç£\Q‰œ («Á…ÈK#„#Ub:vA4Õ%® ܉J”xØ¡ ¿«•PôK–ÑNâü;ðe%Þ°†Òɘƒ&;‰žT‰ê`ª'Lj§I\e%©ÝœÃÿ6ÔK| FY‰ûxX’ÊJ2Ï' 2QþÇ–Hƒ&7–T©¸&Òi…ÔJ”T(+ñOJžT¤[Yùÿñ°¤••YÉ:8ƒØT‰’ Șƒ¦$‰6Çh¡%L,§R-MRØ®üCÔ9þy z%JØäè_,Gj“SV²²²±‘ž0ÿ•(áÉïŒ#Þ9h Ò@1àr ®”IõDI|œ´µE¸Zš„††hVÃÐýE;&–처*ÙÙÏ“–0IL”Z8kpüe%eI €ð¤IŒ„ ;­ši’„ñJÒf^p¬Å@KšôF‡/Æ~”6Ye%0UÞº~Ž„„ù—ˆD‰ÿx‡…pÏAS–Fˆ¯“°¥Lj'JRævH-ÇþâIšXËcÚ !·%©Ñ®„§Ê+7/™0ÿ{È J NÚ4åå@1Ì,è “Êi’Äyp2fªñ¤L:σÃ/%êšQBÁÆ’*o\¾JDºüKÒÑ—ˆTIÚ4Åi €þÿÿOdÂÔ¢M¢$uÍYËt‰YÂNû5Cÿâ=–´²3UÞ»K¨ÀD-)‰)\µHŸƒ¦B †ÿD”â@ý4IÖúJï '´txð-c#«¬¼w÷ñƒ'xæ_²ÎÖ"išå@1QˆcO–Ô›k /A‘³% we>0[ËþS¹¬¦Êg/žâL˜É<¸š„9hêÔ¥Ä@L^Á’*©9FI%Œ¾ÿNñÁ²¥Œ†e%0U¾ÿðkÂ$7Q☃†MBS?Qþ bKqÔdIÕyYªíq$m3ÙàM–•ÀTÉÉÉ‘0ÿ’ؤ$4 ›„¦zšüÿ €ˆWŠH•T^-0¢öƒÓ§¬¦Jîo¨éò/¹i5Ub$Lê'ÊÿÄ@šrp²¤ö:Ÿñçÿ€”Öà¨iqàÉië 5–ó¨Ø †ÿèqÎU õmÊJ,JòÓäÜÓ)¨7æQsx €CªeMüN£²=]ÂNO¥,MâH™TO“ÿÿÐp)+‡f²¤a»©ÖÞÝEp šês+4ZVѲò¯ÁÞÎ÷ïÔ¸ÁŒˆ”Iõ¹€Â‘*ÿþ-+wYITªdaa¡BŠ$”2©?á@ 8åßѲrˆ”•À¸Â•*ÿR=µè3 @ 8åhYIl²$¢~Ä)OiY µHbÂkÂ?(E0Pggg›èh''';;; [[ÛÈHcccGGGssskkÜÉ2<\[[ÛÔÔTWW×ÈÈ(*ÊÌÌÌÐÐPOOÏÄÄ$&ÆÀÀ@ TA@ ¤¡ÍqÄ@^8–•Èî'Ü3¡EY‰I$߃K~ª´ ÕÇ–*ut¨–*h0¤Ê!^V"Ý_*&Êÿä–¿DÊR¥¾¾=z²Ô¡bª ìJz&Ë!^VB²0èÄãïhøÁ*W|EéÀÝMFqª´·wp@¤J++j¦J€ ©r¨—•aå!4uþ‡¥ÎÿDýñÊÁ*\\\ÀÉÒŠº© €°÷¿éš*‡À_=CR%´÷”Bñ¦Jrìl©2.ÎÒÒ’Ê© €pTHò"à¡Rà_Œ´ø—¨¾Ð€€A*ˆûPåhª$¥ ‡¥Æ¿ˆf$¬… o`ަJR%@1ਿGSå0ƒ:UΖÎhĦÊJ•Ä€»õ=s£©r€R%@aM•£ ËÑT9 © €°tuþ¦Ê‘™*‘®ö×\0EGC (¤Tù3Uþ¥Qª ÑT9š*a©ò/°¤üû×Ùù/°¬üíôXV"¥Ê¿˜©ò/­R%@1`O”£©r„¦J5ÔTi70e%@1 µ*±±GÁˆ©ÁÁíJDªü M•ÀÄJ•ÿ‚Råß¿ T §Ê¿i*ˆ³¨” Gn˜*Ç/l=Æÿ¿ˆ9ˆÿðÉðÿƒ4wcïíÓ¥³3¤]é¢ ©òodä_pnþ×Üú¯uè_`¢´·§Ê¿4)+5U‚)9ˆsÿþý7<µS%8%-KK©ò/q58e%)© 3çn ÄÐa¢l‘I؇°kP¥¿òé~¶ü•Ïúí:w¢r“N¹ôäy§’¹W2ÀT&ì¢í8:ÞߢÒÙ‰¿•ê”E%˜J•‹J°<œu§—gè›ÊKÑ1Ujâ'TõjjR5YL•ƒ'QÒ{ü/$UBN vrú Z‹naû×6z|%hÆ’*‘Ïú ¯Áÿ‚kpðŒ£hÂñï_ÿ†õ•¡3ŽÁáR%@®ÎÄ8-«p¼5ø_ŒTù4nO•úàT :iœ*­à©R–*e%huÆ_pYùZVBRå_B58@¦ÊÁœ(iX…ã]Ɇž*ÿâH•ð²oªü Û!M•À¢’@Y @£©×Òµ‘YV‚“%Zª„žˆ/UBvH@jð¿„R%á €ˆ;ý ûÆÖ!zð iWþ%<E×T ¯Ÿ@ý´ÇÜÛ§JP»ò/tã_XotR ÖÞ¬]ù\ƒC2¨ÁˆðéWXÏÎ@¨-+)Z„1`ÝA=·@Dœ~…5UBfù;ËËA4^ùwpWšT @Dœ~…80å\èIC£}p&Ë‘š*ˆˆÓ¯þa9¿š*‡dË’Êóà)ª¢ÿÔf‰A*ˆ¸Ó¯þް²òïÿÁ,iº–mP§J€"|úö¨ÿ"ÎKž{éÕÁ­æÿß»’ €FÇ+i:8Ê‘ÈE&rù‰µE_ตì/Æ D%ûR²Á”*‘Sæß¿$ !#fòÃ}ûÙ ïq¤þ<8@ Äxåߢâ=ŽÐN *†&D8þ‹E ®”>ÔR%VgÐè(:åE&zÙ‰†‘R%AÃè—,uª ÑTIDI¡äD9š*ÿÐhª¤CªüKR¢d©z³ ‰©²=Uþ%2UÐhª¤yª$²°üûw°–•IO•Aç ‘~%@¦ÊÁ’*é\…“RƒS¥¬$%UÐèÙôH•I0pS%dnÇùï_›¿[ Ðjpè·Áw“ýŸ~åò<åN•[ Otž=ý <¹ó>¹óWáï_Ü© €FÏΠ}ªüOç)n²gAK†@kÙÀɶ’ ‘*Áóà »É@Wæý…Üy J– ó€©ò/äœ!È-PØÏ‚œ¨út‚%âGÌT @£ggŒ¦Jä};àå°Õ°ûÁa©ò/lÆñ/¸¬D¾Ç’*ÃÑS%€S%´‡§J”ÛE1S%@žAûDI÷õ@ä—•jH©RV¢ôÁ¡·ÖÃËJ‚©º’ÔT @£ggÐ!Uþ2©ò/¾T ½óö/îT‰¿ÿKtª Ñ³3FS%JoÖ®ü ®ÁÿZ@FvÞ"z;°;oA'ZÁo­÷v`WÞþE:v5¨·jW‚0ŽT @£ggŒ¦JÊV²Ñbn €FÇ+é“*ÿަJR%@¦Jz¤ÊÿÃ'U‚G†h*h4UÒ#Q?_>º:h4UÒ•ÖþB‰¿#>UÐhª¤W²$.Uþì58]R%@¦ÊA•*ÿÂ+r(‚ ýEL“#Ê^ði‚ÿ"iùûÍœöêT @£©rðTá•8,U!Ò*jÂEeÁBéDŠÅ]øâL•©²fˆ²T @OtA=ÊE÷é-£©’ÂÂ-Q"UéQ›žH$4Q"Ñðâõ?þö®Tù÷/5ÖWR˜*ˆàÎ[È߈C3FS%íRå_´æå_¤.FÛÞ7BŽÐ”‰”ÿ’Þ® e%@N•¨G¹`¿~d¦J’ÆpWáÿbIxÿþÇH–HIö/jŠ8æïÉûŒã_èúJÐyA©ò/t%èL6ä³~i›*ˆØT Ûí=š*É'6UþE.4ÑZ‡ˆ6æ_”bѲü‹–pII•ÐÕÁ÷8þ…ž3YñrÖ/½R%@“*5PR¥Æhª¤Mþ‹P÷^¼¢ž§Üÿ‹Ô!B®Ä‘*p|å3¾•làT Z] J• ¼:ãï_ºÕà4ZVªôÁ±¾ZV:ÁS%¸¬/¯¤Oª búà0ŒÄM•´®ðr}%f J–t¬Áht¼r4UbY_ùÑÛ Ž 6þû÷/½jp€M•#´ Ôs;4š*Gha9¨S%@¦Jú%²ÑTIlª ÑT9š*_ª ÑT9Ø–‰MׇOª âOtÁrtÆèÙ´/,‘ÆÃ ,F© €ˆ>Ñ["M•4O•ˆüÿ¼›ùï°I•D GJ•ÿ¡ï¼=Ñ…öU8êúŸ‘’*ÿ‰.È78¡3ôoô”ºtþc¦Ê¿°•È Öÿ«T @D”•Ð$‰rÆþè‰.ôK•1¸QV«ÿÅ\<ÔS%@nW¢8ZVRÔu!QÓ_Ì•èpüËêÊá’*ˆ¸>82!7²Ot!o˜ç/Ùø´=(Ü¿$›=¨S%@ŽW•Tù5ù¡¤JB›t†Zª ÑTIçTù—äT‰T ¢´#›Çþ·ñJ€M•ô]jANª„mëFZŽ´ñuã#y©RC”(54@©RCcàS%@¦Ê!*©®v°§J€M•ôN•4Ji¤:gP×à4š*é›*iUX’ìšA*h4UêT9BW²Ðhª¤{ªü;š* ¥J€M•ô.òFS%áT @£©r4U¾T @£©r4U¾T @£©’þ©òïhª$*h4UÒ½ÄM•S%@¦JºƒÑTI0UÐhª€Tùw4UâO•4š*Gha9¨S%@¦ÊÑT9øR%@¦Ê‘Z…f@£©r€ ËѤ‰Ðhª€JzµöhêÃh4UÒýïhª$ˆÀGJ·0¯Ÿ~›%¸M”„@á?;ãžÿâáý#Zn¸WަJü €ð–•”'–A˜(E|4UâD(Uþý÷NÁ*YÈÉWaHý ;·àʹá'»ýE;j êI#¥>š*ñ€"Ô®ü‡|²Ë_äzFÁ’‚—äÓý¥ ‚«9©òÿh¢ÄˆpY‰ þ¢Ô먵¡Jôé,"T­(Êÿ¢e4BRåèh%~@DÔà(,x¢C;s3U"ªò¿ÇgýE—p•C)URž¦FS%>@ÎdCÔ°ˆV%¢JÆZT¢*ø‹R[#¥Ê¿Ñ:©r4IÑîT ëÀ»%Èý”ÈÔ&(ªä³Û¦ ôŒà6Œ |àDôÜÎ_F€ÅÐpJ•Ø çá\`‘©ò/þä4”å I•ÿþ%úÌ‹¿DŠ @ĦJü‰rH­:HR%)¡Ž°Dù €FWg dª-*±€M•š*áç›c\ 2°ùFÔþEƒi&M€M•60;¢õŒTøÕHrÐS~ÿ"”¡œó Óöÿïp)Ah4Uàp%Ò!çX®†@*O‘R!âh_”ƒûÉ8}€"/U" d"'GS%9ÍJÄ•xèWC RÙ_X¢DN°Q.ß^mM€"œ*ÿb[m‰<‰Cçiìa˜*ÿb½)U"5-QÊOø|úßáÕ ÒÊJ¬‰r¨]5(Rå_ÔšÛÕÈ…çÿ¿Èòp}Ñ*õá’*ߌ#|M%b-äß¿£©’:©ÞyF\h‹v5r5¼-ò/RIÅpZˆ@øWg ­MÃRV¢L€ŒTIÕ¸]ç ÞTù[ ½¬¤Â>Š‘›*G%V@Ä¥Jô¥¹•÷hª¤ u9 Ð@áK•(Û#þbëŽÿÅH±ˆýô]49TkðQ€ ÁU¿‘výŲÆ¾O oª¿¦Ê¡ ˆNs;£©rhä¥J¹ÑT9è@ ïT)‡‘"@Vvp$JÚ$îa‘eh˜§Ê49”™–L“ƒ$U"V¡¦Jt@Ã:USaš ¤å‰’jëØþ“¶è”8’%@ ûT‰ ä¨(©Y¦ÑdùÙpH•D÷T J²ÿa‰̃MŽpéBO•Ô¨½ÿR±¨$b9:LiʺÀ!„XŒ>lY½S%8õ!R8‰BI(‹Ä‰'UÊQ½ ¤Þ‰¨‘[8—£ÿE‘C^ã‹.]®>LR%@ @ª„¦$ùA’•*q9ê”(É’bsPú<ÿ±/Gÿ‹\Óc®nCúûø¤J€ˆT NLä‰Vn"¥J¤d ©Þa²¬òGQÔO”ÿ©ZTZŽþ­ªGiŠþE5ç/ª9Cд+á©Rö?rQ‰Ú®DTí²pK¿²ð”Œª3UR­›C­Q1R%¶åèH]t”e½±¤TšužЀôvþÃú;h©#í¢¤;DòC”‰°´ˆ¢#UR±ëM¥þbwžåè±$S,-Í¿ˆ¥éÃ%US¥,¼e‰œ*1{Ò(©%Q"%BìI#URu<ˆš©’Ðrt¸Ò^ð¿ðßHB(ÍÓሾ©R9UþÿѬDë¡'G$ý¨U¹,¶¢ò?Õ ÊÿT;¥÷/­‡Gª :§J¤n ´% -ûþ£¥Y”~ j‡½$‹ª5UR{àœ:½‰¿£‰ á<·C“Ùœ¿T6æïè† L@Ã;U¢ÆQ@ áœ*åFå4œSåhšª €†yªà! hx§ÊÑøš €°¥Êá¨P{ÿE¬£s4©‘ˆWƒlèƒA5Ì2š*IÄ0£©rЀM•£©rð€M•£©rð€M•8û9£Ýœ4š*i\°¦J2@¦Jú¤ÊÑÄI  ÑT9š* ÑT9š* ÑT9;ôÃÃhÔbô¾ÿÒ ÷=š*IÄ0TÐ_q0ru÷h N š¥Jjži/Ž â ^-M•à S%Õ"â¯Ò”t‰H‡TO—£©rP€¢eª¤Úù£JJJâôJ—£©r€¢mª¤Ò6U`ªD/.!‰š.¬A•,G“#¹ €h*ÿR+Ub$KPÙXKítù—ê)m4U’ˆf#CÔ-+—*aÖâà„ˆ’.!|JÒå_¼Þ³GkpÚ€¢qª¤V»réìµ8,¢óát*¥JÌÐFS% @Ñ6Uþ§^ªœ6E [§§=aB OHš$¹àü‹_øïhª¤  Z¦ÊÿÔM•Û±ÕâXÒ%: jª„¬¼ütS7œ‡×¬ÑTI  ¦Jê]M•ZÛÀÕøÌtY‹’.kÉO—D–•ÈDã¬FS%Ù €h;N½Þ$Uîû¥yY íŽS£¼$¾GLvn‹Ž¦J@ÑxuµSåú¸Òe-þtI“TIli4U’ˆÖ©ò/µSåÞ]8Ó%˜µ`%ér4U @´^ÉF•ãšQSå”iàQuŒŽÏ0 R·ÏÈòIæÿGkpZ€¢ùúJj\¸€ž*wïTBšî‘‚0 .N£d‰|3âB°¿WG&G2@Ñ~Õ/MRåþ©àz\ˆI“â’tj¦JJ@Ñ!Uþ¥Iªœ: #UH“’tN•£58Ù €è°C‚òëå°§ÊIh©’`¢M•C=öíPš,‰J•„Óähª2 €è²›Œö©’˜490©r´yI ú¤Ê¿4N•Ä%ÊÑT9T@Ñgç-eÉ’Pª$2MŽÖàCöƒÓ0U*›&GSåD¯Tù—v©R‰ØDIZª¤xÙòhª$½ÎΠ$~ ¥ÊÿÄ¥IbR%Fªú;š*ÝNt¡ YJ•JË—“&é*G“#Ù €èwέRå:PªüOL¢$±] K•È—tÃŽF¾·i3–*4U’ˆV©røûwV@•T‰±„HR’Z©òï_´Åk¨Baiò/ú¢Ñœl@TN•axÀß¿aøÙ©Ri9ÚÒ6IIj¤Ê¿ˆÔ‡kñÖ—¨©òïßÑãÑIÄ@‡äHt²Ä‘6ÿ*ý'*aà?ÞDINY‰/U"6HÀñßѺ› €¨*“‰‰V‰^VþW"*U‚ LIIÚ¥Êÿ8‹OÔ {4URˆ²T™Døû—$åˆTù˜.‰L•’’´L•qŸÚ•£€@ä§Ê2Àß¿¤ê€–bJÿ ¦Ê¥TM•°¶à_”îõ_øBt¤M•TDfªŒ'ü%CÈ>%`qù_‰`Y¹”še%¥c˜Go"©2–ð÷/yú §®Ç–*—.E$Ëuƒ)UŽ&Hr@‘š*#(ÿ’©ÚÉÆZV.¥Zª$"©&6Ú€"-UQþþ%W'$Y*a­Á—Ò+UŽz€"!U‡0 é3U~þL§œ¤bu4u‘ ˆèT0`22a@Ó%ÊêŒu t9R\–T9ÚÏ¡‘©ÒÀ0%B›ûûÿ…%K¥ÿÿQÖW®[ ,-?‚T ¿j4aQˆ¨T™:pyÅE*x¦–.‘V²ý_L—JŸ2UŽNvS1©Òoà$9“Ÿ8¸ÀDJ–Jÿ•×W®[:píÊÑÄHm@„S¥ÏÀø HÂX2EL/‚S¥ÒHº¤{ª-!iˆ`ªô8 nSJB[–J’ˆâ–.©´^héRú¦ÊÑI+@R¥ÛHꓕи‡Ýꈒ*EÀuúº¥ƒidh ªô8ðÞù†—°j\Á…¥Ê_"Ðul”¦Ê¿£¥ä „?Uz @:^“ëqÔ´ L•AĬdûKd‚£RÒd€Â›*Ý€Ò%|Ûƒ¤Jqù.oWJ•ħ%¼ s4IÒ¾Té:Д&Á«Ë‘;<Ðt ”%Ê¿‰L•dõ®©yhÁ( žTéM*ø‹¼©@Õ8$]*!ú;ÐÖ%Hrõ(áTInr‚]^2šé Oª &üE%¨ÀÍK%XŸÚ‡Öë@;‰J•£Ijˆ€Â*}ÉᔤWãÀθÃë…C{=¾¾Ä¤ÊÑD9Ô@áN•!d€¿pFþý ÂÑÙ¸%°p¯4n) éßÀ2Åe"ÁT9š&‡ Ü©R ðN@I0õW“[›±ÐÞ¸$´„ A«qü©r4ME@ ÔL”H©)õýUÇÆÆ- @zã ZiÈ6 L•_q¤ÊÑ’ €hQV‚š6n ìéò¿8¼æ†b®_¿$L•_±¥ÊÑ‚rˆ€¢Y Žû‹[_5Ž˜Û0Ê@ÉR|¹–T9š&‡, šõv„þbcã–ÀmºjŠ„P â<–Ž–*Gãvè€Â3^IÙÈYœ„F‰à‹6K5Àݨ©r4f‡2 jŽ¢#fv… Ä_T6v bFÕÿ£.Ué,¹)UŽVÞC5géþ‚»ãuÐÌ0ÿ…¦ÊÑhâ €õê ìà/¤ Ñ”4øWi4M@ƒx%ž5n°5ÀD9…ÃР]õ‹@ªqIÉ£ã°D`ߎÇ`àtùw4QO@„ö8º Z0Ú„¾ €óÎ[¼ 1q4ò†- "ÎÎð„ q4Qg@D3ä7ÈÀhšæ €ˆ;“-ePÑD9Ü@{~¥ÿ £irø€"úTÕÄ€AGåDʹè‰ F“äDÚiý‰AFÓäˆDò};‰F“äHDÆ-PÀôK_8š&G 2oÌKLŒ§M‘#ù·‹KAâh’™ €(»‰”h’hGSäD…[ëÁÉ'™z`4AŽx@ T2’’Â(‰£ r€@1PÕ´D8 #-ަÇQÄ@cI£ñ0 @1ÐÇšÑT8 HÄ0£`ЀM•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€M•£`ð€ékçúú@ ¬IEND®B`‚procmail-lib-2009.1202/doc/article/pic/mta-viruses.png000066400000000000000000000300311130547513300223320ustar00rootroot00000000000000‰PNG  IHDRv— zíqgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<`PLTEíÿíæÿæÝÿÝÙÿÙñÿñÌÿÌüÿüÕÿÕéÿéÎÿÎúÿúÑÿÑøÿøõÿõóÿóáÿáÓÿÓÿÿÿÌ̲Ììÿååå™™̘Öðÿþÿþ€€€???33ÌÌÿeeL:ö/?IDATxÚb£€î €Fƒ`ÐÐh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h¨&;!!j4ÐŽCSLÇ„„†Lø½\ èìb!Úø•\Å„ ÅAJO»ˆa@ò=ó%ý »ÑÒŽ  Ñd7„“éÖ Q)l(ŒA€áÉNHp4Ù D² Ñd7t“éÉŽ¤DMÃd@£ÉnÈ&;!Ò“‰Ú%;€ðd‡èÔBYðn.RwIU’ P‚ÈÝdD¨ ¡Û.!s¶NÌU8ba ŠB,¾Ds(ŠU¨Æâ1 s<ÝíãBHa 7V»w…„0b·3I4ÀÉkL"d±å=äÀB I„nsÑ8pÃÐ…„`)Å0¤t"„ž7P N¸³P &4ÍÝèI IXJ;·cÉX‚ #äÑ݉E‰ ¥(4°É{  & Al€¤S›™BB¨)]5fPìÆȨ­f!„f<Öä—‹Ù‚MÂLvÈnÇaZ°as öh@ 9Ê’@Ñ3Ù!Ô„…#BˆJv‚¸“ zMŠj´¦mhñ‚=°=jÉŠÕø“ þd‚E®¶R1†=s`V(x½‹ÅTJ“@ hi‡‘fP3Vý8£-Ù aI –z°sq$;!‘‹îD!<% þd‡fÎ.¢€­ù‡–B1U¡G’!*%;€ŒÉN5c‘“ì…„pT(mn,B˜á*$DL²Ãè{ x²Ã xêJtïbM¶”&;€”ÉN[²ÄZÈãJvÈÝœáŠ%ÉaÔˆBÄ•v¸ÓçPJvX¼K“d@ƒ+Ù BÇ Æ8ÈNvh­9lmo,u¤ Îá¢B[ÂBÉ›wi’ìhp&;ðX6ð&2lc‚(}]´ä!„'Å öLˆMv‚XÇrˆKvBToÛaÇR% Œÿ`oÛ!”Q©' @ƒc¹Ä‘ìP u)°ÅšFgÛ`ñ] Aœ#_ø;á$$;ì®ÃÑÙ'*Ù Nv‚´Hv4¨Æí°ŽÝŸì„0&1Pf;Ð’ žÊ½º"vEˆˆ:!¬-wÜû8‡–чԱuª„°5T0—w…0”Pe¸ €Ã,… αÜF`¯RáÓdh‰e)f3QKì£ E9€‚O!úTÆì ²(Þü‰uÎ ‹Û…°OaôÓQ²êì%XœI2 _]L`` WãÛj’BŸÒE®(PŠ !´ž,ú$‚ÀJc˜‚MzbB.ŠQ&A0æ_ñ˜$„­/-„ƒ‡ê¬ƒÖF±m<‰ÂÒ €F·ðà.“GÍ@&»Ñd7 €F“Ýh²@£Én4Ù  Ñd7šìÐh²Ãìp†Í@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7€””!LAÚ€Mv#)É’˜ z¢ƒ“RD@@£ÉnDsØŠ:-Eœ!T4šìFJ¢ƒU§ð´#/áÀE ¤ªE¤+„Rˆ8,R%áÐh²)Õ+¢L“B¢`©’ðPS—B©rû é €F“ÝH*íP“f²CÔÃRRˆD*HýÒ €F“ÝHjÛ¡¦#h²ƒ¶êåQ“Rª£VÛ €F“ÝìU SØêXDÝŠVØQ­' @£ÉnÄUµè= X» Ñ£@éL ’Çöh4ÙÀ¶Î† ]Œh4Ù¤4'…§³AW·Ðh²ƒ!(&Ba!’,¢[²“Â%N÷É1€MvH €~º-Ø01a @£ÉލrKˆ¢2’;eàÄH4šìF“Ý€b¡ T7BêGHã 9AE â•к!U(ç"iBh&£Û…j‰z²ƒT¶2‚ùΠÁ›ìÄ@€V­8hBBIHBÈÍ-˜8‚mÈÁ„à©Y=ÂtTÐÕ¢'uAxÛ–æd†[¨#€b̉NŒV€é˜)R!Ä…pj„«@\ØMÆ®{%+3@õ-mC àOu´äHGI^ˆÎ)jò "Ùa1ÅdjP’¤¨—t2Ã/Ô‘@1 DGý@@K Bè!j$;!ÌÒŽ˜d'3P¥ÍC ÃItÔ ¼ÉN‹¸ öd'„ÝÜÉŽ`%;@ÉŽ¡Žˆa¥:ª¸*oîC¼›)„ÔëD¨ÄÔ©Ž‘ÍA5ÕdT5=Y¤áb™;¦C¨#€bZ‰ŽN­‘èêÄ0ôü?šô†~¨ÃôþhÊâ¡@ CÕûb£ fè†:@1 Qÿ &»!êÄ0D3Ýh²Ò¡@ CÕû£m»!êÄ0dý?šìP8 ä¡@ C5Ñ Ö.…Ì€­&-Õ l¨ÃMuÂÔÊõôežµ^“4S;ÔIÄ0Tî &üAÉ׿a!!Aìû%„ð&;ÁÁ]ÚÑ ÔIÄ0”Šÿ…)Mux—ª£r„p«BŸl•AY$L¿õšÄ—v´u@1 Ñ¢Ž¢ÒNWR"%ÙáZK"[”޼Œi0•v´ uÒ@1 Ñ¢Ž¢Ò^ÅÂVœ A·E!Õ½TJQã áYÂ$ƒ±~If0•v4 u@1 Ñ¢Ž*¥|­9|IêšN$$EHkï°';ÁÁ[ÚÑ,ÔIÄ0„ªÿ),íÐb Á7‚!íÄANvˆfÁÒNp°–v´ u@1 …D‡%ÓQµ´CnÁ !ÓhÉk:B)siGÓP' Ã-ê¨Ú¶Bî !V !äFlÓ« ZP¥ç:èz²4 u@1 Ñ¢Ž²q;l½R·÷ 2€ß×´uÒ@1 ‰D‡ÍÿÍR`¦;¡á”êÄéê$€¢{²*d: g)†#ÀçkÚ‡:i €$ÙÂxü/<šêˆ÷7ÍCD@–ìˆ |Þ-íH-íh꤀Ðd‡?„ñû´´#£´£Y¨“h@ºD…ï–v¤”v´uÒ@ XO–@ ôÿhiGFO–f¡N" íÉâÂÞ-íÈëÉÒ&ÔI4à=Yl@D¦“Muä÷d©ê$€ =Y´0 Êûbò£m;Êz²TuÒ@ @²ÃDe:ùѶi¥CD@”ì°…"gºÑž,‰¥­C4@—ìP3R •éF{²d”v4 u@ TÛŸŠp¦-íÈiÛÑ0ÔI4ð³@¯`ïSáÍt£¥Y=Yš…:‰ €E²C ¢2ÝÈ*íˆZ•ElO–6¡N Ovˆ@ H™nd•vBD,$©´£z¨“hP$;p1¢2ÝH+íˆHx¤”vÔuÒ@ –di`à ÔLG^i'4ÄUK;ª†:‰ €Q²Ã[Ü£gº‘XÚ Q½´£b¨“hˆ$;ŒL7òÚv¤Ô±âtu@ ‰d‡%Ó¼ÒŽª=Yê‡:i €†B²Ã–éFZiGåq;ª‡:‰ €²ÃžéFg)h[ڑ꤀¢ÿölG¦¥ Íß´u@Ñ?Ù¡Žãœ™ŽìÒNJJ •†r¤ \\¡^ ‹ö!RÚÑ>ÔI40{)ðQ™ŽüÒžn0(¤”áCh¸²¢ÁêÄéê$€¸½8À¨LG~Û¥Ô‚SXR Ö‡Zè ¥¶mC4@º—{ö#*Ó‘]ÚIA’¬<Ãì°¥8íƒ,å½—‚&¡N" ßKDe:òÛvàƒR‹bKvðB I ‘àéqödi꤀§`Y‚C(ÓQTÚ!Ê0)‚¥ja‡¢]pè•v4 u@ †q;´ìGT¦#·´“D¤´…½i‡^ÇÚdGêø •C4@ƒgá<ˆÊtä–vH ­œCJMX{(ÕòàkÚ‘5KA½P'Ð`š¥€Q™ŽÌÒN šÜ`rˆ;Ì!:A¸”Q;díÃa–‚J¡N Á69 yâü?:KAyiG½P'Ð@ “³òktN–¢ÒŽö¡N (í„…0šê°—v´ u@ P%‹/ FK;Zµíh꤀˜9YÑÑÒŽ¾¥ÍCD@TÉŽ–vt/íh꤀~•,Q©ûðÊÊ0ìÉžd@ï’%"ÝaŸf@'#-ÙI òÒn°U²40¥Ø–v¸&·¦&È(ê¾x$\Ú ¢J €FÚ¸މA)øÔ¿ la1Ò,òB'¤wèCcÜy¿÷@%;€ “Úª'‹Xµ›gEž“B,kB¤=)øwX%,%ˆMb «Z"Nj‡$:ä° d@ï’%²´CJyhëœÐÄ¥U#¯¼C•Ü¥"ÔG² ‘7n'…^Ò!-iB¬lÂLYH=,ƒ¼m‡ꃡ’ 9n‡šò—4¡.FK ð¦ ‰Ñq;’@Ìq;ä5ëÈ Ü¥¤PV× ¢4ùŠG ‰Ñq;Ò@Èq;üCoCp¨xÈÛÐÐíRP9Õ!5Û†~ª§{¨“hÈŽÛ‘þ†|ãªajÛÑ&ÔI4DÇíĤ©Ÿê†8 rÜŽF¡N" ¡YÉŠIK¦;òÆíhê¤€Š•,Èû¸C`4ÕAüvì1CD@CpQ;Ôÿ£é·¿1Nÿ„ Ó2ÔI4äÆíàÞÇ#>ÕÓŽq;|)ÂP'ÐP·#Âÿ#<Ý á·¢U¨“hhMŽ!{4Õa÷·îc@ D£P'РªdaWLR–éF|ºÃrÀ6¾J–:¡N ÁSÉÂ…)Ìt£= qÌ €Å¾4Gy¨“hPÛáÍwDgºÑtö5Ú ­C4@ƒgܾ#>Ó¦:ì³´ u@ ªÉ1ÜùŽ”L7šîÄ ÔI4x*Y<ùޤL7šêHYB­P'Р:h G¾#1Ó¦;ñuÒ@ žd‡+ß‘šéFS)çÛQ+ÔI4èK;Ò3Ýhº€P' Ã@ñk!ÈÈt#&Õa½^¿iê$€d‡½W%.Žy 9Þþéû]Ú°qb,+è꤀°d‡À‡…™n¸§:\7£®{¢w¨“h@“F  ¹þÖéÏ…Æ(¾Æ¢Ž¶¡N Hvr`€+ àבëýáêˆ÷·]CD@ ”êð¥þÆéNˆ”ž¬]C4@ —èp…Þ-í0K;Ú‡:‰ €¢mG (õÿhÛkÛŽÆ¡N † >|@™÷G{²â¸”Ð0ÔIÄ0pá'‡#(õÿè¸ø„:i €61bïÎRô7 BD@ z¸C€LGçdÅ ÔIÄ0(B [ަ:û›š¡N" †Alh!@Ïð¥ÕC4@ ƒ)à 8šêèæoª„:‰ €[èC``Â$–vT uÒ@1ŒæúAÝ=%±/;Tü @ ‚£én0%8\) kjÃô7áq»Áh´´£ká…£ø"X®ÁTà)ñ36è@–v4MnÄÈF(Ä8UqÇ@–v4IrD&LA¼sû:Hô÷ Ny4ZÚ @’#½ $°ÖWOv°¦;€-í(i¨¡U˜$—.B‚´Iuƒ>ÝÐhiG|Z#£%GµTG¢¿yº ÑÒŽpó‹VU,}ü-4ûµ4ZÚQ9 \ãòµ¢<4q@£¥Ý J:4ö÷ ñ@–vÃ"Íá+íQCh´´C•àï÷$@–vÃ#Ñ ’¶e = @£¥þÁb«$lêàBÔ¦–¿6ÝÐhi‡?Õ?B¸t£Ë ÑÇß‚ƒ<ÝÐhiG(ÙQPHÑ5Ù‘êïMv4ZÚá!x Åp€*B–„ÈÁ5 !tCÅà!4sš…B+j$kjÉ+í4ÝÐhiG¸Ä‚WðdIH0ˆ”ŒD•GÖSONpm°ä%((„®Y@áJ„ˆ¹þÈd@£¥¡h‚'!¤D-˜PR"Ù ¢';hÚB$;X‚BQ ˆžœÑmƒcCh(¶íh´´ƒ÷D…pu)„1Ò"1Ÿì„K;ÉN½°EèCQ"D~Ov@“@øÒi¶çø ¬mM !šfÈí7!äÉOX; ž¢a:‘Õ#\H 0"lCjÖ!i'£´àq;€¢C²ƒµHâNhP¤:̽1ƒ&ëv ºRr›Ð@—vD«d‡\>àõ:õ!qá?ȧ^‰pºRçÆ2ˆ¡%Dº.ê…Q©nHÏ‚QTÊ#‡ôÀ@1P3ÅQ™BBT Âá? ‘¥šÏ, ˆJIŽÎ e©Np¸§:zðãX€¢B²£…Ë))9 …¿Ð ñ1=öR Îd@ ”6ˆ !ZäúáYØ‘;J>0¡@ ƒ3ÉQ.´/í†nÛn°„@1Ð%% ®\O©ó…„!v÷#&î#½ðÖ*² ä¡aA¤e¸™HKÆŒ‡Mi@Cc–‚¤¢•éy® }¥Ò´•b UÒT+ê|>B9ò*ds‡GÛ €†JIGtÂ#nÅ­N!ä1!ô•H³§‚‚˜k 0W¬ ç.DjD('ÔÒE>Ûnôdˆ&Q?  öãÅ( PÖàIvhÒè“úÈ}(!´ôFD²ƒ6·‡Hª b}h´Åʼn߹GAw i~ ËDÛ¹ C>ÕqX²q(•2Ò*"wˆ“íˆOw£Ä0$ :’Фµ5Š'„½ð¤F~#á¼¼‹F€bäÙ‚ôÐ"©G'Dù’r4cÌQQyN¸ö0ˆaˆ¥9*Ö²(!/$$4ØÎ ¡Äß‚„¥P·Ð]æIäý–âC¡Ý@£Ü†ÿ\´v,@1ê\ANLì ÁaðÞž=ˆ’ÐÐ]ÔNĉå#6ÕaOwƒ¨ @ C¸QGø>_|+χsºCòã lµðkûŒ–vpÞ.@1èðÝæ1p1)4šî”vƒñ‘‚¶©}Çç€v#ÈêÉŽ´¶Ý Ä@|”àLv‚šì„(A®én°g+€b 1Ò1‘‚/ðAÚ-Œ˜˜„®âAì%Ä¢iêíüA¸ 8’‰™©n·_‰)íµÏˆøêeµ´C¬C^Öˆ8¾ùäøÑ!臊 Vda‚zDujÙÁ6ª@ÍÒn{ €H/í°%;AĪEQøñ4èéUC4Í¡œg@YFD Ÿ±Êv¨O‹aø{Ðû €¨›ìÞB]>†8 K²ƒ„ª^ý"” Ò(Ý¡¤>â¯Ð;Ît72@1ïAäÅŠðå¯(˯QŽeÃ~Föd‡‹E+QåµnáL‘Gtª#q½Ý€€b ±,@\(›XÐWaë- ­[Df Ѝ‹#Qm &f¨vûÓàIxBĉBúêâÄ@›±,¡+¨yÓ¹ Oˆ>«»Ðº« €h\YNP5üÉlß Ñ ?ao€â·Ì €h“ìãMƒtNzt¯7†Ti@ ƒ¥Œ¢^ Ñ$üIë×R«LöþàÁˆaø¤::äzüÃ*è5…)DíCª´ á—ìèþøïnGWH§fÊP*íˆ ©Nˆ:‰˜.£¨š|¹ž´´Gn=¤J;€¢tQ;úº'ÊÒ.UÊÛÁþç=(žJ¥@Q!Ù ®d7Øs½ÑU4>ÀŠ8Q7;0C à‡FàÀ|@À‹<ÀlX$@]@ ‡!Ê”ÊÂ'”ó„×1!.eÀLvB5Æ…†XmC6ÚÉ €(,¦ëžPî¦AºC Ûé4XŽ“BJ‰´ð„FHªâÉ €¨UÉÂïD4ù—>!/NAZ‹‚Tª¡.…¢ÄA£¥ÝàOvDÅd‡~§J©%„V, am"§ßF-í†@² Ê“Z²Ã~1f%+ˆVÉ ’p–Ûhi7´“@1PÚBYÉ„qC› êŠ'´‘!¤â eCùµìhi7’@ ÌaÔ¤±énh';€†Én´´üÉ €èèZnS-í² JÛvƒŒ¶í†@² á—ìFK»!ìhø%»Ñ¶ÝHvDy²“‘"À%‹`Ê`—@•˜‡¢—ᣥÝPMvD•dIz„’ ádKn0Œ?޶íà@h ’®d'$„'Ùu*YÜÉNP”ÄSAI²a¥r²‚%;!!ú”v8“¾d@$';HMBVÍÂÁ\&%ƒªnBJi×@|²q³B0’Ú0S1ÉNg²BOvBÔHvÄ HFºƒµÀ’‘^å  ‚¢ ÉäRÅLâŠÒ[Ú±"';Xi‡œê¨\Ú¡&;!œm;!|m;€äÙÁ € „áê]´9ûþÏÙü›†u ·Y ¼},’_ØnÙ­ »Òî,=Y}vå=»ŸM» »}ܹáMÖÇùœIÈ9erq'îGLÑSâS°“¨qöûÀ3Ô¤Yp猃ÝÁNZ¼(ÕƒÝ#»M‘>KRÉâIv2ˆV¼EJBØŠF,¥Ñ Gìã'â#2Ù±(Ñ17ˆ&;`Šcc!!`¢¥<&pÂCT²`ÄKw@‚ƒœä@i„@iRÚÒA“(ÍR8¹ ¡ö(0“@QìðV²H© Þ=@R…¢ £WŒaÒhÛW²bENvBœÐd'Ä JrÐd'Nvì°”Ç Ju dÇOvBLàdÇ+í@$8ÙA„‚Ô±À.…(ÍË;È °ÇMul„RØa&;€"yQ;¼Ú“·òm=A”.rC,…ÖÍ@6¥Ùˆd$Ü¢ »‘UÚ !ú³ðdFÜÐòH @Ó¤š…$;`™ÇÄ$/ì@m;!X²ƒÀJ–\Ø1ÀÊ;X²ƒ”wB¼ðdêV€“,ÕHv4ná‘‘‘!mFê,,Å¡.|‚­.†¥:!ÄêbD²‚o£W² Üã$Ã Ý ‰°dÝ9MvBˆd^W iÞA ;”Ò=Ù Ñ:ÙÐ0/í„FL²bE®c… {xÀý ð2Oh˺¨¶@ˆ º§ZÉÂS‚W Ð¨m@ „'†_-+$4L“´¸CêÌ"%;!ÈBOð Ø’vØî1hGœì Á[ÇhUÚ‰!„ s²H$c½ozt–ûœ¬ædˆ`4â4&ŸRCîïâ/í¨uÕë0LvBÈ©Ž¶É €ˆˆÚÁšäH¯c…†8 q²¢Û €b  ‚c¢#TÚ –vƒaá@ Åž,þTC¨G1šìA² *Dô`JtÄôdG“Ý€';€™³£Én€“@Ÿì„†BIGlºnÉŽ¼Cd‘Σ s² ªÇúÀ¦¹‘6'+„zˆ,ôH!¢’ÒAcôNvÄ@jÔþúi¤"„|ˆ,ìXEÛ³…p&;!FÄ¢vÔd'D0Ù ìˆV…uË9¡ÑT‡³’Ârv±ÁSpí¥¢ ´#>ÙY©€¾INh´´#6ÙÁOÌæ„­€¬-†ž ]_ ”‚OÌ‚U-`D,/†½#„~‚¬$Ù ÁŽ‘Ÿö:|tìä|;"’@1è”êFëXÉNõ4Oxi]:hLHzÆl'¸’…®y‚¬4&¯d…«‹á«P ‡ÈÂ’øYl€¢¾ó>»)ÙÁÏjB:»˜±¨~¾ü†!Èz;èš;èùvB°…í Cd…à•,ì,OP²p9ߎÈd@_ÚNz'5…I`ØáhªÃÚ“E?DÖƒß ?Vk²C¤:¤d'Û9&Ou³‹…àm;¤#³… ©Ž”d@Ô.&6éáKhø‰©oäžæ‰èP ';nD²Cªc1“Z²ƒ«ˆ”ì@éÚ¥€ªêR€ëYÒ’@Qq–OÚ#3½aI}£©9Ù!Ÿ°"Ÿ §:npÛzp1h‘1³äÄlÄÚb&HË´Þr9##ò T'iÚ“â¨vhëŽKˆ„¶@Qyr ËÙTHphio4ÝA“ê!²°ÁbNŒdY] í΂—´3ÃöîÀ¶Ê ñCîDa„.-˜ IvЦ°´ƒœ#ˇt èÈløÙ³‹‰JvD›9YøÊ^ª&9¤¤7ZÚ‘ˆ,3±§yÒp– €h¹€&iŽpÊys²B¤.Õ²šìˆ†‰N‚¦WÂy¥É+PÀ'µd² &; ÙÑÒnÈ.| †!›êp¥»Ñ³‹‡@² †¡ZÇŽôZvh';€¢a²£yÛn´´²É €h—ìDDhšî@æ–vƒ=ÙA¯€ÂHvDËd'B³h°®d7rK;Äc³(Ci‡#ÙM“$åÉR=ÉÁÌ-í°%;NÔi Z&;!D²")Ù­“,éÉR+Å!›;ZÚ¡4&„¹€^ÉG%‹£m@ôHvˆ´Gvê“EKq£¥ž¶tQ;ôfOè èAcìà•ÅÌBÈGC/ö¯@‚_c,^ø;ó 2 š–…Ü »Û“W¼È:) ¹Ïz«§Îd@tKv¨©p"DUˆÝ¬ÑÒG²«>ÎS¶ð œîØ‘Òü”1ÄêbèAcðc«íÀ,ðm²@´¶þ„²¨¶ò |‹1ìmÄmÆÉ €èìð%B m´´#ª' ªe!+Ú…  Ÿ E<Õ1 Á׃Ë=È±Š°mcÐõvˆÕvBJRàñ ñ Á×y¢¬·鹿%9D‹™ìh`“e`´´Ã“세ђÒÆ10‚í£€¤;HYÇ”ì„`«‹ái’ê@ÉNº D"%;!È¥íðòw² á—ìFK;DOVvEÖd‡¸´Ü¥ïƒ,ñ„¬·CjØ!%;Pˇœì„WïkBŒÚaIv4ZÚ ãdÙ<&Ý:Mu³‹™…êXÈIíÐ ‹Œ°Jé^ Hm NvB :–Òºƒv)`«‹!©^ÇÂSf² ÑÒn¸%;èúbH?–r„±F²­·B¬.†\Ã;¶Üå@)î@,ÈòbH²ƒìßï‘…®.׳°~,ˆÂÙ¥ ÑÒntr cÜZÏÒpN €FK»Ñd‡=ÙqÐ2ÙÐhi7šì0g)„ µ,Í’@–v£Én>Ðhi7šì Ù­“fjìf„1IJh¨ÊGK»!›ìˆÆÉK²BPBX“%Þt7ZÚ ‚dÞ›MQ² º—vBÄ(DFšC×0ZÚ TiGq² Ú';H'$„àÁž<ý!¤…U±V D͘x¬Wï,ÚOŒãy"¢ðÙÉDfJ!º5MÏekµäIóÝÅ*¶;¥ Ù;vMÑ)Ù¡!TiÉ‘ðFK;´ÒN~1$ÝqÃ’lNV~Àä¤1&¤ëd! Ÿ S² DMvBÐCŸà'{|•,dN”ì Ÿð$;€˜d­2ñ';!¥Jv$·í„`k‹9¡7|½ì0OÈÊ'Ø(ÐCÁGf#Nó„œ] IvBp Ns°¥ðTÇ‹–ì`«;…ðV²Dóáb!X—BÚƒ€·÷ m6D mÂ!aH Žõ–vX’Ò*OX²/j‡¥:è‚;f&Dº¯·W³HgC&Ç„àëžÀ ŸÀçÛaOvBà¥OˆÕBø’@Ñ}–Bû`Èè,u’'j²';!”Â)ÙÁVÝA ;~!lÉZÇÂ’Öd=Íiu§žd@ôŸ¢Vª-í0“¬–…ìƒ.ôBNvBÐÂŽ™ y•'´q‡œê„ ÉN^ϲ@ÎR@Wz"’ô4O¤…ž8“@ Àœ,ÒäØhiGý¶8íÁ7,Bö, Àû± D²ƒ-ñ„”tBCd!ZÚ{°°R¼ÎSHÖ“…žÔŽhÛ¯DaC¬õÄ™ìhtÊè¸ýçdhtʈOvB° €FK»‘žì -“@–v£•ì”v48’y« FK»!›ìhДvˆñàÑÒnø';€<•ìhi7‚’@ P²C¬dB™”E™#Tü–vD&;ø¸;dÜŽ@²¢y² IvˆtBh‹?Q–vÔ)íàÉŽ]ˆØ}²BÃ(h”ìhÀJ;!Ô…x"Á:w´´Ã—ì„°%;ØÂ§Nv4ÐÉNKz£,Ù–vɾð œìW²`LÓSh';2+ÙZÚ qÂîô„­2†ßž 9V\Ò—CWCÇŠak‹As²ŒðSdiÛ¶ mÛ !-ÄB^œG~—b¤–v…'ðưÒzÒ˜´‚EZæ)?Et±tu1¬GAÛd@£³Ã¥´cE¬ñÓðT[ø$„Ô´ƒ&;ÈÍÙB°Cd…à§ÈÒ:ÙÐèœìð©d9‘¯‚§:n!èIí¨ÉNˆ qj6ôÖvø™Š´Nv4ZÚ ›Ò¥°CJvà:Vµ# =©]±®Ò¼ƒÚÑ8ÙÐhi7<’øØöPªC,k‡^îP€ 3ì4OHË-í u,,ÕÑ6ÙÐhi7Œ’üÆ1èÎ1ØcXqîXÀÛv°ÛP (H§ÈÒ¡K@£¥ÝèœìÌÉÐhi7šì ÙÐhi7šì ÙÐhi7šì ÙÐhi7šì ÙÐhi7šì ÙÍ’íÓŽÂn´´É €h˜ìhœîdGt;Ä“@1Ð0dd¢¬1鯿; Z&;AYZ•x²²£©nHû €hl¾,Õ“ž,¾47šî††¯ˆvÈR+íÉLr£©nhø €èe‘¬,%©O–¨7šî†Š¯ˆÎöÉ¢‚ †k®©¥@1 ¨í²¸à(Æ €Fƒ`ÐÐh²h4Ù‚4šìFÁ€Mv£`@&»Q0 €F“Ý(@£Én  Ñd7 Ðh²h4Ù‚4šìFÁ€Mv£`@&»Q0 ÀÊŽ¡•x|8XIEND®B`‚procmail-lib-2009.1202/doc/article/pic/postini.com-stats.png000066400000000000000000000443741130547513300234700ustar00rootroot00000000000000‰PNG  IHDR|†ÖÒ¬†gAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<€PLTE‡§ÅÁÈÌ,--ÌÐÒ}…‹Px¢Rr’ÿÿÿÒÔÖ¾ÆÌX„¯=AEÉÎÒT­bhm¶ÀÇ’œ¢ºÄÊf…¦õÿÿ¶ÊÛØÙÙX„²£®µT„³ÆÌÑgu‹s4Okf‰° MRU›bjúÿÿX‚­°¼ÄFYoÊ”biÂg{£ƒ,W%\ÔÖØ'3HN]ˆ²¬9­¹ÁÄËÎ*CרØOfÏÒÕ™£« 2Ô s…£;dŽ^}œ†š¼ÅËU*yš¼¨rmM†´X~¨#E%1j¶^йU„™')lC=ƒZˆ­K}­ÈqZS~§QdS„¹·]‚¹¢»Ò˜0' ¸ƒ‘iCE^…®©KDÕÖÖK€t¬X„©¾'/os´S‡²´'€Ô…8M^‚¦0ZS†¬! #_±~ˆ¸[OmR£\ƒ¬’H’±8W»ÂÆX‰·Z£_»Y­+B]M‰£ÉÌÏÁÆÊ?]~¹ÃÉéøÿÛÛÛXƒ¯X²¾Æ%mìGIDATxÚb¨£`€@1ŒÁ((@£‰o  ÑÄ7  Ðhâžø<ê¨B‰ €Ÿ˜15ØhâM|ø@!%>ê¦=PêM|£‰_⠤ħMm0šøFÞÄ@ˆÄgÌIm`<šøF¾Ä@ˆÄÇI}0šøF¾Ä@ˆÄgJ}0šøF¾Ä@8_]îÄXGÕÄÇ `6IìZðÈaÑ 3™ áÌè®Aw3µÌ:¥ ˜/˜i’ø˜É äÄ@ˆÄǂꠘB@TâÃçj$>HГø˜‘\ƒ°ƒ™¢Ô‡?ñ1“—¢IN|´)ùÀù†™‚Ä@X_”„¦A`1áÖ!DAì:ŒdÊ+ ›Y3#)ñAãϰ¢Æ„ð™¡^E Rt9¸^n(² Ü,$uH ”KâcFØO p%)ñA}€âœ±ªGB}ÈŒ¶Ì(Á†F!@l*Œ‘ØÄ‡µxKsäÄ@ˆÄÇ‹uP²‰ä­Câ£Hð"iµ„%> ° ¤&>fÔàªEâ#‚5… Ë1£ c–|X G/æp$>f8#,Þ‚ˆO|µp#ü b’q‰5`0(lž°'TíBS4²»Ñ „;[3ñÞćœÒPR^Bº9íñ²X"¥=Ò_-ZÊA"fD3‘™¹U –T‡ž÷ÑSj0¡&>xY‰Zg*ú ¤GR›¹Ýy˜IÂUÍhRK>láÃŒÕGŒ8Ò®ÄW‹-ÓÃÊihêsÅRò"ñI!@Œ¬ „ð‘„  @Ê>^ˆ ä$>DœãL|ÈÕ.JâƒÅ%R‰0Uf­ƒ½äC5“p½Ëˆš@ˆèí"§ äôŽn—k䇻Š^ ·VP}†á ûZ¢š»Q „¤>WlÕ.@“ø‚ðÄÂH|RåÀÔg 3‡Ì’¯–ÈÄÇŒ¥äÃÒ~ìÃQ•à­vÑÜD¸ÑgR1ÛæÃV¢ÛŠFFÇ@˜qÊŒ¿o”\ˆ¯vÑ£ál{¬m>€B$>C$PÅpF*¿U Ød”ÃŒ!¥·‹Q5`¦fÜÍDôj…­}ÈŒ¦_›c‚™Ø68âIîí23cišaÚ¥ÄHòs-¶°ÅÛæ{•¨¡Tw3c7P/È{‡ €°'>C`Õ O…Pjb¬Cá⤎ó¡öÁ»¼Ø´«C©I™Q¼ ÉŒ··‹>·\ýR¨Ñæƒ{š¹–”„NZâ«EkBÑ9%*ñÁÝMbo €‰‰ú€Ú3̵4Ì4pq3{lPÌpå äÄ@C)ñ1Ó:l™©ï‚Ñć'ñ"ñqQŒÎíŽÎíâK|4šøF߀%>€B$>[êƒÑÄ7šøð%>€B$>!êƒÑÄ7šøð%>€B$¾*êƒÑÄ7šøð%>€B$>êƒÑÄ7šøð%>€¢q⣠%>€¢mâ³£"%>€B$¾z꛺Q0 ÐRâ š&¾Q0 Ðrâ ÑÄ7 ,ñÐhâ–øh4ñ‚K|4šøFÁ€%>€M|£`À@aI|£££€3ñÐhâ–øh4ñ‚K|4šøFÁ€%>€M|£`À@Q–øÀ4Œ —…ÊÁ§ôP¦÷rpµ£`D%>€¢(ñÁÊMȲˆDWƒ,‰¢I-’ɸô˜ûF³°†ëkêPdM˜ à2¨iwâÑBGJâ {»%Y FâÃìp wTjˆJ|5XŽ gµ[GYµ‹ÃÌ,© {º¯AnÐÕÔ°}D$>€¢¬Ãc¨5‘¡¶QÕÕ ˜èx“5ñáéjàîpÔ‘Üá@Jjˆzµ'Q‡ìP´2¯UÂØz"#±Ã@TI|èƒÌȉ}¹¦id…ƒÌ5ôº¨`ýÃ#ñm¦×j(Ü1Æ Gß`N|D“ÄW3죀ˆÄ@£ FÁ€%>€M|£`À@‘‘øP× LÍbY¹‚mö£½·‹µ­6 †{â Òò,&Æ ÆÊ•4›\Öq>\ :òWµ xd4?H|DrâC-¿0¦É0g:Ї^°M¯aŒ­ÕU-(šGÄ@¤'¾:Œ±9|+WPb]F‚IJ¨¦dˆ®jAò¶QäÑćDI›Ûjô•+Ȇ¹Ê¹G­;„Wµ ¦ÙFК2@QžøPRO ®Ò­cYARɇwnwh­jA±¦ }YÅh•,ña©{ÑT" c¤=œ+^†ðª–l jê(XØ<Œ@Q#ñÕ N®£ÉÕ`&LÔ:—ˆÄ7$WµÔ CÆ£‰ˆìće5 þ•+ˆ–_ ú",Õî]ÕR‡Òœ@Ö9ÚáÀL|DQâ«Ã\Ô‚”bÐV®`I|uX§©>N2Œº`M|DþôZ ä(NƒsUËhÚÞøˆìÄ7ÓÞ(Z‰ €FŒ‚K|4šøFÁ€%>€"5ña=ö¢ËâŒíè+^°Ð£`d%>€¢Jâò8cv e ÏŠ—Q0r@‘Síb,À³=²yC–­–¸™q1è(>(弤Ñd‡+ñY‰¯½à«Ã²ª¥yJë¦q¬ô I|uä$>,kFÎÄ@ÔXX€íä\‹ LÙŽ¡{P"ñ.¬Â—øˆZs»uø}XË6B%ßP]RUS‡®qtaŽÄ@ä$>ô¤ˆm3c9qm¾¡zPšÆÑ…U¸@‘³‡3!:¨§TÕ`$Ax‹r¨dͰYR…-ñ.¬Â‘øˆìćeå òY-è‹›1àçªKªj°Õ×£ «p$>€¢$ña¬\AnåaLJÚ5ÆßßÂKªP‡ZFVáK|4¼Vµ`5МÕ2ºŒ-ñÐðZÕ2¨ é~˜‰ €FŒ‚K|4šøFÁ€%>€M|£`À@&¾Q0`‰ €Fß(°Ä@£×Ü‚»æ €Fß(°Ä@£‰o Xâ ÑÄ7 ,ñÐhâ–øh4ñ‚K|DµÄëM#ƒ#A#õóKÔÁ6Ø’Íc9ñªÄ‡pÐ K}uƒ°²¡oâ ª&>W{`C>º‰â0¯n R`ÕÁœÁœ"¡®A¸…걈œøˆæ‰^hxB³3Õ#¥¼J}(‰3¼CâC '*º 9ñ _JžøÊá¤L<ÀùáÔÄ7ðaU†èáD=—!'>€þÕ.–ä6Xß`¨vá‰=œhPíÍÒlò èy Fö M|V-Õ]†œøˆf½]dz€Û|øu œV‡%³Š6F8ѰÍ@4çCÊу ‡Ö l‰©<àÕn=RE[GÛÞ.@œŽºÑ9œÁjȉ €Fß(°Ä@£s»£€¾©)ñÐhâ–øh4ñ‚K|4šøFÁ€%>€Â•øêÆ)¸˜ °ˆâOÇ”¤rÌ’S´]NªÃBª#pê¨è¬:|QEd,ÕÑ&ñŽÄW‡ uĻ։–ÁROW‡ÕÁû’HÉ¶Ž˜¤Ðaä„@“øê¡~È˽êà‹ RHÁ†EM#…A‰j| Ô©P›QÖ¦á'©ÇxV´N ¶ºe$숰¥Ü}u¸Â¤eÕ²³`q‡gÔ-äÄ@Ä'¾:¸O`$²ÇàY±›–ú:*”|Î@2p¸lÆFR-ñáušJ®®CQPæzІ+LPÊ ˜³êê‘‹ ä8£Jh!'>€ÂžøêPÛ#uˆ,Y‡ä”àBQŽXÏpˆy_Š›Vðbæ qŒä,$û‘'Ù¨6†JØaõȹ½JAkã MnQZØ †DÒ:Q”Éq06šg°·l)K|„#ñÁ­AM|õ(­d܉]¦K3œÜ DͰD&> ê¨Ûœ!Ía8¢{WG%ÇÕÕc–¢˜!ƒ­àFó -J>€ÂšøPK1äpÄVíbtÓ ðzl©Çx«Ýú¨vë U»uXª],%$õ«]Ì Y‡QíÖÕ¡‘X«]ê–|D0ñÁòb]=j+©Ã™øίǪ‘²8F3 ½ ­Ã´“.ü«G«ËPZHRÑ}è­IDǭÑôûPuH^ bâ j 2–1êѱòA~ȉ €¨”øêêGßÐOxôXMˆœøhtzmÐ7…#%>€M|£`À@&¾Q0`‰ €Fß(°Ä@£‰o Xâ ÑÄ7 ,ñÞõ|˜“a(«–ú¡èkÔp¯uƒFœË᪠ê {fBY ‡25‹6C[GÈÉ„B‹†îÇ']G•€FN|„wU žÄ‡4ǵpâ#:xëˆN¬öêPrJz$Õwá•:2PøPrîX„0¼9¹úvÀO¶µðL7ó¼-¿ü!4òF››ÓWËl«ã ÆòÍ´fžˆ‚úq/¼VáÎI´q·0¾[>TXT¸à:³þxj”«ú}øJ‡RDKdx;ñúò}pnï8„ @o>\}Kçã$¸­QŒÐð\t¾ÄZ|Ðù¯Ê–9?àûʾó³W g?ü¸À:ÀG0ÿŠOE”_ÊwS‰Â«@¦§@`iDuÞgWœß¿/¾ONÎf„Áo>_½cûѨ®C0p¸ƒy¾}ã¦ëx ›¯¡™-¡y¢<Åno>™"Éó ^§l‹xsį¡QpBhjää¿ùJLâÔ‰ü&¡`5„"ê¯Í·Þõ|è%_=Ö’¯ÙX:hF`¡FâC[t†–ø0bë"/\Ë݈«ßê°%>Ôv0fâÃa)ÆÊIj'>ÔŒ‹ÖÜÄ ¼:45˜ë¿êÉH|„wIRÚÇQíÖÕc.&ÅVíâ¡]µ[§Ú­#¦Ú%9–±d´¥«è «èUíÖ£U»uh¹Ûªzd¥uhŵ$&>€ÂŸø'eaëp  µ`YË‹º Ñ«ü°v80Zîu™OWƒP‡ƒÌć¼kâC±•‹ÞÉÃð+™XZBZÓ‡Ö!Bëp =(ä“uuèê‰N|Dî sÝàä öÃ0n¯£Jœ‘Hȉ €Èžá¨iëØÀÈK|tL{(‰ €F§×F}Ó>Râ ÑÄ7 ,ñÐhâ–øh4ñ‚K|4šøFÁ€%>€M|£`À@áM|xVža›}"欼:ªdÔÑòL62‡H¿Á»’ªŽTmDÙ\G¼Ÿê9 å`Ò@áK|W=â>’®Ž~i¡n0ŒÌÑ?ñ}Ø ®H'åWäÄ€µ3F„aàÏ“¯;‰MÒ"ˆ³ ‘vËqŽ`ÍÊ&ß`z5…ÏÊ5-ö:cxš2âr÷IbųÃ/ˇ`çhïU úê1>&\Á-?ú’“îÇâé/É ~X¾%+wpƒPtóßÕ½¢…hÔ Ð6^|!þí’Œ oáB1G\ÎOŒ¹0Ust“ÆÏç—µŒ1„8ôÕqáD¶Ëgg¤iPê9€Ü8=þãò X¹ƒ@†¢›·«{¥D'ðÀ§—ÎâcŸ°7¨þbÏÂ^nŒrä®W_›Y~eØ2WŸ:vŒO¾#3@Óø¢š /ܳiÈûÈá0S¯²Žï Šªlæn\ËÂh•øP÷—Ð1ñá-b.3p×;$%>¤¾ò²Lò¦%D/ðGN|D‹j·®Žà²0Ú%>Ô*Ça´ègR½Ú%X÷×a­qE‹RÛa¬v"®ÚE]ƒ‡VíbY¤‡ŠõØ«]/@N|„§Ãíйz #7ÞÑSžea”%>L[ëQ{9¨aŽv*zÓŸŽzôî°8 ½GP‡åCd§£'>"|€Ò?¨«¯ÇÕá@=V»ËrW䕜hûTHI|4œ™ë¨¢„>î¬*!FmÝȉ €FPâ«7žã¾Tg$&>€^ôMïH‰ €Fß(°Ä@£‰o Xâ ÑÄ7 ,ñÐhâ–øh4ñ‚K|„3ñÕ‘vÇ.¾7ÍÖ=ÕQA ò]‘kÌ0BµÐª££.2@áI|$»ªnüC…ÄG»°&w?ìHI|„kz¤;v‘ŽñÃXxFùs¨#x:\Úå²õ(ŽÃy”¥aŠsé"ÎCù°8)Äê©qýúÉu¨çða;‰’Ã9HM|„kaA wìbžåW‡eé5.Û#ât8¬$âL!Ê‹'ÚỸ¾Û {”_ü‡e]!êíÈ ±D«Ä@xVµÇ.öƒ$ÑÖ÷Q+ña¹Öõ¦:”{¼ëÑÛá:Êâ‚÷‰vØåC¿ñk8S8%ˆãªm<'"¯¤Á†ÔÄ@„f[„¤ÄGõ’˵¶èÇÏ¡K^‡ãÈ2*—|¸–.â8”ÿ©€ÔYmˆóžwœ'â8·6‰ €ðW»õÄݱK ñÕQ¿Úź®ûI¯t¬v±/]Ä~(Îsq©xß.®#€qŸDˆ|n!Mºȉ €t8ꉺc¹þþìËFòÛõXÁa¹ºé8@ÂGùQ§Ãué"ŽCù0:ð–扆%>Œõ‹øN"¬Ã¶Ï„F‰ €(d—ê¾Ãȉ €(H|£io¸'>ZÄ0râ ÑéµQ@ß”øh4ñ‚K|4šøFÁ€%>€M|£`À@&¾Q0`‰ €Fß(°Ä@C+ñ8ÇÀavuÍD½z‰Š%îâˆ:Jê†iâ ‘‘øðu‡mÍ,Õ#œ¨Ä‡Ó}Ã5ñÐK|uëõV ¡_\_yûn=úÒ>lÐaœùGDâÂ8F}=#Öó Ñœ„c5"æ²¼á‘øhÈ•|èËÒêêp,|Àzû.Îëÿ0 «#©Ä©Ã<Ûs=#–ó±];Œe5"•Öe ¶Ä@C/ñ¡žÿ‡vö»sqžu‡ç 0Ò"ça…ØÏÞê-ïྜxH×Âȉ €†dÉWå*ô# ëp%>" #+ñ¡²ë°Ÿ½W‡ ê1¯Æ<‚ ó˜½á‘øh¨V»ðú¹Š"¶Ú­#â:Žcq¬„$TíÖ×ã¹®xhw?@ Ù¢·€tŽG=Úò5¬÷-£œ„WGrɇåp>äõ…uØ/ðEÙ'„º¶çuÅÃ'ñаd®1¶ŸÄ@Ã%ñÕë‡zD!%>€^–øh4ñ‚K|4šøFÁ€%>€M|£`À@&¾Q0`‰ €Fß(°Ä@C;ñ!ÍA‘x½GÜ%!uÌf‰ €†Mâ«ú‰¯~¤%>€b‰c-^}=b¾ yiêýNXϧ n2Ãv âø Ì÷ðÜELÄ!„Ã#ñÐÐ[ÉŒí?”[V±åºõ:ÔÛ³‘Š”(î¡]»[íÀ=¼ú!Ÿ¹‰äƒ:Òn¶ü‰ €†tɇq¦'êZKœwˆÒÊah®Á±, ɸî"Æ<¬“= @ Á•ÌdU»u4®vëqˆcM¾ý°]‹¾Nkx$>€rÕ.Öës w80:4è×bX¼òËÙ€ØôüóÂa‘øh˜2׺}'>€M|£N°Ä@£Ók£`À@ …ÄW=h Œ¦(2@ ħ2xŸ„„(ý&)ò@&>J€™(ù&>2@aI|uƒx %>O™Á~~`â3\á5h##ñÐhâ£$ññ(ð³ 게&>ò@aK|œƒ Ä7¸ÂkÐF$Fâ ÑÄGyâãM|ä%>€Â–øL1°¯lŠÔÁÕÁ8!S‡¤¼“‰Ýd<‰OFor”«Â£ "+ƒ¤G“I(ñ•“ZP»RrC 5ñáV†ß…XŠ¡6%‘‰ €ˆJ|u¬¨CVU‡`×!Iס¥)‘Ç“ød8ð&¨œ >ePY´ËAÀhü‰øÐ©Žì#.ñÕdÈ×JLâ@JµÝ ‚ÀÆp‰.x³·á-àň˜œBð¼‰|T ±À}_€$R›Î^f Í—ÔGò­LA¢†,g*xã­êœ«á µ3=œ4v#ßsÓ-"ñ£c;ùh6Ï‘oA)•²¯…T¢ó¶Â2ù^H«£B ?óÎÙjǶ"·?IB±‡ÕñõšÂ &õNðqòÓÐð_se½]*…òŽOÃqã[NKð ù›‰ð}šBjEF%âƒ%~ËÜâ{à´ÚRaØï~¼gÍÙçXÒ‡í`XðAµÖ vâ›Á°^å±à# jŒøbðQñàœ²ôß›½É+½¥¦­KpüÛM*Hì,àoñdËQ㤜e,‹oôÆiKP:»êEÞ\£?ÀXß-€ÈO|hb˜‰ì $Cê”#¥P ¯Q’øÐÄàjÑŠD”Þ„ ZÉ/ ±719¡…5ñ¡9!FtâC6L§“ø°E ÞÄ@ØŸ:¨c YWe#‰AI¸hš’Ü$u(F¡ÛL¨Ã)¨jÉ'ƒhñ!)–Aî‰ xäU»ä„J¸ ©&?ÄPŸ€SuØœ b¡Øƒ° ]k]þÄpr⠢Р°É(C8&P'…-ñAeêàn…:°Pãë¤HH|ðÎròAjùÉ  ¦ (FjóÁ›‹2ˆæ  ")Óᨠ'´ÐB 9 (1âL#²)pçÂXu¨i¬ÕsH)Íâ±[â l‰Ïpðj 2ËÐr¹bp…ÙY‡ƒM´&b†œøh4ñQžøl‡Aâµ$§)tM¤&>€Â–ø˜Ókùƒ+¼mDb$>€J‰Oið€ÑÄGÄ@Ø×àC#ñ ®ð´‰‘øh(%>‘ÁPŸÀhâ#/ñ¶Äg;xÀÐH|ƒ+¼mDb$>€Â–ø„‰op…× HŒÄ@Ø_Õà(‰omØEI|õƒ+¼ÉÍ-’Ü©©©’âÜ  .é¦í_*oÂ^à]fÅ.ÏÀ /ïë› Þ|F (ÀÚ— H:Šgg‹ÇCŒ‰wŒf( ,Iå–ôw’•)—/®ŽŽÞÊÊâò•ÉlF^Ê`Ý5ñ¶Ä'0xÀH|*ƒ+¼ÐrRÎf3——Öc·gs÷Vgg·—Ö°´fË®&,¾ÚJä¤b^Ɇ¬“›OY9»Ê—4a°÷ŠñçÏf+'>†Kkvß‚_9¾l¶d6§ìâ=_|‰ €Fß°N| Ô$”³ai(X¾Éz¥‡ËÊUÊ[ÊË«©ª²ÇHŠ×fó)³#'¾49”ħœœÍ]›¬ æÔ:É›™NÙÊlrÂìðSAU59YV8Ù-™ÍÕÜMRÛWX¦‚5ñÐhâÞ‰ñ©ââ°âO¼@”Jtd¥å“U‹TÍ£øŠŒä¸%¹³RæH‰¯H6»%ñÅHúûKfC_¶ƒœj¸µ‘‰I4¢²–‡hdÏã÷•3±æsã+€¸{â l‰oR7èŸÁ =Ô¯ÎXUÖŠ󉻱y“0¤‹7…yfvYyv 9y~Pj±Ö’ÉȉÏÈ$»@\¹©Ú•”Œw„&âl skÿ'ayy#i `î ¬‹åظي $‹q&>€M|Ã8ñU*³S›°ª°pv-¨ b³fg×¶è,LJ„‹ ÉEXDIf›!¥ óÚeqDŸC\2YØ:Y’ú²ÙåíùÜœŒTxäy0Ÿ|´¹<¸”µ–sâ½áX@&¾aœøÜœô€½9`ÅhbâÄ J7ânÉÊÅ®:<Àħ#'l./ I$ òÊ Ä'ÌŒH?&æN@ H^_Usss=hl-kží ,)BŠ0‹>ySÖš ˜ø”±&>€Â™øêήCõŽ‹,&ZÔ³°ëë E¿$Kâ-Á×,°ËÊ`(ƒ«…ë@åÂ),*±$>äû=P/<€ŽOr¦F š:Œ Á^ý®llNÉrðÊPÇR–AžGUØÏ&>sP©UÊf]TiL+¥ñ’âá• HŸumŒ$h€FÜ_’;&Ɖ=Ôž+²ö-ö.`cãóeË“Ö)2’‹2àE:F¥@c±&>€ÂøêÇž£Þ!ë0÷:‚a‰8<¾Á@c# bK|2ø A²2X’(ÃQ5:WS®{ɇ¥î¨C ORÓ^R"D <á…0 \\ÒË=Qé€ë[ù4ÒJ`Ý(/Ë.o g·Ž/t•Fª9}ýù £$ââ’ñl®:!i!EÀRNU.&ÜU6šÝš_žAšAG‡dd^Æ‚5ñÞćy!’ÿû¯ƒÝV‡?,ëPòt]JþÆ’"q&>…H"2ˆÒP%qUÃåÀ%íÁ‹7´Ä-óÙH!Áć~WJ>F¹Çãž6\á…™ÚР¹D1AÖ]<>€ÂV¡t€ 5y#óR`²¶’×¥6>Gn˜RU'ßbÿ‚lePòKÎöwd‹Nj Bkyi¨1 ]D(åAÖÄ@_¼þEõÖÂð7GðrZ$Pí"%X2”A-¡âh$r9ˆ'ñÉÈT#'>”Z˜Pâü´%ñÕá ·:<á«uу¦®3£%>s99¢Xâ IÑÌh­2a=9P7×\NÒZê™ ‡+û*³¹Ê±±I‚Ÿ¿°yh¥(A^žÝÑÅ`e `M|DlÉW‡^œøÒY}]r‹½8Ä[òÁËÈÀS)‰%-!¥/D*¬Æ–"«ñ´ùÐòlÉ qO\rH௺z¬5,rêÃÑæÖ«VˆTMƒòüÀZ^ZIgë 3«a6eaˆIr8·r¥<ƒ¼U2Ÿ$h|Z¼Ô,4Rv.ä£Mˆ+ì'>€":ñ!jZ&>¤æ ¾Þ.FÂ"/ñÉ ¦Õ( NÖǨ–‘ÁH{¤•|Øê=Bu„à _â«ÃnPœN»œ¼Râ+b@o¢™—&Ë›ÅMœ”Å“A僵“/·$;°4,'¾xIådÐÄ­¥ P£9ƒ49kâ ";u2Øo#˜øˆÑŒFkLãïpÀ«]Ô’#QâK|¸ºXÅQÒQ‰¯íúsô{»ÞWW‡-€°"ì‰/&Ù×\޵äƒ3Ò@‹ ’ó„eó’ÙÌå½”}‹AEŸ|2w|¼¸x­kžu­r¶$Ÿ_q´90í†àÔKÁžøˆÈ¡ÔB¥±Œ|»l1‰¡³ãn1´ñÜC-ˆÚ5ñ¡  µ Ñ´Ó+磵 ÉÊÀŠC":ðTƒ-ña»®ûmjèáU‡^(¡†™øœ”%õ„KA=xš+‚”| Æ_QHˆ<»^¸¼[©µ5»¼*w²¸·5°¸3I†Žë)׊g+[¹)»yÒœ°²&+éá,ùˆîƒÌ¤ âd–¡Ñ°1‚ôd&=¼en>=Ð3¨-´Ò€‰O–ˆ¢ù ¼å@)®’[9ÜË[OX^>:’øôØôR¹ùœjÙø’åAõ­5°(¯@j{]G4Š˜Œ5ñ½‰ÃÓtK|¤¥=ú%>2 ya›¯¬5¨Ë!+/-kÎ\!iiEE ÖŽrɲÀ:•Ý*9<5Þ×)Ú¶þ¥¶–[’;œÍJœø*UuXuäCäII}ò•Ö–òFª²rnX@N¯ ãé5Ð„š²² »¼<›ž¿¿W²9¼Ú,‚„¥ì|âNæàÕPìr …1ÊÊ tE‹¯­Ìcóe3ב/*õRM* I‘'2áÉÊÉYZ; ˱–Ã`M|4šø†qâ“¥=åd9y“l·G=#D 4b,¯*ìTàm )¥Ø Ĺãkk••kka‹W$}Kå+õœ„­Kåee2A-EggâÒž‘°ŸœSxƒ<·¿d-ö¹]€M|Ã8ñ /nn£5×S×#Å?¹8/SU§4 <¹®vC uwHZR 0DÁÖ1{Ü–òò•¾À~3ÖÄ@£%ß0.ù”}}Ù]}kõÄ¡‰OÏ·RÔquŽr¥~HÂ|à•)ÖñÞ(‰/.ÝÙÃ9%/Ž™AË’äŠ\äQG ‘sQl0TïºêIŠ Ë['»ñÕúb¯vh4ñ ãÄÇÆ¦ç«Ç§ÌW M|ʮꮠt‘’å‚(ùÌ Óm¥Ââþ(ÖÊ­ÒµüسRÔì€i.­( :^RŸ¢Ó@.34ÑAGT]ù ’ó„Ã->ñZ¬‰ €FßðnóÇL`‰¯¶6[ØÜÅÎ…!ŲB<ÍìD¤¸ðÄ©jÈ—¦§£”|éé¹–Ya~ÌvÁ!iÐAê4Œ¡>ÈzaE!!ðae›ÊÚbn6=eqIõX@&¾á<ÔÐÄfsû'Fø8Ã'‚É‹‚´)CIÉW‡Ë_uUòa$>îìôpÐ|†‹–OQš‹NTT¨šŸ¢Z¬Ÿ»†Ÿºêbe#y””ÊJi5V#`/6Å’M˜Ø1M˃¦IB U1x•3¸`ÁÀãÇ\*ÌfnT&‰0 kâ <‰¯i¡¤E}Ø×–¢­çCJ¶ÈÆ@UÃÔS\ò¡úÏ ú*ùRSÅKC"ìdì,,‚í"Â\¢\´‚c“âøbÜøøx—/[±¹‹ƒ›•“Q ei2ƒ‰³Øúy$Q”$ˆÄEž•ÁÐ ƒ¼ŸZ‰3Û¡¯  Ä'®œ—Äìk æ“L|:>±™Žeɨ kù€EŸ_º§§‰ªŽ‘Q •£d)»§¹|ZQsZˆKha°ÔÓA¤>м[¬……–†b’´k«c7Ä@D&>ôò s™)²ÊzôįÁ‘Ô¡¯À¯#¶Í‡ÙþC+±. Ç(ùà)ê%ÞÄGËF ¡Ä'éXæ¯ ,½ìì"´\BäS\’\ØÓ“³³QÓ¸Þ÷J×Hí7*’tÒSw•MO–•¬€¨§!/ïレ8°Ë‰ÍÐà÷cuñKÒðO'”øˆpâCYüVí¢$Kôà¯GÝïV‡ZíÖSPí¢¦.[:ˆªv‰O†&Õ.ÎôUòz9Jó;òi !ÁÎ:)¡jEì¹1þâeh U¯¯wºèT`ýjnî(ïž®'®qap†tp]œ]\àk÷œa»ÍÓ3ä ‹%c¸SÅ $>€"2ñ¡&=”¡DW¥É-ñ!íþC”|¨ëè‰L|ˆ¹(DKyÚ‰¨ %Ut8p® §c‡6ÃîífÇ;¦jðóƒg6\äuRRÔXSc¸%1*Ÿ¸0béh?°k.¯SNƒ °È;»„@w$9C§KÓõô¬j‘ÎÄ@4d®£X ŃÌ21ÈUp“–æaMd€ZzEiHSlònܾâÄ%>€^ö ”kÅùàÈ©ÙÀ²Ï‘MVXØìóâccó¶Î´¶òöŠ)FIzÊâ’zrlÏÐ¥{д¥!©vå…Ù’­u!S¹EÌ •TÌò@ lîÄJðÊД§Œ'ñÐhâþ«ZøØjkቯ6»–;ÞWÒËš'-MXY8Ï‹]Ú\™Ý׫€1¹Æ­ L||á•ðE°Z6D^Z’Ü|%½ÙtµÀ¼R sˆ¼§‘´[8hýh5>àI|4šø†}âsc¦>eXmšÊ“íë]ÌÆ#Ïln’fÄæËÆ–l$ÏnŧŒ|n80ñY[Ã9A¬5²—¯Z)õu+ö•_ ç#,_Ä\$-[é–Ê&«'.žJ\É@£‰oØ'>ÈÚä:˜¶ÄÅíÍååS¤¥Ýø ¼’…ã‹Ù”óá›7²k½¹­…C–çÁhy~“"ÐAºÉâÀv¢èð?v`sQÏHžAÞ\Ã)9=]>]²˜ ²‰Ð8@Ñ8ñÕ¡œfS‡2䌶ÙåìgµÐ.Q!Žh©Æ2ŽS-3hòY$&>HDOÜ79]A•=½8FXØ· ÝØV‹AT»zɲ U¢ S…ŠB@G[ÁÒ ¼‘¹¥°›$w67è\+ißÚlI6vÕP-nÇÔôÊR97_P‰2â Ú&>”‘=Ô3nOfAJ§u˜ßйäC]}€t( Ê!¦øê(N|ÀÄ(­ Ú\[Zª!,,çŸïpÄó9YR_HZ| )¨ç!o.h-kíT J|læòÑlÙÙ’Vr²¬)æòÅ’|lֲ젅ûÊC aæaM|Dój·®ý˜CÔsÐeÒ"—¬vá«cÐÚá“tN|ˆ-j¨g«aÔØf8Àí~ÌÄW ºÝÀKN¶´Ô<-­È¼H5œ)Šsg'k€v‘î*‚¶ûÒBä³A ”¹Å•­ÍÍ倉ÏÛ)¯Ä5ÙI.0PÎZVÞIÒâã£ÚZ`skâ º$>lç@âM|ø ¢GâÃRíÊ ,7¥âÃ<´ªåÌH܉ÏÉI9ËÔmmmv2w¼$Ÿ^Œ 33h¢ÖÄZe‡2»µ90µé”2ÈÃ{âO#Z¦*;%›ûfg‹³¹Fç¥;Æó±G³É–&ó¡'>ì%@Ñ:ña;?ù>¤P««C!&ñ¡Ÿg¡ž4>”Ÿ²²hÄ3ñ˹`…,g¢ÃÆ ZZ$²ˆ¾˜ÍZX8\9]X( .÷@3{ºzÉ8Iqeïe'n`÷„]>M'ÛÝ˼È>9Õ795ñSÖÄ@4ïpÔ™øPw?ÆÄW=ä¤ÏéºkâóçŽqÊΖ3­“/Kf‰ïrƒ$>Go¶@7¾dË¢"¤?U/GIXÉÇçïëìöú&³3脳ç1˜”Zù²'Cîiƒ óMÑøˆæ´zýøQ”£úÐû"›øPÎ…¬4‰å@ü‰O Ԣ̲AOAsc¶KÓÀg€6E†0È—ÚËÕúº!«râ.`‡ô:Ò¤CädùÜ0ZÜܾ æìÂò •ò•ì•y&ìÉlìNrÙá»±ŸX@´N|HJ ¡‰~@ø¶ùP_5Ò)÷ƒ¥ÚE 8B`¼;99áI||¾À¤#=$2 \$/'‡¢,¼V2Ù(z˜©|‘ŽF±w-zâç«Õgg·417©L®”©+/+—nÅ&§¬Ìlòa/ùh¨9‚™ñ­„ÆZòeƒz|€’j|¹A5¬tsò9¢!æì¨‰K’¯Ö<»ª|U… Â1G kõÂÍŒ*Ù’åÂÝøØdÙAWº±'[±=ñÐP=rÄ&¾:¼«ðÑ_6¬àS»Õ‚Ç£asPµ >8Ø¡`v;¬Pw Cš{ –a©«¿¸–¾³¤x²\¶Ue©¬Užžuzº°¹,;››¬8_6®Ä@£ÓkÃxz Xâ)ƒR´·[‹=ññi˜§NË…aÚî$Žºï#[<Ü$—ÆÀÀ"/ì›l%ñ‰s§úrHJ¦:9 ë”æù²G³¹9±‡ûºéùf;a?" €Fßp>¥Ê‰ <È*øøÀCÊXŸwº¨èƒt)\@󶾨µsvr­“<t›.ƒ|t¶µ9–Äç›ï¯—Íç•\*ÍÀPê[i"'—íä«ÇæËŽ#ñÐhâÖ‰OØØç¯-ñõüòaévˆ; Ë3¥A޽àëˆZ«Šgg×–BgØ@mÈÉÊëpëa¦ânIq·ÐÏ æ–: ®ââ’|N^n•ÙÙNX@9Œ‡x ~.°½"ù°'¾Z½áRÐ gÀ’Í. $DÖÝÑõŒÚZvèÙg. ѵrò ÒÀŽ2æiÙÅ|NrÂ&ð¾K^27°!Sãä”5ñÐhÉ7¬‡ä†$>qðTƒ2x¢K£äçKVeH¶úä“,üØ%QOJç®í$Op…„Kú2È ×²±aìÊÌÎöuVE>/ÜZŽO/9UØãÅ^òÐhâƉ Ã|ʰ’¯µ7›l”V”ÆÌ¬“¬¨‘œšŠ’:%¹³Å³…!Ã|E nþÀÄ—Îm?z¶^v)ÚŽe>'<ã|4šø†sÉ^†Ž1ƒkaeôÄ,úätBBÒ\x˜Cr4„ÓSá+« Ç»Ÿž0ä( yvqÿYv7l‰Øáõ5BÛo$W߯šøh4ñ„ÄW ÛSQ‹¥äË®w•MÞ¦„0„I¦gǦg£&>`µ- ¾Ã£¨TÃ+µ6P/kâ÷·F»¥#™M<wâ ÑÄ7tCx¤3ñÕZ¦…¤¥„8„È«&§Æ§¦¢v8@‰Oœ Ô‡-’ÏHI,.Á–øÄ%㽅Ѷù:¹Õ*§âL|4šø†ýB [ÒKšßÙÅYQÑÓÄ ·*yÐ%ã¾â8HJr+‡'玷·NÏ;Gyg×:òñyùbM|„'ñi‚ €‘HÂ`Z“PPhÖãR£IAâÓúú)B§êÑÄ[µÂ§,­èRäb§àá†[U­¬‰´pŒ¿$þħ——'œìäËç* ºíÃ9Ž/»6¾À—Mkâ ܉’Ü41ÒŠ&ñé‡&‰œŽô1Òº€>!ÕTO|š^Ó„g]ò““&IAGNâÓK „œtfX̆¹V ±þ*O2·1 %øáÊN|nâÀ XÍ„AÞÙ#=¾¤¶V’ÏW8kâ œ‰R°¡§=M°0$HJÐùp‡„=’4œ®G‰MH:‡‚?ñéW£&'p¡¦a ‹@8úðDãB$p“Õú¨"D'>ì) šÿ4qÉÇæhšÔ•Wöd¹ñ¥.qî|Ò •ùµÐíJ¾^&²ylz©©ÜµâÙNòX@¨vÑj]MXòƒ&5M¤Tª‰Îp ¸ 4ÙÖÓB­&ª!ÄT»úˆä„HúÈÒ(‰®ž.!RèºH}T¢Ÿ&¢äCk¤  T7 ÏÊõ(AŽ(4QB£P%'ñª§…0UÊÅ(g‹ãU‰¶­^®…î’S2b¼Äeec|ÃÁwXÊ•aM|D¨Í‡ZúiƒP–‚4ëá|”(ÐÔ„'>d6rzEª§4‘ ¡AâC¨Ö‡•ú°$ #ÉY–ŒjWµFÎeèA€Nj¢Š 3¡‰O³]öÄW‹'­ %>wqæùbÉî|µjj*úL¬‰Ôï÷ ·–÷JíšËöe—Æšøˆ¬Ä‡dMD»%ñ¡—|õX_=ºZ,Õ­jËP›9xÛ‰¤$>xIX}‚Ô´ÖD$;dYXeS䈒_µë«ÌGLÑ')'Ï /[«ÌMLb…(©…îîÕ«%¬'ÛDžûÜ.@ªv1òJµ‹®9Ð5ѪÝz¢ª]²Ÿ>žÄ§-ñá¨pÉ­v±&>Ô!äü‡šùÐKAl™k⫯Ç_íSòéT†0ðCvšL{±BÈÁ.z||Ä$¾±£Ñ4d¦pL†œÄ§ìË^TdͧgK|¾zµÄêt#&ñIŠ×bO|4:½6xf84)&;ñ…sÇȧEë±ûBŸŸ2q:kõ؈I|Ê|µØ«]€M|#~z ØååeágzV|¾µÊÜÔX@&¾Ÿø$¹•\Ù“¹ N>‰ €FßhÉÇÍí«§‡TÖ«å¦Oâ ÑÄ7šø@— óñqóÁ.Aöaé’øh4ñ ãÄW?†œøˆ@âÃ÷ÕM|£‰J‰ €F•Ÿ&ŽÒ¤kà ­Ä@ø“¢­ÈCž&ÀÄ]À§>Å^ƒ³©½x™Ø’_fM|(‰ €ð,&ÅX‘‡´ž`àlÕæâä%úÈk èTò!¯œ…gVîhâCM|„·äC¬>A¬µÓÔ¬¯è’O¾tYc­dMH²õ¨‰ OYâ ÑÄ7ævëêÑÒr•Œš¶pW»¹:ôÄGnµ @£‰oä$¾z”š©wÒoÀÙá@êz §Y :4šøFWµ1ŒRG©±X@&¾ÑćjFI†.B½Ä@£‰o4ñ Øô@&¾ÑÄ7`‰ €Fßhâ°Ä@„O©B9•Tù4Ä:MØÊS¢CäD8ñI²ò+ðð0è0ó0 q Ïhâ£(ñ¡cqÑS ÒÑHð~êÑΡ#2ñ]òI˜±JSŸ<ÏàP·(ðKÛ˜&>r@8·ý¤MÔ#»p$>”yu¤£MQøj¢(Á~r14ñÙ°òó+È+ u ??ëhâ#?ñ1Õ.J‘†¼žYË1}õõøNÞD]i„)ŒÍÍ* zXöÉós +« DÊI|u„e@‘šø‰P#ñ!ŸŒ5 ¢-ðÅ8n®Wâ3´aeÕe<êA³¡“øH[¦qâ ê˜%þć*‹åD‰Ï@BÂÌLPWpð¨[ÌÌ$$ {âCZÊ‚˜C_Ç4O†´hÁ®«£Aâ ÒŸ&jÃOå´uMÔ~ õª]`ê&? ]‰Áàn:m'>”ExHµ¨‹ kšÑÔCØu”–‹X@‘”ø45+Ú’zÔ¤ƒºÍýà~MÌ…ùõšx:ÀÔNuƒÀÝtÚ l×c$¾z,KQê0Ö:CJ>$¡:xÊ£Aâ !0È<ê.Z%>T%(«`Ð×TÑ$ñÐhâa‰Ôj—–%@&¾ážøP¶ !ö¡­á«Ãì  /å£8ýaM|4šø†}â#k@¥ŽÊc1X@&¾‘”øˆ2¡Kâ ÑÄ7ÒJ¾vrâ ÑÄ7šø,ñÐhâM|–øï)Ux]N=M|Ã9ñù%ßhâM|&>€ÂDêá^päæhâΉ €,&E\Õ©‰ui­ÏþM|TJ|ud™T‡4ú\G‘_±&>€"p8d=rs4ñ Tɇ1ï†v¦ 5@áïph¢%>Œ{‹‘kåÑÄ7(b1Ú´Ž5}ðYµz”C^Ы¢Jâ bª]´Vßhµ;4_ö.[bµ,ñÕÁë_´ƒ†(K|DL‡¹ÄCÞ÷C‡#7GåÕn]}Z²yuHkú0ÏÞÃ,ùšR§Ú ÑAæ˜ø0VïÕ×ã.‘|n˜:Õ.@&¾áßá@IQu¸«Ý:¬Õnj$þH>‰ €FßHJ|XßC>—5…¢ µ 3­#9ýaM|4šøF‡Zèê0äÄ@£‰o4ñ Xâ ÑÄ7šø,ñÐhâM|–øh4ñ&¾K|4šøF߀%>€M|£‰oÀ@aK|ƒ »Ô]$¹kp: 9ñ¶Ä'Ê8X€(J$º‹$w N‡!'>€Âšøj @‹äQw‘â®Áé0äÄ@£‰o4ñ Xâ ÑÄ7šø,ñáÄÇŒD¢f €É1£¨‚È0#™ÁŒÉ¤ ’ñ8 æ*€*.Ãøð…”d¦“»ˆK|D8˜f‰ €ˆH|Ì0«ë˜‘Ò<`™Ñ‚™ÝG'>üŽÂm u\†'ñp.[hà."ã–¢Nâ 4kÂXh!†™ø €c0æ €ž(™øp8 ,·‚Q’é2bÝ…Ïaˆ¼Ê ) WSÕ]$&>,!‰.…=ΰœCN|DLµ‹Z°º¹ªef†×¿ÌÈ^ªeFJ“ÌX™ÙÚêd=BÕ.NGÁìF¶ˆQw‘é2"Ý…ßaðćl=ÍÜElµ‹'z1¥˜‰-Šq9 9ñɉÚ G£•H*ÈrQîÂï0,‰Sžjî";ñ"%õ¹âmóQ½]f<áÆŒÖXF+!y…øjäè Wbz»ø…\K –|¸Œwásjn…[O3wÝÛÅ’ÈHZµ‹Ëaȉ €ˆO|µˆ±D‹”™¹[⃠À©ÍŒ¿ÃAÂP .GÁ-`íeÔ’*.#œø°9 ­ª@ëPÝ]¤%>lÑ[‹œHëpÕÛ a;ÈÌ€M|£`À@&¾Q0`‰ €Fß(°Ä@£‰o Xâ xâK©£€ö )ñCÍ(h4ñ‚4šøFÁ€€M|£`À@&¾Q0` ÀŒÝ4žCIEND®B`‚procmail-lib-2009.1202/doc/article/pic/procmail-bayesian.png000066400000000000000000000404361130547513300234640ustar00rootroot00000000000000‰PNG  IHDRnã­°cºgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEAФÝÿÝÑÿÑk†kÈÈëÌš33Ìâÿâ®Ù®999ôÿôçÿç Ì™rÚ¸îÿî5Ï ‡‡ÙjØ´±Ý±&ÍœòÿòŒâÆŠ¬Š½í½xܼžÆž©ëØçѺéºùùÿYÕ­HÒ¦LLLýýÿ™æÎööÿÖÖÖ‘µ‘t‘t—åÍÍ›†àÂßÁ¡É¡ŽâÈ~Þ¿¨¨âtÛºªÔªgس…¦…TÔ«`Ö°JÒ§FÑ¥MÓ¨<Т––Ý$Íœ2ÏŸ/Ξ8Ï¡hhÓŽ±Ž!̙͛LM¾—½—µâµ·å·wwÖvvv~~mmmÚÚñUUUããôx–xpŒpééöçççffõõûïïø€€€êѺحž¸ðâ™fÿê÷Öµïà¶ðá·ðá­ìÛ²îÞ·ðâÌÌÿþÿþ))¤üÿüýÿýûÿûÏÿϯíÜÍÿÍÎÿγïß´ïßÌš®í܉áŪëÙ°íݧê×¥êÖ¬ìÚ±îÝ÷ÿ÷ÒÒþÐÐÿÓÿÓÏÏÿ¹ñãÌ™ÎÎÿÍÍÿlÙµ?Уc×±qÚ¸€ÞÀ«ìÚŸèÒ[Õ®±îÞ•äÌ]Ö¯´ïàVÔ¬PÓ©¡èÓ¦êÖ£éÔ“äË’ãÊQÓª èÓ›æÐoڷ̙̚„ß›æÏÌ™,ΞãÉdײ|ݽ‹áÆ0Ο:Ï¡¤éÕDѤ*ÎøÿøùÿùúÿúÕÿÕÒÿÒÙÿÙÖÿÖÛÿÛØÿØÔÿÔöÿö¤Í¤ìÿìßÿßäÿäÔÔÿëÿëÛÛÿÖÖÿéÿéñÿñØØÿÞÞÿññÿááÿïïÿììÿääÿééÿççÿÌ™vÜ»}ݾ¶ïá èÒ¢èÔRÓªnÙ¶hزÌš£éÕôôÿ@У_Ö¯"Íœ˜åÎ{ݽ'Í”äË+Ξˆàijîß\Õ®‘ãÊ^^^Ö›„™¿™šÁšœÃœ“¸“•º•‡©‡£Ì£òüݤΤ¦Ï¦§Ñ§ƒ¤ƒ¨Ò¨‚¢‚¼ë¼€Ÿ€åÓ¿™™™²ß²¸ç¸|›|‰‰‰‡‡‡‚‚‚‘‘‘z™z½½èŸŸà±±å¸¸ç²²²ÌÿÌÌìÿÿÿÿŽRˆ2=¤IDATxÚbø? FÝ@1ŒÁ(  Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 èhè&·?þÀ$(FàPGWc>MÄHž©0Ä@ó…Z%7âÌFS„CM܉7ɰ²äFv§NÀís0ÑùŽœ`ÿCNráé=“<\èšÜÈó"õ €hªþÓ(½ý'Ë`¼©¿YÐhÚ¹úÑ‚$; ³YAƒ@Æ ˆnÉfé4sÿŸÜHi+Ræj5=UZVèÿ¡kr Ñä6šÜè˜Üh„%·?ä'7ê¶BInQÚ!ÅÝi¢grÀ‹ä‚ ÿÿ™­ÖªH—uè¢ ç¤ïí6nbŽÓ;g‚á>V‰¥‚Á¶£’‘uá¶U<ØI«uŽHÞ¾Ol2Àë”M’˜Ôª¡~ÜØ@^Áß[¯ :'7xbøåP<¨RŠ´tôK¤¡Ú‹M1²hºq؇i2ª'`Þúƒc<÷XÑlÂeý\þ` LTcp–nX݇á\ä‚@ôí™"’Fé„pÐê?JŠC ƒ?Ä&·?ÿ±)FO³¨Eû0Mþƒ^¬¡¥ýÁ×hÄÞ„Âfªõhåv9 aÜ£gTÐu¡¡$€¢WrÃRê fœ?¨ÁŽ5б„"ÎðCM¸œ[óBöa/p%7Ìb{jÄŒrÌ"ï. زö4ŒÅÇØLÇT¦D‡äöµzúƒ£–%.‘’šÜþü''¹¡ˆãJúÈ>æž@ö¶lùgy™ÜþàLnøºØ}ŒÙæÁ*Ík$€¢_ÛZÉíQÉí¬Ø¡8¹á-i±y“Ü䆻5#¹ajÀÜþP+¹QÖE ¡–Üþü!PºÁ“u’Nûð&·?˜-7Éíÿ¬­QLëQ»õˆKnc(Knÿ)ÿ ¡•Üð5ÝÑþ#KfrÃcžá+²’Û”áÿ8½‹ÂÀß®ûO`T‰ŒäFiz Á“ÜÐ.þ“ÙUøëÖþ‡Ñä'7|öaw0É QUÕUÀ¦—ÛþS/¹QX¡РHn¸r4¡!ÿ8«¥ÿ'7Böaw0æëìrŒp!äÏ?X{ò’ö±9É s)žW Knè#>°PÜþciLS/¹!Rõ"’Îñ-ÔäöŸÔäö×hìô‚—Èq£ÿØ2öÑ*r@ |rCŸØÁ›Üþ *K|É [µƒ>ñCx ‹}0çŽþ5‰c| sáHìÖ£ýù)÷mŒæZûÔžÑ^l–’ˆË+qEfEð!„4!Нtû1’Œ9K‹;¹ýAÏÈS °Ìcb7G¾Ã1?‰ÑXDš«Àb- ØÕl>þCô$Jðˆ>‹ÇѰ'FÌxÄF£ÌýùÿëÌ'æP>J¨þÁ6‹ÅI©K׋·p „b™¢GÑðÛкõ§cjÀ1ߎl Ž•Ø²š ˜–’ht'MòÙh`4šÜF“@&·ÑäFG@£É=ñÑÔ† Ðhr£qW| €Mn´(ÞF@£ÉmÐÐhrt4šÜF@&·Q@G@£ÉmÐÐhrt4šÜF@&·Q@G@£ÉmÐÐhrtDrr#¼n•(3FçzF$ “Ù &¸ ˆÉ ÇÞÑ7@Ñ%¹aß*5šÜF Ln£émä€Èä6º6lÄ€Mn£€Ž €¨•Üþ`?wk¯`4¹X@ÔIn8·/ãMn£©mÄ€"?¹¡Cñû&q<Ém´§0ò@‘“Ü0nÀ¤þà?Ó}tØm„€¢Frûƒï\¬Ñä6  €ÈOnˆ¤„íd=ÓÑô62@Q£«€õPl, `é*Œ¦·‘ˆÉ -)áwMo# ­’¶®”8 †7 *%7,g‘ÜFK·‘ˆ*ü°´Hn£}…‘ˆú³ ÝÎÑžé(€€¢Òœ)xq%·Ñða €dkÌhZ© €Fwb:€Mn£€Ž €F“Û( # Ñä6 èh4¹:€")¹ýÃÐ'¹iÉíß(¦€NÉ €F“Û( cr Ñä6 è˜Üh4¹:&7€Mn£€ŽÉ €F“Û('·0 ur *%·?`4@xùHšGc{¤$7€¢Véö–êþüƒ"D„pÿ '¬?£émD&7€¢VéIM(…Úx2‚¦´?¸ÒÕhr)É €¨™Ü ÉéÏ?´äý+ÿ@ÉòÏ(Mn#(¹í’ÛŸ¨É Úrû¯Xÿ@ëÞÑä6r’@Q1¹ýù‡œx: ˺?(µ+1ÉmDÍaóä@´Kn(,¸ lÉíÏhr)É €¨“Ü m1ôÔ†Áüó‘*‰.ÜF“Û0JnD•äö:ò…ø÷Ñ€ºýANšZr£ÉmD$7€¢Ã¬Â åG“ÛðIn4ðÉ ¡£Émø$7€¢ÇœéŠRÛ?¤µÄð%Åp1„ÛH;|¶ 9dš#Illl#.¹Ð˜¢ÿ–¶þ 1QÒÝŸÿ¸“ª?ÐLÁ&ÿŸ!êp‡+µýyÉ €†PrC‰Í?Ð =a:PŒÂ•ÚH RSÛ¬Lhx$·?ˆ$÷"ˆt!øÈÉíD íH“?s ç‰ýGýiÂ4ùHN¸õÐrÃ6pU ­O‘ªÕažÜh('7´úëÒIÔixzùo°ýÁ(ݵ&BÉä:É,¸:t3ÿ`©©‘‰j$µ!S#!¹5’Û̈ lÝDA:[Ó¹ìCIgÉíz2FM–è|fþAmÄýAK{h &5xr£×>¿JnD•äö›T@lrÃYº¡6öÿü'*¹ýAê‘"³ù=yÀêVÔ䆒¦±™‰%¹!;ÕXCOnô*Ì(¹ÐÐIn°D%jC#5bA„êR$%u(é£pûƒ·.ýƒZ5#nØêÒážÜhÈ$7hÅúåN¤^±¢µ÷Qpðþ´ÖòÁ®0 u0 ·?}‘ÿP“úƒn8aö†{r !T™‚  èy†8ÆA†{r ‘›Üþ hZcû?"“@ ‹äFNÒù3 EÛÿ‘™Ühx$·Ñ)ú!’Üh4¹&7:&7€Mn£ÉŽÉ €F“Ûhr£cr !ÜFÁðIn4šÜF““@&·ÑäFÇä@£Ém4¹Ñ1¹ÐhrMntLn4´’[Ä`TM(çå Ÿä@C,¹ý¼ ‚ºÉ 9¹‘¶(u0'7€MnTKn!”§5œç{R;Á Tr Ñä6X’áôDÅâm ’@&·A‘ÜH*»þ Ýä@£Ém$7+J*”r•Üh4¹ tr#½Q6„K7€Mn^ºQØ K÷@%7€ªÉ ±62Ò DÛ€÷LÉJg†Tr !šÜ¨˜Ú¨¡w ’ÛØÁC)¹ÐÐLn 6Øð% ,X‚fƒëcƒ¦U6dˆ^$ål´On”6ù)Œ¨ä@âtƒ' !X‚%%01¸.¶¿èÊ{r£ ½ Tr áÜØ` /6Ôr‘j’,Á!Š0”äF~½JFrû7â’@ §Ê”í/)É {éFÏäF¥Ä6”’@ §®¢…]lˆFRÛ Ò~C¢` I9Û Onˆ7t’@ ÑÒ Oj£N?“¦¥5'?ÉKp•Üh˜ó²±± ÞäFåµD䤷Jn4:«@ÝäF‹£åÉFTr Ñä6ô“FTr Ñä6šÜè˜Üh4¹&7:&7€¢ÉíÏŸ¿@øŽ$˜ùNáHÒpK¡ˆŽ&7ª€šÉí$üù ÇÉjÃ-Kj4¹QÐMnÿ"'·?±'7hÁ‡–¦ÀB $¼øBH!”H‚£Ér@C¶2ýƒ”˜`©ƒpiMaHÉ…åüA)ëþü!ª„CInxÇ&þüÁ£_rûóç §nbØ0’@ Ý®Âl¥Û´J½tCª~‘SºJ2þó—ôä†/U ®IúCZrûóŸ´kar ¡[™bm»ý!Ø<ÕÜþüÅÕ$'¹ý!˜p]pI(¹‘ŸÚCr !šÜà]QÔž)…§.E®‰aSêš-$&7Ô‹÷¼Á®VúƒtYr‰/¹¡Üiƒr¥Ò ÿ÷IüA¹3b0$7€QãnÈ’"gÜí–K¸0îÆB¾c„˜äöåJ$Ôëåþ ¿fq×`In4:ÌK“a^¤‰ï<ÂvmZ‰¿gŠ5­¢¦e [ÿ ¢Ê €F“-’òp»”°kD%7Ì¢orC¾tsÐ$7€Mn´Jnp^mŠ!û‡˜®ÂŒ*{jÃZƒ–ä@£É6•)¢5ÿóB8´+ ‰Lnˆ®ÆäÆøõt¨÷Ï¡vVIr ÑäFû)z”ñ2B#„fþ7è1Hgh4¹Ñ'¹¡ÝèKvr£ µ †ä@£É Ðn1§ ¹ýÁjŸ?C¥t Ñä6ºÞŽÉ €F“Ûhr£cr Ñä6šÜè˜Üh4¹Ñ<¹ýMnp@£ÉÆûLir-å›S(¹ÐÐÝ«€I ÂäF£[8†lr ÑÒ†ÉíÏŸÑä† h4¹Ñ,¹Ñಗ!ŸÜh4¹–ntLn4šÜhÙvÐä†ÏâJn4šÜ†mWa0&7€Mn£=S:&7€Mn´­L©zvàÐOn4šÜhÜ%¨ä@£É¶=ÓÑä†h4¹Ñ4¹ýMn( €F“í’ÛÀn[r ÑäFã)úMnYr Ñ)úÑäFÇä@£¥ÛðNnWr Ñä6œ“Û¿Á–Üh4¹&7:&7€Mn´JnKzÃV£Tr ÑäF³äög´ÞSr Ñä6|“ž(*¹ÐPMn˜wþ± Àµkƒ¼í6ø’@ £ûLÙ¯•ÄšòØFZWaÐ%7€F·5Ã/hF\Š‹ro.º.¨Ø_„B666ò“ä í™b_p7PÉ €†W醸ô› ‹Ö vÙØPt‘ŸÞerû7È’@ Ã䯆THÁ®þÆV™B¯G”‰Ã1¹ý\É €†WeÊOS¨åjY‡MËp-ÝpLd Tr áSºÁS ´@Cj´!Sèê‘(rÉ@¬ ¢³yhˆ–nÔëd² ƒžéÐ9’ €Fú0/õëF“ €FgFK7:&7€Mn£ÉŽÉ €F“Ûhr£cr Ñä6šÜè˜Üh4¹ §äöçú™÷þ ªä@C÷>Sä»HáþE\pú¡ðï”Ëå±"6×R2(J7ôvÿü\É €†jé†|<ê ÞðÛÂ1/ Çsï2{¹†@rC¿>ðÏ`«Lh¸$·¿˜É óšú?¨¥rQ÷ç/âöyäR©LüƒZÔýùƒZ\–䆸Âý6™AÜhh'7¤b Wrûƒ+¹aV•ð_lÿ³jEN…ä$7Äú mýíŸ?¨¸NïBi»ýG\á<øJ7€fÉí®Ò £|Â(Ý ša Ñ®¦ÇLn)¼Ò ‘~þ óaÂ(ôŸ8–¤£7ÝPn‚TÉ €†xrƒÕ§ 4rÚnè‰ôº4ý’z²É¢‰ Éä@C¿gú©OŠÒ7Eí™Â /\u)¼‹TþAí÷BMGîâRÜv#6¹ÁÙø’âKl©m0$7€w#·£Jž)5“ìÒføÝáƒ/¹ÐhrÃ^Ö ®äö›³ ƒ/¹Ð JnQéöw€“zªÃ›ÚpÜÙ‹q÷Û Hn4˜’ÛŸÑ䆾UcçÞ¢çL1opÉ €Sróý3šÜ#nXK·?C|Š €UróE+àFnrû÷¥c0l’@ ¦äöíÛ?ƒxŠþ“ö~蟡¾ €SrûðÁÃãõŸA:Eÿ‡"'·?Ã"¹Ð`JnÀÔöòùŸÁ:E2Ë@µ)zxíùor£è8%":atJn4¸’0µý9Sô4\üpÏ` ©ä@ƒ)¹½§¶‡ÿ Ê)ú?i1gúå,+@Жˆ ñä@ƒ)¹½§6111´ fPLÑÿùK«äF{0x’@ ¦äöšÚÄìíÿŒ”)ú–Üh0%7#xjSUý3B¦è*Pr º$7P&þ@Ø8$µÙƒRÛýFÆýKnDŸäøDþ ùý‡™™ÙÔ€À××4¶ ì‘B: ˆÔæìügtãßðKnD×äÆ In(© <¶û©Ù¦ ImÎwþŒ&·a×v z&7fHrƒ¥6_pj󀎶¡¥¶;wîÞû3šÜ†[r :&7fHrC*Ú°¦¶ûàÔv÷î½{’ÚF“ÛðJn4 É 9µÁÆvÍ6pj»JmÚèém4¹ ñä@‘ܰtÄ; ðÔöèÑ“?£Ém8%7€¢SrcFJnð¢ g'T‘‚RÛ“'OŸýMnÃ(¹}’3$¹ù’1pEúèÉÓ§Ï^üMnÃ'¹=“›4¹aImöèpj{LmH5šÜ†xr :&7?hrƒ7ÛðuRÛ Pj‚?£Ém˜$7€¢rC4Û^bo¶Ýƒ5Û€‰ ”Ú„„„þŒ&·á‘܈®ÉM ’Ü`)¾NÂSäÔöîÝ´äöçj4¹›Ú,¹’›ßp—œÜpíÞAo¶SÛ»wï\\þŒ–nÃ!¹}’›(¹©A’¢Ùf„ÞlCJm/PS›«ëŸÑä6 ’@Ñ5¹ù‚’Ž hDjs¥¶÷2 @MnC<¹=“›/8¹ái¶aé$ÀSüMnC=¹’›Úp—œÜpí"u8©ÍšÚ^‰ÿMnC|½@Ñ'¹©A’Û7Prók'šÚ^½MnC<¹=“Û· ä†oÖNÂ{pj&6äÒŠWL’0/ MnD€¢Sróýî’‚’Þ ¸šmÔ1hRæE¨£É@ôIn¾ äì’‚’þ ¸SÛ`ˆà»|—<âžfdðËé1.hþ‹t­ó_˜ÈFBEa꯹Mn¤€¢cr7Jnø€`i¶AR(4ð–nh·Ê£J±aH±¡ë‚¦$6¡õ&B,åŽV¦d€¢SrûöÜ%%7B @°wÀÁñ@rƒ& ä»èQ“ú5õÊ!ªPKMhñMhllC0¹ýÁ8ÿr@“@Ñ'¹; à.)(¹^‚¨Hpjû‡¯2E-Âþ¢•Sl¨Í-6”&Ž2ñ/ºrrû;šÜÈDŸäì$€»¤äFÒØ.rjÃ_º!nl¨é·6ÆÐ[pllHe"ª6äÒÙd¶!Vº ’Ê €è“Ü<@É t–(¹±µÙNm(Sô´é˜²‘$9í¡_zƒ3Š:ôKéñÝP?8’Û¤t†R¢ŠbH¡õ0Ar Á”Üþ¡Ï’YºÁ/œ'”Üþb»Ôû/æ<5–äk˜Á»þüGjÀÁS¼ /ÿ ®Ê €Qrû÷}NÏ$zmJdrÃ’Úþ"­e‚UËØÒãþ!8«@ƒ*¹\s«Îûƒœêþ Òú¬*Îäö£ztÉÒÔ6’@ “äF\Û O uqÉ$Q “Ûj%·?†Aé@Ã!¹!z¦Ð N!J:|=S¸(o»¹j¤NÑа(Ý(TÁº­x4¹Á@&7êóyFÇHMn4šÜè’Üþüù7¨À@%7€MntJnF“ÐhrŽ¥ÛŸÁšÜh4¹ æ¶Û°Kn4¼“=wÎàë™Ò9¹ý´É €†yé6’QñOßÔ6`É €†hrÃB|0÷ÒD*Œƒ¢¡ŽÉ s T¯J.¹ÐÐLnu%êÌÕäiÔ?è*Ðföé™Üþ ªÂmÀ’@ ÝÒí/Ê<<®ä†2•JÓÊÿ=ýÒQ6 Tr ¡ÛvÃ:/O ¹ Xé6šÜ €†heоN (ŠÈÀ·Ýè—Þˆ³g ’@ éžéŸ!0îFçôF¤-•Üh('·Át 1Éí=RÛàNn4:«@¯äFôF´•Üh4¹Ñ-¹Ñ!½mÁ@%7€MnôKn´Ooþ òä@£ÉŽÉíß Y‡4PÉ €F“=“Û¿Á²êm ’@&7º&·#<¹Ðhr&ÉíÏHn4šÜ†Grû34’@&·ÑÒŽÉ €F“ý“Û èžTr Ñä6šÜè˜Üh4¹ @eúg«ÑMn4šÜ†xÛ¼‘ãJn4šÜ†vrû3´’@&·Kn6áþP2+6PÉ €F“Û&7ô´BÊÙ2àí«dÏÁTr Ñä6p•)Fj!!¹QxÄ@%7€MnÙvCK0$'·!7@£É‚†ÌŽ ¡¸¥O|rû3D“@&7 ’[‚µž¼äM8¤&7ŠOñ¨ä@£É‚ä¶œà"€‰ ”ÚÈAJ7¤'·¡Öv ÑäFAjpZ£$µ!—pDÇÃMn4šÜ(Kn@YjƒŸ!§'Ä¥’ØB†æœ)@&7*%7jL …4äf¢ÿØ/ïºÉ €F“’Å…zrC\ IÉ]σ0¹Ðhr£<¹Q+µ!'·?ÐnVÉ €F“ÛàImè¥ü†RôBnè&7€MnÔHnÿh™Ü0RÛNn4šÜ(MnÔ+Üp%7ŒÞéÐMn4šÜ(LnTLmÿp֥æ2 ÑäFYr£fjû‡4ê»æû–žÂNn4šÜ(.ÜþQ;¹áúÉ €¨—ÜþŒÄäFÕÔ†T™þù?<“@Q1¹ýyɪU)Rrûó˜&7€¢beJBzFÉíß?šT¦Ã4¹5“ÛŸ–ܨœÚF@r jvþ8ý1É©m$7€¢nr#6½ ‹äFå†]Á@%7€¢ê@(½ýIÉíßhr# µ“›ÝŸ’܆rj°ä@ÔæýcgGTzÉmH§¶KnDƒäæögø'·ˆ¡ÜpÀä@ÔOnnnFDrû7šÜHDݶ$µ Lod'·A†vj°ä@´In–h“Üþý ,àßhr#µ“$µÑ.¹‚!܈ÊÉ šÚ~Œ&·Ñä† ’›ÞŸÑä6šÜ0@Q7¹ÁSÛhrMnØ@Q%¹Á<µýüƒ(£€V`€’@Q#¹!ÜŒ”ÜFK¡UÜÑ'¹u“<µýú>šÞF“& j'7XjcMn£É ÐhrtLnDåäOm£Ém4¹aDÝä†Hm,e£ém4¹a€¢Qrû3šÜF“@TMnÿþÀ«Ò?^£Ém4¹a€¢rrƒU¥£Ém4¹aD›äT8šÞF“& Ò’A/Üþüñ)J€>É €HׂoÑáh¯Äü2 † ur Ú%·Ñä6šÜÐ@Q;¹S›$¹¦·Ñ䆈ÊÉ-ä(µA’Ûhñ6šÜÐ@Ñ2¹‚Ñ䆈úÉ ˜ÚF“ÛhrÈÚþ¦6Ÿ?ÿGÁ(Àh4¹:€¢zr¦7ŸÑä6 °€¢AróññMn£+ ê'7`zó”é­ºú££ã̙Ӧž:5''‡4€ÀÁÁá‚••°°ðåË—/¾:k–ÍüùÖÖÖü@`kk»`……E}ý9†E‹™™™ÉË›¹¹yw÷ĉ'Œ»ºäääZ[ottœ711ih˜3ÇÐÐð” `]]ÝÉ)SyõAà°\š;÷ˆ®®nS“––Öôéššš×òòòæÍÕÑÑ™=ûæ„ ýýWÚÛÕÕÕ/*))͘1y²4´´›4©§çx_ß™… ‹ŠŠz{ ¥€ ??¿¹¹¸¸8rssÓÓÓ JJJÚÚâ@àzVVVvvvggˆ‚p¨ª¢y-’›¿ðhrMnØ@Ñ ¹ýÿ<šÜF“V@£Ém4¹Ñ1¹-’Ûÿ?»ƒþŒ&·Ñä† ˆ¤ä9¹12 ˜€`ÅŠŠŠŠµk—/_µjÍš•+W¯füôg#;lÚÄ Û·oÙ²aìØ!"ÂëÖ•––.Y²té²e©@ )@£Ém¸&7€¢Ir¦·Ñä6šÜ°€¢QrS–ý3šÜF“ Ú$7Æ?£Ém4¹a¨µc@ b#¸‡ »l E°°DÐRÞ=nåÖÎü n‚›”XssÎM.7›™›ÎÍ‚›àßq«0S7‚@ÀâÌàˆ·@xNåaÂMâv8»·-wÓvói7[yæf›Äk7ƒ÷ÝdnÆn"^¸™¹Ù€[@´JnÿüIú3Ô“¸tã§VéöKé6_év{é†HnRC.¹`ÞŽm†(€Ò0;Ц`˜´¤  ¦DBBa؆Xçü\@™Aaûìsù¤ïÆßä¶ñÏÜtºyià–å±¶àiàÆ¦õvK¿¸™¥jFn Ür4rKn„›+áæ@¸¥m77÷S˜RÜ(n¹vÉø„)Åps¦ïÓÂôý_o™Qܲ†[æp³cLݶ„›-§lÏí%³u¬‚ †aøBºIrqðJZƒ’Zœ¥A‡¨%hÑ[‰’¦¦º™wð;ÿAðAŽxøÏöðÿÆÍò6Onöï¦%ËPÝä4å£ óÖuÔ5 n4qÓHÛŠÛÊs#Ž9_é—žU%nDG †!o½Š‚ªcÝ´w8nˆß=⦼auCuÃÕ qÃ_¦,Jž:yyau_7ݦ¬n²æÕó«ë[}ïNÌ¢nƒÌ×Á € DQ{°!±&Cc¶óÎdY„x6#áøò'üÊMÞ&­[qÝzn›ë¶r››êÆP7¨cÊ2pÓ7ê˜cªK×ÍÜT·7ÕMÜtººcڸѾ Ęú½ë–Ü®—grÛ“›êÖ¸á¼qÌÂí@´KnìÀä–ôg(&7pé†R™.€W¦h¥¸íöçRr—n“RÏZºÁ“Û„?X’¸í†™Ü€é@r·ÝOr Z&7pzû34’Û|É V™Â’°ÈÀ_™âHn’Ûb“Ð2HeŠHn°&·?˜Éí¸2…'·?žÜ0cï6Â@ @GaDMà Ä)˜‡‘\àOŽL€ RDC:+ç—ãæëMÜïÞÝ7w·A…íénð0ÕZá—.…ên'±€I‰ $…¢B¦ZK>´B…9Tpw3òƒ‡)Ë›ÒP¦ˆLáò6¨ îÆ}‘ 9*™¢d*)t*¨»qEu7Ø¥…Oãv Z&7Xzû3:«@Ò¬Âfþ6Ì;ÐÉ €hšÜ é-éÏhr#!¹ý!aëi³ º2 º$·$PIIn@Æhr×Ü@ãnÄ&7иÛКÄ Ú&·M°ôMrÞÃhr±SôDã䆜Þàén4¹Øä@´NnÜ8ÒÛhr‘É €F“Ûhr£cr š'7émÈ%·?¸’rrcCMnlð䯦ÏÄ'76&·?@„œÜþÐ-¹`¦ŽmvÞà¤EÀ—<ÂÉýÜ.޾妒›’“y7Ž»±¸á·á»Qrc¿mÜ$ÜôŽÛ@tHnXÓÛPKnä$7x鯯 Jmx“›(ý’Û–n˜µc„Á ÃÝ»„`oa« ®â Š8`¯¥`á.àX_á{žš ‚!>’öá?ÈÝÜù/n½<^S¬æ–š™fõþQ#·DnYçž^ç­…7âÂ’, ÝL S«›©An0pãøáVÍÔÏO˜ƒÜ̳™-7Ó .gørƒ«/'pBnF¹ÑמâfØÁ6ÞÍ­öÝjfÚS¬7·ÞwKnIqólÛKâía ÂpåÛÚë,’"˜ãö6 à ("ä,ž@ ñ._á|›E …½A& 3û7ûôδÃí·ÿVô¾wÛ7 }o;úXÑß¼3=èÛœ½5í[X[˺¦I7ÎÓ qc¼"¤âFž‹YF‡[¸ºÁõÄ%%]ˆUåÜ<ÝÄ ’„ãƒÛ7y+K†ò&n(ÝØ tc¾vpÂ6((–Ñ›¸Åt {·f^yŸYàf¡SðÓr³ÉTÞì§?Ó§ÄÚ» €0 „áîf@l@ÄjTY±K ±Ó¸ gç…D eúOÿÎ'u;öo?~¯Ô}á&ÌÛ)qLùdݶP7åÆ }æ†<¦€rcÝ€4¦ÆmÔºen¨ê†&rÃäਭ»¹õÆ sÍm5naL±<¸qLÑ7ïi-Œ)†T7û€dÞ"7=cIá&bÜ>¬Û-svl Q”êÏ“0 d Zf`<[ 'K´;<}_”AÜ.³ßp[Ëu›•›o7á¦u›NRÝâe ‰›ÖÒ¹ÕíFç±Ý¨Üx¶^7çÆ·zL÷à†_Så¶ñÖ-¸µífí‹^ë¶Žæv À¼ãQîÞ%œP¥pj…Z¢§s—p˜Wx3³D„D¢q‚Ïþ;›Ý·1eN7ý!⦯¸q$FL9ÅK,ßù³·Æ”Ó;n[L±qC{ˆ)–˘:7›MçÈ©F òÕMËŒzã&m4*`?FÓ–%nÚ»ÁG4ÁMÚ Ô%ÊÔÒ nbʯ¸­kÆ(Â0E‡xÏãuÏ#x'Ï÷ÿOÒÒÁEA …ÒÎü<ÈÜ,3yCß7°»açßἆSÛ¼È}7<Ä Ÿ…)¶{U«*”ÙMoSn°E˜šÂ4TAÅÙÍd Sòf&UÈ0UÜâ%OÈî&3­¦ Uà-Þ7«¸±ÖÄM¦@3õæ–¸qv“*n²…&Lá³[« ¦Y¿¨Â%€È/Ý`É –Ü€¥Ûš?+É Rºa$7>Ô õ¾äö' †Ç¬ƬÁ6uxé†:ÂvfáB`‚¢³ DãäªL‘Vó"'8\É šÒBшlj„†nrc#œÜØ “XlJX“[ÑMnDyrûC¨tCY<þçb Žäù%Á!… nàæLÙÐ’¡a^6Èœ)°rÄæeƒt†fr òÚn ì+üu˜`]XÛ ØÚS@]<•ÇÕvûJ‹7:E?ðÉ €h½¼<‰EÒ^PrC/à © šà,ÒÒÛhrøä@ƒ4¹a¤7PiÆIY‚MnŸÜˆæ«y1+SÂÉM!³B§0”áŸàÐö™"'·?ÈÉíþäörûƒ™Ü@ûLAG„“Üþ ’äІ?°&7È>SHrûƒžÜþ šä@ôšU -¹yc¯Pa ﺒYºýùƒ³tûƒžÜþÀ’Û’J·?XN@"µtmkîûƒµtûóµtûƒœÜþ žä@ƒ4¹ÝòŒÄÖcàDOqÐâ:N‚?Áá©LIHn‹ÈNnú4LnÅø’Û *Ý0sÆ&A´ 1° ‹°«A°[2µ˜ ü½“åC?¼x`ƒýßâÖæ5Üû},±àÂÍvô¨UPgЇ© „›µ ±¢_ pGòÑ$Ü@ކ‘zŽ0 7ˆ0ņô 7J˜n ÜÒ}“MФ øðÖî0•¶á›fô“ïþªNÆ­S_Ñ«TÐ$µ ;ü·SfîÖ@ °F3@% `Y…˜’†HXË(ùè]›–?¬¨Böå*Ž|ùæ¶oú¢ïàŠ[pÅßà"Ú0¹ÛðFˆ«ÍïLÑ=¥ìLIRø#¤¹!껃N7¬EÕw´·j!f¢²@šnîÛ ßFˆ!m ¯ÜàAÒHn"¼tD É o„ˆ·å§›Š4-Y=¦§¢JrûSQñ‡Éíë,M8Nh'•ôuБܠ•)xE°xƒ”n8“ôHhrPéf ,ÝPޤ'7ðñnЮ¬2ý#q z¾ÛÐa© 3B€Éí¸2ŠÀ“ÀJ7ði©h¥8¹ÎJE$7Ø‘4à®8¹A¼ ªÊ €¨Tºý¡Ir{ûW‚ãÄŸàÈLnàÒ˜äk»ý¸…#¹!÷L1“´í®Lóà§ BwÑÿAé™bV¦ äVNpx’¸í6¸’@Q«2¥QrûìŽ3ÁY·oŸàp%·?ø“ÛôÊô¬2ý©Lñ$·?x“®Ê´Q™*a«La¥je «L!Éíreúg°$7€"sÎ4‡Jnþ V¦ 9¬Õ gó‚‡yÁç»IФ? än sqáÄBNnž·Àþ½†Û`@JŠ|Ðýè[ ®øh^Ðy[ˆå96 åG ä†««` ï* ·Ý zZ*¤«d7BŽÜB´Ýþ@»  ·@•éhe ýð®ÂÐ[ Ú<Ì ’냴ݠ'óº .¨«>o«`°vˆÌ9ÓLHzÍÐ3­øOnÀs¦Ð)zЊ·MÜÀ³ Àäö‡ïÏŽ€¥(µ­[÷‡Øäæ­‰4Ñ·a 4”„ô6$fÀ¥ÛŸa;«@¬ù.Ýþ •n°!–I,È[@DrÏÑ›Ü8ÁUj “ØBÃF“ÛàKnDYrƒ”nX“| ¼ ^º‰@NÜúCtÛ ’Ü891’Ä64“Ûlhe:L“@Ñ0¹á¬L¹H­LAÉ-¹LmC4¹ ï)z€¢¤íö\™þYi§"·Ýþ@» àž°2ý­Lÿì€öHé*`Kn„ÛhrŒÉ €è=«.Ýþ0‚-¹“ØF“Û`Ln4“q©m4¹ Âä@tŸ3…V¦ä'7"Îäwƒ'7ø5 ä‘ÄLn q·?£Éb@ƒyŠ[r‹$6±á.ÝÀË+ÿL…¯/wƒ•n +Øþ`-ÝþŒ&7Ê@ ¹äIlj#2¹¡–nÿ°W¦£Ér@C/¹ý'.±LnàÿþÀ/)úOn g„€öЃ’èºæÑÊ”J €†^r‹|ü˜˜Ä†'¹AÛnàKŠ Éí¼t‚«°C ×çþ±ý3šÜ¨h¨%·7 äöŸ˜ÔF°2EJn+Shé:‘|98°x-ݨhH&7Œ"aa”%7¤Ò Úvƒ'7pé6šÜ¨h&·ÈÇh+’ÂÂÈMnÀ’ qÁ$"¹ýMn44“ÛÉ þãMm„ÇÝ@iÂ…u`ãn°¶Ûpe @<šÜ(4(K·ÿ‘D%7p†ìUtÉ €cr &8"“[°gÏžÑä6È’@ ¾ä*Þ~Gþ'˜Ü%·]@0šÜWr A˜Ü#ÜÿH‚¥›þä¶ F“Û`Jn4(“ÛÈ¡[o±%7Dz{ƒ7¹íƒÑä6˜’@ ÎäöÚõÄZº)™Ü¶AÀhrDÉ €irÛ¼’Þ"±V¦ D%·ÍP0šÜOr J (£6 …0  3¹©¨•Üà&bInlÀäÆFlrccƒ&766’èÖ*'7ðA÷d%7¶A’܈ÒäVNmº…0  eŠþ (ÁyB 8üÉ a&Frc›vš ˜Ü؈,Ý`Éífrcƒ'76ÔäÆfˆ=¹±a&76xrc› ¹5vãúÉãd'7`zÉ €(Mn•ÔÀ$Y®[Yù–Þ"ÿÿGYïöFX¾©NnS£%76PeÊÆÆFlé«LÙðT¦l¨¥ŽÊ” ³tcƒ—nl®ÏeëêÉ sçnƒ0 EÑ†‚² # Q¦ ¡AÊa)Äìî½v TPðd?d¹:²,ÙÒù·þ·±|vïó*úîùiº ¸Íê#n‹}ßqÃw·ùtƒ5ÂMð7¸Â „›f‚[t/Š›“R|¦ãg/:Å-Gu¢Ïµ5+Ø”â3UŒ£RÁÍÚOí.oŒ"Ö˜ÆÍ‚É(ÿfÜ Óh°b²&…[]›Ú=`«¢Êáö@&·ZªH:¦«Pp‡”Þ"ÿG"¯w{£@DÛ Éàß˜É ÞvƇ†›Ãpr&¶Åll³€É Xº±Y¨tCJnl‹Ì@É Zºï3e3fƒ”nl7:Ø ÷™‚îÄb]ŠÅºW z}.ìÆ?]6Hrƒ–nlÐ;±tPïÄ%7ð“ll--ðäº4tIøŠ")ЕX ;Øb!י沱¥°[(½“Û *Ý0w¯6ÂP†Ý±ŒÀXÁu3`ÙÃH„yÊ}õ¶×`@ÐP_rBÚäÉ-}xü‡Š£“Š¿zc%ܦ¬àž¹5ŸÜ€ðg Sø˜â¦œ`3n˜dn{à¶Á¹AÆ”›X 7mbA“-·YlÂmYÙ)þÄí@ ƒ)µAŠ5pR‹ Cp°‡Hn Õ ä&·™Ä'76Hm l»±AÚn ªÜvcC”nð䯯ÖHnàÛšaÉ T•bKnësÙ@wÑ#'·+l(É X›¶°áKn Ê4~ãJrËU¦lƒ$¹`îŽm„( wo‰4ŒD•9(<=m’± b‹l&÷?ÛHH”ÞáÓÝÙÍßÌtˬž ·òZðF­…¬·ÞëõÛÝçö»ä†6¸ÉÜ´mZv½Ì-n7¡—©‚›VO·X¦*ܨ5O50Ét‹eêž©>pãtM¬S‹ÞÉ\ü;“h£ŸûV<ÜH°)÷Lõp®9ך¹Ýf´4­ù\O7‚¦æÚ¥¤Ñ»´pkä#ä/sgl AªŸ‰†!± {0ÿÛô4i"¥?9>„tàVª’Ö‰–/êö^·~ßþâ†Ä ¸¿¸!La±Ó]aøÙ­“)L2…P…#T»2ŸKÜlwãtÌL}¼QÔÄŠ[&muÃ%U™¢ßíÊzî@UP`lÑãDª‚ŠÄM¦@Ü|¸7Ûݨ Žd áö AÒU@:½ ^©ÂkTÔDLnÁÄ,@úƒ««ÀF‡Y6Î*°a „ ·bp‚Ã5Â6XfˆÒq7ª€|ExX$J÷.o»Jnþ ™ý›¾É ˜Úh—ÜØbMn±x’Û ™Ä A4Ì Jlàõ¹È½h‚Ê‚RÛŸ?D&·?(&ÿÆ:B»äÆFÃ9S`íˆ9ÌË©Mq$7¶Á3g @ƒj T£B\$¢³mÁAT—Üþ ™û{tŠ~$7€\Sôà&\$¬Ãí£B«Ø? Ä$·?è¦þMnƒ%¹ÅÉíÿfªp ì)€{ °¾)´Ë”&"¹ýA7šÚF“Û HnDyrû¿ºÜe¿…A:ð9`·`rûƒa,µ&·A܈ ÉíÿNê‚?Ð>j´XƒŒ‰@kTüÉí¦iðÔ6šÜAr j$·ÿ[© }TP…Š4ô›Ö&7'É ‹QˆÔ6  곋ʶCœâ`£noß¾ “›¶äöӘߣ©mp€¢Rrû¿þüù³  òH"AclˆYã(½…>ŽÄ’ܰY6šÚ ª™´?0¹íGTɨ5©A(PìEKnXLMlƒõ’ÛÿßÀrPyØn% S`Àµ(lž1_Òô5¹a3a4µ B@TLnÿ)ä ò°œjÀ‡8™f@ÌÓƒj×?·oƒT %7lfŒ&¶A ˆÊÉí÷>8òö8Õ€“ˆwR!“óиÛp5Ð䆩û÷hb¤ €¨œÜ€Uê^(òö¸Ô€Ä¡r 5*hTˆn‡¡(ŠcjMlƒÕ“¨·€¼Ý„.5 q¸|â˜Úš8šÖ5 Z$7`‚;{ö,w ÀãY$á#nFF‘< ÓŠ‡Ô¨aa·ÃΣ‰m€¢Mr&8P?U`IJ à\¤ä¦Œ àòP‚û¦Œüþ=šØ= š$7X2úý[-M!óð%7eÔäJpaa£ImÈ€¢rrCP1YYY$ꘒ8À”`“ÃF“ÚÐDãä)ã~ÿ–…'7”T†+¹Aq)m4­ @4Inˆª¹~ýý[,«ˆ¨<˜(â¿GSÚPD«®–äí? '#ÜÉ »$rBMiC]“¢„$É [Zü F£m¨€€äç€ »ßh!„!9[Cí“Û„FÚCÕ–ÆP%GÁpDãäöcT¹7ñ#EýA«tG#hx€¢urûœ¾ÐSÖä†Ë¼Q0 @Ñ<¹ýÿƒ^b¡rÑÀÍCÃhŒú€Mn£€Ž €F“Û( # Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 èh4¹:€Mn£€Ž €F“Û( # Ñä6 è –öïNôÛ_oIEND®B`‚procmail-lib-2009.1202/doc/article/pic/spf-system.jpg000066400000000000000000001606661130547513300222030ustar00rootroot00000000000000ÿØÿàJFIFHHÿþSoftware: Microsoft OfficeÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀÐ"ÿÄÿÄa  !1"AQ#2aB‘$3Rbq’ÑÒ4CSUVru‚“”•¡±²³Á%567TtÓÔð8DWs¥á'„´ÂEFceƒ¢¤ñÿÄÿÄ5!1Q2AaÑRq‘¡Ááð"3Bb±ñSÿÝ(ÿÚ ?÷úR” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R”ÿÐ÷úR” R” R” R” R” R” R” R” R” R” R¹Ï#Co,© “º!eŠ2¡œ÷G"ϧ’ÌŠ”¯?µúWµ½ê‰újߥº²ðr2Û˜`^ ò,fâìi·£ÉtNÆöœœ¸ŒsÞE‹¾ÉpÙhlB4@$®ËËÓZ]±$h V/£>’,ºéݱLÊÚDü%¼¸Ž$‰‰:ßp–>žr]èÖÒJRJRJV?ô…kœ¼¿‹§ð¹\ŽŒ¢/m; ¾¶B<’§=|t>GЂCaJÍáºßÔw{|2ÝÝÏŠEöˆÌî1qÚ^$81yh >º§°úQ·Éu-çNÚôÇPµšžÙÒÚ2ª í¦ytA;±æƒyJÉÁôA-c’Â_Ü8KUÈ¢;¦#dG,lèÄmA‡–lø¨yï¤Ë^œê<%ÿOgÕô½«'D€ÇrKð_»¡²G†Ñ nƒqJÍÏÕkyg~‹ê‘¡vµ›±o­Á, ? ¸Ää¡Ìá¬r–ë"Á{oÄk ‚º†è‘½™ ™JRJRJW9§†ÙÏ,q!u@ÎÁAf`ª<üKø’JR” R” R” V_®ºÚß¡pg%q޾½Þ­´D¢Ÿ@d“îÆ¥Š®ÎÉåà\`²]ôö3-Ùìûu¤W=®\¸s@Üw¡½o[Р°¥)@¥aúŸé&ß§:·Ó¿T_Oq‘»†Ü\º Pìrq—’kÞÑ`F«q@¥)@¥)@¥sŽxfy’)cw…øJªÀ”n!´ß#Å”èü?é@¥)@¥)@¥)@¥)@¥)@¥)@¥+œsÃ3Ì‘K¼/ÂUV£q ¦ù,§GàAøÐt¥*;Ô°á¯ñ˜¸íäºÊe^D³·ROäÌî|*(Öô¼ûªÞ””¬Oõ½ÆK«oº[/‚Ÿ–µ‰®T¬¢h'€2¨‘$Ò“²ÇÇ; ‚£aAÿÑ÷úR” R” R” R³}7Ô™,Þg;e{Ó×xÈ1׫k™‹q½^N9¦ÑF´€ø-÷ÇŸ˜i)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JPxž?-ÃÂgª®2™ K,—S,J[…±Ð,@Þ:ü zgåßGÿex?òŒ?ί?éïý¨z³û•ú¶µì?ÿú¼Èudÿel"êü¦gÛ®:[Sk´Žî{ÿg[ÉW|–³`ê Ì•RÄè ¯;ú†úçèO©àÅ™BK‹¤µ1ÉÁ„¦Ú0šmŽ'–¼ìjµAy(fú< Ë$9 EÄÖ÷–ó®ŒÒ3‚W{Þ+ä(ÃáAqÓ½|ÝYÓYÌ>O®±ÏÙ¸Ä^\,%¼´HäªYWe!|‘Ïèû¯o:ÿ§²h0ÐYö%6ðD÷¥û² yà¾ò€Ç×Ǻ>”ÆÍyôùÖAFøømâ°2)$4Ü!, ¢S¶C ì¾<ÕXºÿ‹o¦ÜËMo?ÕIh×vñ[§35ÒE}nBÝÐIÙš1¯#A´éµÉu'Rç°×Øñ¯†uŽgö¶ÈÌ[E1/¸UK$x+ wâã˜É_õVÆlu¤vv#ö¨¯Ù¤ 8Ct{lŒHb0cË•õ­çÑ—\à:âöã»WvY÷]G<ö…¶ýµpUPBÛª“¶;õŽ–±¸°éËHïcí_MÎêî0Àˆç™ÚYUHߺØ'ÀO© Üg×}=“Ä÷»>Ýi-·w.Я-lo[Þ¶+ÇúG¬o>‰à²èÞ¹Æ{ŠwÚÏ-nÆXå^e´UA'Éo#L&Ðo•zçRä¦Ãt®_)n±´öVS\F²T²!`ˆ:ØùŠçau‡ëN—¶¼öx/q—ñ$½›„IÔ.¾W’°ÑtËøPGÁãqoœÊuF&ò ˜s@’<wÞâsƒàªèk]¿‰&¼ÿ§¿ö¡êÏîTêÚÔ£;_¨>˜z»§0wÉÓ6ñ {|û±Ãp{~ï/ƒ ÊšÞÈÞÙMŽxüN73ÿ žª·Êcí/ \dn±ÝB²¨nÃ`0#z$oñ4>œ¯-?Oôî{WU.@K´uïZ€›;`yG¾Q¾Î†£,Hâ+§Ó4ðÚõ×ѵÅıÃY6y$‘‚ª(–Ü’Iðw^©ŒÁaðߪqV6íw=’Ý"ç­ë|@Þ¶}~f¼¿éþ°þŒº§ý­½ãòû§î3ØŒ>3)c’ºÈË"ir²v‘"y ž;ª«¢Fù7ÄÖ‚ÂÆß޶°³·kkC r'Š(FÏ“ ­G¾ÃYä2x¼ŒÉû++Ëo cœm)$o‰ ²¶U~UaAŸê>§ú–󌴳öܾVVŽÒÙ¥í!T¤w“GŠªùð ç\ñ}K}’ÊfqO„’Îÿo š¸›Q\<ÍpuRL[ïñß’ )R*馱}]‘ÁâeÉOŠÎ¯zë}û†3‘xòRÌAVò;dìCUýßõ^'­ozC«Í¥õâc#»·ÊDÀ¼#ÍÄ3€ÎäÓÌûÁ °é¤œ–{éÿ¤nún; ñé#ÜL׬ûU!AE1)`ÅЂuîüÒ&s)'\Í‚\DÂHî¤È{g¼¡Ëª¯k‡Þ-þv¸ïd-yÿÒ‡äZ`>’í-;‘ÚÊ-r‰{&6š÷¸³'&mo´=7^Ò?²±×y“ÿï‹·½M}Ö‡K ¨å q1Ï&oî€ÏÉô•pÝ/ꫜž÷pZÏ ÀïNñ2´E~ÎAm—r)­ë/ô¹‘êºû¢,Q,N2L¬3ZÅÝ`óNŽƒr·Á~ÓˆãËՉ߀)%é\¿OtÔý_ôy™Žç¥®íÞòç~Dˆ!!L‘°%‘È ÊÞUÀB¡˜úÙý!dþ»ê¡ì·g³í×qÜö¹ráÍ훎ô7­ëz±}›|'NI”ÌÚpš=¶°f¹.ìá#HýÅ,ÌY@Ú-롺£Ïõž_¥±m›Ìtäk‡Gf¶¿]B­á DQPžET…‘´[`°ª?¦É“òJË –°d­ð¹»kŒ…«HºàûŽþ÷v1­µQÿ(~†ÿ%þ½ú·§8ö»žÅìVþ×ËzáÚÖùoÇî~;ãïP^uïÒ…Dâío#Ç]åâ+ÛÍãjÁ¼Ï¢»*€PÄ…ó A¨yÏ¥¤Àdqó^ôõô}5y+B¹£"² ër-XYvU[^sO ËôGW°âöÜ5”l¬¶ç±/Ù‚¾_M+ Ó{û׎}µµ¸–idðŠÀÄ6|—Ëz!ý/ÿÖÑ÷Tÿµ·­'W}'ÚtŸRã0o‡É\K{qFà@ëV 7l…&g^Hx ?{[ߊÍý/ÿÖÑ÷Tÿµ·§ÒÿýaýÿuOû[z L·ÒÅßO_ãæÎôvKÓ÷ΫFyQ¤hÚBœŠI÷KrÐb ­k:©þ¥¼Åã-,ý·/••£´¶i{HUiäÑ⪾|ÇÀùÖoéºn¾Œ/mÌQÍy-źXÆT41•F£¥Êó_:åðÝUæú2Ï7ÓÝÓYéðÝMiX]Äá»RB‰SAÇ&òq;²ÀèÁ¸ÁõÆS9”Ä]â'ÇÜc¢äi2Ldîyˆ½Ùøc¢vAU*EZeNIqw£ä8jvì±rù±PN‡®‡®µ±½7ú;¿ê¼OZÞô‡W›KëÄÆGwo”‰y F›ˆgÈ/¦™÷ƒ^©Aã@™,ÖK“»ž Ià»ÌO=ÝÛ\—ºÑÆÇŒB>$¯Î_SãÀÞñú¦ó!œºÆtÞ2 ŠØí/o..ÌE7±VXܼ€X¥ð ÙÕ`ÿàï<6ßG7Ï<±Ä‡0ÈØ(,Ѫ<üKø’tú ¼¸±‹¨úc6'‹¨mò yr—. È$TÁÙ/åv[ÐóC³ÊƒaÑÝxO‘Èᯱsáó¸Ý«äWðI£a¢ë®$·=õÑ ‚u“̶ÖòÎâB‘¡vÆÎÄ¿  –?€Ÿ…y}þ6l·ü$±—¶Á‡Ãîñ'¶ÏÞUC @r$ ÖÔ^©Aæxo¥Öêü½Ž+¤s3]ٺŠ6.QË Ë{ÑñòÌNü) aÒIKÊf0Ù|-Þ5‹Fš[/zà¼C[d(»c¶A”©mfþˆ?ëé;ûª?ÚÜWKüS^ÿÂg¶ŽH¬1œòsEÇìÒdNáýÙSóÄè6EÓ3f®3¶xn’É\ä1¨²Gc,‹ò :˜ºèð(ÚP »1a¥u¨µëI®±xV?’‡1•I cgCƒ·áÞg#܈1_{EˆuÒxÖ/èƒþ°þ“¿º£ý­ÅGúG¿ÃôïÒþ-Õ8x/°WØ£b$š$˜C"Ì]¤íIâÐÞœëdq!¸nµ¸ÅuF3Ô˜¸,$Êò7V×Âx]ÔHåÖ6Vò€i[‘pÞê}’ƒé6Œ¹ÁÚB÷ ß¶ºlƒ< •U„éø«ž,TmååI†oþŽ-ó˜k.žÃôæO/wv¢ÇEnL žûÌΣÝà °yˆ|Héô½asOÙõf,Iõ·N\ ¸x+·8˜…•+p®™îQ‡€I ÿÒõþ¦Îe0óâ!Åâ ÈÉ‘»ö]Kyìý³Á¤å÷j7'ãàh1>Cyq˜¼Åa1^ÙqcÃÚ§»˜ÛÛ#2ò‡ìÒq(Ú Ä`t >–ÉCÕ·òu<+ ³[tµÇ‡îºG,ϰtIn÷¸µ»hí˜3éëþÅ}"õoNõ®äùYï­¯òC"äÓ¬eØî˜lèò é´=3×är™œ6FÆK Æ—6ÑÈ.‘•xxŽr< Õu³Yü7Òëu þ^ÇÒ9™®ìÝb† (å„å½Èhøùf'~@´ékþ¸êÛÛ.‘ÃâŠÚZy“ÇÅ "³°)d}…f${«À²t2ÿDõ‡ôýÕín(4+ôsÖý?•œdvI~ÌÖ'q.I Y•6GºÛ]µ*tjËýd³Y,Nîx-'‚ï1<÷wmpR^ëG1øN¿9}O}>ˆ?ëé;ûª?ÚÜW?ø;Ï ·ÑÍóÏ,q!Ì2v 4pª?Ä>$Aì•áyÙóÇþ½1$¸Üjä1ÄP.AÚ&^7ZNÈ*~÷€‡ÐyóãÝ+Çú‡ÿj“þåIþ­Õó/Õ`±v‚òÂ9ó×®ÑY⬮ ¦âAòvEÒÓ;•ý|nŸ-ôƒ}Ò¹œ}¯Tà#´ÇߺÃNÎû¿r–Œ¥Ò>.ØŸ>€tÚÍõõåÆé·£ºƒ$'^žHšÐN\važA*±mÃFI:Ú¡Öøèh>š¾Óè·%g¿uw-¼Я—šC:ˆ¾¬Úèyðhmô¯Žèœå†2ï|ëq* o&Žã?}•´L¬€©*£^ö¹â¬0½g‘¼Îe¬3-}‚µ±ˆÜ%ýÔŠÐ|ï®±³a³?CX»†§²¸ŠÞFŒ’¥‘­T‘°¶>B½“;kg}ÓÙ;<dzØÏi,Ws Û†nGÀÐ$ìø÷úG¼“§.ºªÃ§ý¯¦ ”…¸[¢.f…\$“$²ƒÌéÝN“Ư0½ge˜é©º‰¬îì±1Û›‘s;Dáã‹"‘È+ÄíHØ yÿKXu$?D×})i„’úÞñ'ƒ”à iq²³È¦C"HïÄ!: ¾»53ªz:ãÿK¾¶ý‘qgh“LCmfY¦*H_t{äxÞ€M¢û«3¶x9:€ô¿ TQ ‰bžôG|c‚òn&]4tÞè§ê¦,^¥ñ¹»L]öF<”K$W„(Ió“J² ?¸¼ˆ(AÐѪ¼Qýæzir×X®˜ÆÊˆMÅͬXÙFÈUã¹Ȩóé v£?ô½smyô#€»±ÄG‰³¸É¤ÖÖh‰’vFÒ{ ²äBÄHÝ¢Xý ^]õv§¥2£qhní31!™%NÁdE%9ÜT’çh Ú:é¸Êgm Å]Ø&)âCíd,¬ÍÌ0hÇÜ*ÈF¶G¥m+Çþˆ?ëé;ûª?ÚÜPo¨²YK‹´Àa㸂Îáí¥¹È\µ¬rȇL!Ôr3…`ÊX…éo:ÓÝ}Ía²÷·QIŽŸïRÚWYÝ£]¹ ,›hràt+Êþ‹¯úßqÓa‡ÁÙgqRË×( a>¤mý« rRxñÙØ‚Føï1¹>¹ÀõŒ¸œ ¢ôí»Á{uŽ8…ñXÝ¥D ĪÀ$\ñ:!2.¼Èœf')?LN–‹»xlåŽåd1Ç4RK€ÙíYX.6x±RF÷üÿ…ê_¢ŒdYÌ.f¢è”–ÚÂé•‚¡´l‡EF™‘„‘ënC Wô”¥”¥”¥”¥”¥”¥”¥”¥”¥¹Ï ÜÛË™H…Ç##F¼2Tþ ‚>Ò”¸~Š::Û(rc®âÈg7i“ºYK6ùbMìììïÎÍi38[,þ9ì2+;ھä72CÌAV1²–R ÚŸåV Ëô÷ÑçLt¥áºÁØÏe#}ð—Ó”“@É •mr:Ø:ÞÇšé?AtÜÙ™s a%¦Bd)-Å…ÔÖ -Èòí:ò%¼’vN†ýi)AбÁâíñ˜Ëhí¬íÓ„Q'¢ô’NÉ'É$“²kžC‹ÊÞX]ߨAsq”Ík$‰³ë[æ?ª}TaJ üÆÔii—°‚öÝ%I–9“§`ÿ¤˜$‚A°¥(#ߨÛäñ×6‘÷-n¢xfNDrF0Øò6 ôª1Ð]7 ÃÏea&5äEI.êk%p¤‘Éat G#äù­%(*ñ½9ˆÃa›‹±ŽÆÍ«-©11÷Bò.¤7=ïï—€wºÏÃôQÑÖÙC”ƒw@»9»LÒÊY·Èóoggg~vkiJcó?EÝ!Ô9¿Ëãg½ºmŽs_Ü ’x¨îiWdéF€ß[ PG±²‹g¬/;ƛўw™ÎÉ>]Écëñ>==*E)AW•éÌFnâÞã#cÄöÈëo#eId í_h¤8Ó.¼³LGOc0Ow-„ îÝ^âyç’ye*¼W”’31 ½:õ5iJ;ËuKý&tÄø<5ôy3yq 2Àã–8„ˆÒM¦¨EÛaÀ¸U÷‰à}¡Ùâq¸û‹«‹,}¥´÷oÎæHaTi›díÈc¶'gæ~u2ƒ.>ŽúUlá²LWnÆ.ÙÇq*A)B ´±á+mWlá‰ÐÙ:©KÑø°·‚ ö6;ÄËÄK²24tÊAÑñ±½«ÊPWØàñxìxK[#Æ$FjS’;äòÞÎ÷½ì“½Ö~Çè³¢q¹Èó6˜"¾ŽS4l$¢9ÙÚÆ[€Ñ;¡[ Pgú“¢°=]ÛËYîãEaöÉ£Œ½7p¼½â9kz:Þª>[è÷§3ÖpZe ¾½·ƒÌqÏ”ºq½±äw'¼ÞûGg^7 j)A—Ë}ôæzÎ L´×¶ðyŽ9ò—N7¶<Žä÷›ßaÈìëÆô­”Xû8íayÞ4ÞŒó¼ÎvIòîK_‰ñééR)AOÔ=/‰ê«1g˜†yíG¬)w,HþA÷•ÑPG-ë᪇7AôõÏMžÚî\Hualù †ˆWe÷Àhi7Ä·æ´” §³él5ž ៴cì·²½Òºâ J[J8®”xØW€ú4èþ—Ê.O…Ž ÅB‹+M$¥õã͈^6<è‘èMk)A›ÍtOuR–RÚî{¸<2 aÇÌj®uNÔ ‘¿Zó¿¥ûvë/£ cïÚœ…’ጽÄî[‚¾ËìzòÞþ;¯hª{î“é¼ä——ý?Š»º“\æžÊ9´b6t¢‚<=#o-¬÷·VÛ6:ï²ISÉÎÁj¾ðÑñëS2½9ˆÍÜ[Üdlc¸žÙmäbCCÌ©,„«í‡eׂ6jÂ!µ·ŠÞÞ(á‚$ q¨UE@<WJ ¼GOc0Ow-„ îÝ^âyç’ye*¼W”’31 ½:õ5iJPÿÓõ|?Ñ×Hà3šÅá ¶¿nz‘YÈN_{‚’U>#Ý@<TŒŸDôî_1^çÛÉž7¶“Im1Ú…;x™Y½Ñ¯$èlSZ PWáð˜ì ›Úãmû1É+Ï!giYí݉gcóbO€=« W9à†êÞ[{ˆ£š P¤‘È¡•ÔAðA5AâFx[,¿ÒÒIºYÖH²¤$¶×2[È Ë>לl­ÄéI]è•RFÀ׬cz[ ‡³»¶ÇÙû?¶r73¤¯ß˜±bY¦ßq›nÚbÛðE,zO¦ñ—‘ÞXtþ*Òê=ðš (ãuØ é€ØØ$~š¸ Íáz§º{)6KmwÜî^w9 ‡±åæEg!ϼÇl‰ß­Zfpx¾¡Ç=†^ ÛVÙá2o‰ ŽJ}U´N˜hø5aJ ßMtKô…Ä÷,Lv³Î$Èò7w ]‰z$ oC~‚´Á Õ¼¶÷G4¡I#‘C+© ƒà‚žéì¤Ù,]µÜs¹yÜä.NÇ—™œ‡>ó°:'~µÏôuÒ8 ãæ±xH-¯Ûž¤Vr—ÞकOˆ÷@Ð$U¨¥±s}tuÎPe'Ç]Ë®.ß'tÒ†]q<Ì›ØÐÑß ÚR‚¯%Ó˜ŒÎq9Kï¬ÕªÝ+t¯ ìKsÑ>þùy'{¨x¾ŠÀâ/-.­mgi¬¢hm Íä×ÙˆÖG`› º• ¥o5Ð}=Ô9HrYKk¹îàpð8È\ ‡1ª¸}Õ;P6FýiÖ7ëÓŸGÙ[¤±“ –¶L‹o*µÇpkÚò;tÛ’wÄ1;­%(I«É>›úÇëÉüW·w{þÓìQ÷;›åÏ–·Ë~w뺸 ÅÍôKÐsåEújÐN_‚3¤[]kì•‚kÇ‘ÇGÎ÷³VIÑX®íŒå¬÷qÇ¢°ûdÑÆÞ›‚8^^ñµ½oU ¥8qA‹8ä’ìÀQ“›ÝÊòé·¿µf/¿>-Ö…Sáz§º{)6KmwÜî^w9 ‡±åæEg!ϼÇl‰ß­i)A—꣮‘ê«Áy˜ÂA=Ðõ™âwð¼ÈAmrÞ¾«HzsmÓG§`±Ž,I·kcl„¨1°!†ÁÞÎÎÛ{$“½ù«JPgÓ¢zv;Ë[ˆñüÒQ=µ²Í ¶†@rí+y'aw²[×Íh)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)JÿÔ÷úR” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R”ÿÕ÷úR” R¡ä²ØÜ5ºÜe2–03„Y.¦X”¶‰Ð,@Þ:ü ÊVòï£ÿ²¼ùFçWH:Ó¥n®"··ê\4ÓÊá#Ž;ø™‰ÐÙ$øÕå)J)Qï¯ìñ–r^_ÝÁik¹Í<‚4]Øø$ÓA"•Ÿü»èÿì¯þQ‡ùÔü»èÿì¯þQ‡ùÔ T{û<œw–p]ÚɾA ‘Dƒ¦ˆ#ôTŠ)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)UùŒ²aìÒcm=ÔÒÊÁkmÄË3±ôPÌ£ÀäÇdiU‰ð …Sßu_Oã¯$²ºÍXÇ|šÌN­9$ª±]˜‚4 v4ê?äëå>Û¨.ç¸gòl ¸hí#Ö2«ÄΤh7wm*+W6xË8ìì- ´µ|!‚1.É'J< ’Oé §üªöù·œ¾ãûgì?dáòþ‰1rߟ»ËZó­¿(rŸØfsü5—þb´ ÿÖõÿlëëü³7þVžÙÖÖ,ùfoü­LÀæ†zÂKµ°»² q-¹ŽèÇÈ´nQÈàì4Y}4ŸM2âúÞÒ{Hg“„—r˜`IæáBt=Õ:Þ΀$LÆf†Wù(,.ÕÑçŒÚ9ŒK܉Ú6M‡)¾H@<µéäU¥?'ôƒkeÚ[l.rã¹°×cg¶¶¶ôÓÏ,¨¼#ó²À7¤‘é¶3+”ênëcº›§5Оbût–àì&2*ò:$‡@ø!€;ØRƒ?ù9~þìý[œ–áãÕ¬|×â9Gºì|U•‡¨ ù§än/þÕœÿ.ÞÿãV‚”ÿÈÜ_ý«9þ]½ÿƧäœP{ØìÎrÊcàÉõƒÝm~\n{¨<ëÈPÞ5½‚”ÿÉì§ögœÿeÿ—¨ö¶=]ß\žn RVœmŠ$Ò(ðŒ¯2'‘ -p%”òA¨¥ò77œƒ_dùy–;ûéf†fù´»>¾@N¸¡©˜ÞšÀá®ã„ÆØÎÈQ¤µµH˜®ÁÑ*ÖÀ:üXC#J…ž!!Ùx¹RH @ot‘¢ÇÇDl°:P+œðCuo-½ÄQͨRHäPÊêFˆ ø ª»þ K,´Xè±÷׳ɜڢ°¶Id1£¿&©*ûâˆBH[¸ ÏþBtö)ƒÿ'CüÚ¯Æt®b.ì²g¯±½ÍjÞÒñï¸ë~²Ý‡ßÏÜHõ²=6W”Í ]þ*ÐØ]ÜÁ·I!1ñ‰‚%ù:qGot¸G©„?Ȭ ž/-gÈÇê!ÉÞM{ŸÝ™ÙCzŽ@oDèš‘cÒ}7Œ¼ŽòçñV—Qï„ÐYG®ÁLÆÁ#ôÔ|é(¥()ïºO¦òw’^_ôþ*îêMsš{(ävÐmˆÙÐ~Šù!e½Ž¾Êã¤_{=ü#÷)…¡ ¯xiGÝ€F‚”q¾k“Iš<­œiîµµ©K¥€Û(b²ž$±àí4¨Å‚¬x:û¥æ·ŠâL´vPLà“#Ù¬êF÷™TH4A%w­úé)A–ÆæmÚã´¾\£Ik2Ê¡´‰RFôA×â*eUäºo —¸[«ü]¤÷h#ºh€ž #„ƒßB $ ƒähÔ?¨¯ñiƒÊNÊ<µžNi.cüu+“,ltù2(Ùí±; ÐR«ñ9?¬¢%‡±yi/³Ý@˜ŽN*þëhrR®ŒÓ …m¨° R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” ÿ×÷úR”y,ä6 g­Ýýû uµ´Œ3ÙòÌÄ$`é´]—— ²5Pû=Y}ûmÖ+÷;xÞòM|]%~Ú«yð'ž@ñ/ì/­32g1¢;‡’Þ8.¬tÓ$m#/iùö¯÷ ¥ËW?Êû(=ÜŽW"ù—Ú,$háºyã ]y-ÏJ>ñù3u/¹{ÕË«s÷áç¿/—ÚAH<èû¬7­‚Aæz2Î+ü}ý¥æH\Y\w]ä..£`Q£pRI£¾˜hƒ£ämZeVtÞNò;; Å]ÝI¾Á{ŽÚ(;:ŸÑW R” R³é™½H`œ[µ™Æûll±°‘[¸‰<ˆ#ÔúQòóz(šóŽèÉ–%Óy¼Î9ºjrÍw“qô¶Ò[)ž~q¼¨²rð’8DâHʶƒ†Óm:Ÿ2n™½¨ï†O¹#Œ´1´2/1ÌC<û€€JŠƒgÔ¹iúc©o_ؽ³us l°¸ŽE…Cy^{ù{ÆÇ®¼ÝÙä/ïúJÓ!o Mº³ŽTOHÄŽ ììï€'gD­¥v*£<#/6¾éœÜø\¬kÒ·ÒI”‹-°KslÀI,ë-£°3 œ¤×*åÈrͤéL.A:¾÷5y…’˼—¦¾xdºnäÊÈ‹$.CD»"òŒéUÙw«ÎšË岸‹×¿³·ŽþÖêkQÛgHgd:䤂Bïk¿?tÿøéœõÎ[#š±¸{Y¾­¸XDöêcæuï32ñ`G-龆¢«Æ×ñã÷÷þ™e›¥g—ªonON]¥ÎtI8K˜•'´kS„¢ËåtI$R7 áÉ\¯¯Æô·T´mƒ3õ¨Æƒ&BÚ6÷lÄ&.öžNm8i@åÚ–Cö€©ÛYõ<—Ýw6“Øc±y»¬¤;Ê“v›^~è!‡Ô‘ãDÊ»êü’_¼÷r±FyÙ-åqÅX,…8©îb”ßá¸Õ.[ªÜÄTDåçw=’—¶QtÔ™å¸d·‘-Ò-$—p¤šY4’í«)_P›vJéÄf1ùÌÜ–mk~í Ò$yÝî¡6ÈÀ°šPS”L’ ÈÈ­L]w]i‡-c†+¹¤¸É¾6b-f‰.Ϲ¢ᣰ ±pJ£Õ˜ìŽþ×=uc5Õ¼·V·pEp™Rv„*ÆK–f½Æ 7Ú ×Ú&è–OÒX¦y$“gÞˆ€ó1…~+£]-úŸ¥p˜ë;{aõ}¬’¼[G–.Ü1Â’0<• ü‡ÛçÒ (žîîWg?´â.½ÀÓ¼1£¨F*üãdÓh³)Ђ¯§ºvêǵtþ»X©mr¿´®îoR}ï´ß ½é¸¶ýóêÒÙÌV;Ñ`²KqieŒnú#û"+Ž7ZÜÜK¼UXøíÞÔ{•èÕ8h庯4ÖÛ öO©`…b:ûVÊ…S‘ʤ T>žêC•‡=q,‘Ïo½h¢kkiöÄ1ÉÅ£Û9•K²®¸ƒâƒÏÏIee‰–Û¤.ì'‚Ë.–’¤öшä–~ý û9·¤;Ð#I!Vœ…ÄööW½|¹l®.F‚ÒöÜ ¥†)^ÎêHcHàwçÉP4ÊÁ#GQ#‰;£ÞUÒczïyƒÅän{ö­{h—RGìò¸¶VüéX&£aµ#ñV Ì"F~聆—æòöÐ{t19Žé,šyâ‰AæÀ¢³¬jí¼(ç¢}á°Ëõ_MM‘Èõ”t§µI‘ÂEimu«aÞœó¶pÃ\á;`?hñåS}#éyâÊ+Û`d†y/mnír2É=Œ Úiày9™y¹[Ž\9«™Éf<ÜEßWàì’ýç»%Š3ÎÉo+Ž*Ád)ÅOp#¦ø ƹÜõ~ãškl¬¤æ‘ËÙy’2=ÙtD :1•N.‡¤‡Ÿ§Gå“:YtíõŒ’E–1D·‘"Å3H%±ˆôU?ä'Gÿb˜?òt?ͧäœP{ØìÎrÊcàÉõƒÝm~\n{¨<ëÈPÞ5½ ꎢµþ‚êhå÷þµ°Žn?.ƒ¾;åËá­yØZcq8Ü5»[âñö–03—híaX”¶€Ù Þ€üL¬ÿ±õ‡õ÷þF›ÿ5Uù4úD¶í>:ó§/c3«XM€ hF å]Ÿ È7­ 6Eõ Ïå·å·EÛö?cöog;áË–ùóõåûßOßšêÃenÉÕ2Icr—–\l–Öð®‡ós–Ÿú°]ñZ n[™·kŒ^BÒúr%¬Ë*†Ð:%IÑ_ˆ«Ñ]Tgg¿C ý§HÞÛa3øöÊÛ»f&–fY°4£Rhwƽ<^^•Ú.žÌÛâP$qGIÂÏ\\ È7å­ûß…i©ZOI¹§ÆÆ`¸»»…†‰Ž{†™î%D²k¦÷ƒÞRƒ>m£»È\Á-¤2ÏqíP̶ ÞîûBÜý´›å* @U)îlHW[ŽŸÃä±—YkŒŽFÒíò q«{6€FÂ$ˆzGØ+†/]€/)A‡‡ ¯"ÁÇŠú渨°÷ÏìDmãî*¾Óìäã+‚ÍÌÄ…m:£¥æê+‹'Šþ;1J*[“pœÊ{ÐL®­ €¬?9X6™X V’”{Ÿ£´0uvW66Òe¢¹‹Ú5Z`.œ½É“[!*k€D„é<žzç7oš±[éþc£â%÷DÀù6±÷½Ð\{v Éž”É'Db:~µ¢ÏŽ{SíOb̲-»«Æ;bPA&4Ùäwïh C¸è+ÉÜ®`‰o›¶l‰ÍÄw·ûOyyÇÅÆ€xÙ—JO*´ÊuCm­ºvÒLÍô7— lÇ ™ZVeŒJz—-•%xì×OÊÈ ÷r8lå”ÇÈê÷ºÚüù[wPyß‚Á¼oZ ËÿžaqŽ‹=Ђխ/ìÖ8°î¢8îäH{F‡ /ÀPkq‹Ç=‹^K3Á%Åä©4Ï MgG:gm~×ãDhhy ³WþYbÿì¹Ïòïþ ?,±ö\çù ÷ÿƒAJÏþVE?»ŽÃg/fLW½®—çÊ紇μ-çzÐ$>¿ËÉîEÑùT‘¼+\\Z,j~ÊLÌæUXëÐâƒAUù<=¾Sµ#¼ö÷Po±um)ŽHÉÖü » J0db«ÉN…Wóë ¯s±ƒÆkÏ{½5÷/ÞöøÃ¯Ÿ.GÓ\Nö’É}ç¨/§Ì)òmgUKE'ÔTë½™ ñì‡ŠêŒÆCnéÓWwºpöȦ‚;9\{¦D-)—°Hä­À’„­° Ïlëëü³7þV´ Ïû7V]ûÒäqXèßÃCoj÷D= IÕK|Aht Ñ —䕽Ϝ®O+”oB..ŒQ²~áá„G©ó¾Hv‰#@h)AÎ!µ·ŠÞÞ(á‚$ q¨UE@<WJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRƒÿÑ÷úR” R” R” R” R” R” R” R” R” R” R” R” R” R” «ÉtÖ3p·L&6úu@‹%ÕªJÁvN`N¶I×âjÒ”ÿȼ"{¶É}eû¶ö+›XSçÆ(¤T]Ÿ'@l’O’iù/,î;¨ó–PŸ&>ú]m¾|®RW5à0_ÖÉ'AJ ÿäöSû3βÿËÓò{)ý™ç?ÀÙåëAJ ÿäœSûÙÎröaàIõƒÚé~\m»H|ïÉRÞu½ò3Þ%|¬ñŸ ÆbîXätyJºŸB¬#ÁV‚”ÿÈ~šÍž" tž†lak)~ä¼%X¯¡âN¶ÖÀ§Ô™›?8Î¥”{«NÙ.cDøS·+0ОFØÞùÈh)AŸçÖ¾çc“ßž÷zk?½íñ›>\‡®¸l¾´ê[o~ó¦ ž3à.3$²È̉’ãëä1;ׂ6F‚”ÿʧöœÿ eÿ˜§åSû Ά²ÿÌV‚”ÿ¯3sý·I_E1û¯wm#çÉ¢’W=4ç[ÐÙlëëü³7þV´ Ïý]Õ3ýÏQXÅ ûÏa‹1Ì>\ZYeAç×hÞ7­üÇ\{Ùiï²ìß¶-ýË42ü¹[¯üÿ[Ùe,r K¨å$Ä0ëeO‘QDðéJT…)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)T¹®¥³Ãî/ÛÅN´Äxñðõò?†¢f#ˆå{ÕpÛ¼Ëg¿È¥»”žkqqFÀë]Éž4sÈ! q*Cq:‘ëÞ§œ,±¸«O%M϶I>¼øeS oãàë5õª, ¹ÈÝK49 «šC+ÛÚ°0ó>¬#2©$³ r,IÙ5_ÚÎ/½í¸éuç·ìŽœ¿]Æã¿žŽ¾GÒ²ªæx' _Öp¡WÈáç$×~ìÀU•§Vçæà·9ŒE»ò?RÊè¿/"ëgõV+¿œþ·c¿Çßÿüçõ»þ>ÿø5X®¡êV·ýE&ž×%Ó¹†eß³ªKdÊ?t[œÇǧƒ×ÔkFWÖýEkýÒþÑËî}UÜ~|ûâ|5Ç—Çzñ¿#圛Ýíã­5ç¹Ü{þu¿‡gÓÓÎÅ®>÷«GØÇÔS KKTÐÇž÷s@xôãøïƯ9˜zÞ7)i–·i­BÊH’ÄñIh:8 §D ¡¦UJ[ lT‹ÛU‘¦,ïÜ’Fè »ÈÌîtÙ>P<Wµ¤Nc()JT…)J)J)J)J)J)J)J)J)J)J)JG¿öÏ«®~®ì{wiýŸÚ7Ûîhñç¯÷„\Ooo ’ÙÇìñÈ€Ò8rC#{ß-~.KÌÇKÅ4Y¨šiä2-õ¤#]¾é *8H>›8û.–ÌXXaûqb¤ºÁöb¶÷Ý äqÁ4 Ë/cñ9p\) 97=¯n’Ÿ1“»ÉKu›¸–,~VâϲðBX‘t»*€†Û°uãZó_Y¤\f*{èo,o kK¿cf˜Ão!A"•ä ïFYÆØL™ô»jmU³3”DåO“è\ÅôžÎ)ùãòÉÝ–wåoq|åýÁÛ;Tûœö¥•ØñâdZô^bò Ô9±Çô¾bµ™îÕ^éù4ŠeExôäŠÜ½à¨G›ËÌ[§µAo}>)"îÏ“ŠÃn=ŸÚ5'¸7S°„mÕwË`.ºÚ ${ì6VÞhe·I­øE,‘¤îcŽ]G#rRêËÅ >ÇÝÑæ•\>ªn¤‹!qe†Ž˜y]•}ÙJ€`{þ£wÇÞ­'Jcï1%‰Æ_ˆÕ•¤vÎ`º7 ª|€µãzó­š6ê©ïú‹§£µ‡%gmq{=¬ë4Q4S”‚c"^E^9b ꡽â½Å†ÒJáuyocšêdŠ1ñc­oCæ|z ÂfºÆâ÷pØs¶ƒÁç½HOðƒàË×ΪµU6_ª,qa‘\܃®Ò7§·5¯O_Oçù,µæZq-ܼ¸ï‚¥@O ïõð*+ «š’R”ª%eiÔ[áì4WÓ…Ð[×è«ëN¼œ>¯,ãt$y„•*>>÷þjÇÕ•®"IW»pݘǓ¿ ¡þZ*˜ügRã²³a2¤ÄG"y ïcc_Âjâ±:rP-´A-ôX1Þßj}¯ËÉÿï[:ÞŠ¦¨ÕY)JU”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥¸]^[ØÀfº™"Œ|Xëg[ÐùŸ‚«sYï«"•`µžyÕI؉»ià³|´~/…ygQu-Ì—½Ñ3Mq'#iq#6ÇCáàmމ´j•W k³i=Ò˜qÊöÑŸ½#k› z~÷ãäúzVR«?åÉ¿­ÖzþÞçŸû>:ý;ßÃ^]ŒçõÇþ ÿøÕ„ÌÏJΕYÃ9¿íëJì<<¿¿æúùýÓ¿O¡o”—ëÇÞÛÇË¡‘D‰WãáXz%xú[:¨ÂVt®ÖöÒÝH$'Ï“ðÂjæÞÊÞljpg¹ {ª7¯> |âj <[νٛµ¹lú‘þïá«h#U,ãG½4¤yaûߟ¯©ñü5Ô@ÒžW$7¨/Üý?3ÿ­TŠ þœ‰aÇ:©'íNÙŽÉ:I«z«Àÿ@¿ÿ4ÿ U¥uQÙ…JR•`¥)@¥)@¥)@¥)@¥+œóÃko-ÅıÃH^I$`ªŠÉ$ø; éJ«Æõ.3pÖø¼Þ6úuBí­ÒJÁvÈRN¶@ßâ*d7öw—6pÝÁ%Õ¯h…$âä6¼”y]#~´)T÷ÝYÓxËÉ,ïúƒiu¹Ã=ìqºì6¤ìlMXXßÙäìã¼°»‚îÖMðš ˆÚ$0ðtA¢‚E*++cœÅÛäñ—1ÜÙÜ'8¥OFé‚ADU_åßGÿex?òŒ?ΠÐR£ß_Ùã,伿»‚ÒÖ=sšyh» ±ð6H¦—×öxË9//îà´µ\æžA.Èl| ’é ‘Jcg“³ŽòÂî »Y7Âh$#htÃÁÑ~Š‘AÿÔ÷úR” R”ûþ”KìÜÙeËä­neµöOØí…‹{!IBAßï`úRmzrÒÂòÂk)%¶‚ÊÝíâ´Œ'h«X©bIU;å꿉ݽ+Y½rcц}zBÊ ùol®¯lî$šiùC"^ß3¦R=¡á± l/6"Óˆ¶ÆYöë¥æÜ˜’I$Ÿ™$Ÿ—Ÿ>•^®¨Ùªt1 ýJ&>Ã)ko—É)ÈÌÓË0h„‰#}öBhŸÓƼhù¯»–·Çf†NÞöéXÛÇo$ ±$R*/,ªƒÈõk^ƒKîÕí*Ó~äç3ÄÄ*0]?Û{7·WÙp×2ûGÛï0â«ëãǧóP›£â7W·c/’[›‹Ñ}£³»YDFÆ;z ÅîiÃøðÞõi)Y×\×;UqK>ýŽ‘®£’{ç²»ˆÇsf×,Rf1K»þØÍÚ|¿µÏÞ¨÷]·Iíì«ÝÉ-¼{«q!XÉhEÊÈÅþï"N‰+⵪ŒÛt|_ZZÝ×ÉA­ëßEd“•ù÷Ú2ä7v]Ž^9žF #™F´7Åè>?ÏUwÛÛNF{iW[n;Q¿Äx¬&™Ž+"Ò•úf  ’N€¨ü®ÖÖ³]¿—zõ'Àag‡Ú÷®Ï×.;Ñý?/ýzU„E¤EŽÑ{6믴#ɾè#üççñ á •½‹èqtW’®¾G×ðþú*h€»‰'`å[’(û©ãüçñ?殑D©X×@’O’~dükî‚v#þt‡ûïõMj+/ˆÿ!þûýSZŠèµÁR”­R” R” R” R” R” R” R” R” R” R” R” R” R” R•úþÏg%åýÜ–±ëœÓÈ#EÙm²@ý4¹I2‘äex!¶šÜkQò+!ð>'ǯùªªò{+¨¤‹3‡`Œ†9ZHD‘…?CàwúÍsËuWIß\½cŽ„/Æ œKËÀõóçÒ¦Z}`ëðämo­f ý·È(WÁØ>¾ž•œÍ[XÆŸ×ýSj­¬cNlÿä'I^ùÅbb›ã¸hy|‹„ oãéølÔ+£UM˜/o%w¦ÈÜ)'ä=ò?ÏZ¼ŒÀì.l†»,p|w¶_Öwó®pÛ_ù32éøð}JÈ.ý5¿ôRb0³tI…¸ÜÙ^Ü&¶cšæ[ˆöÊÌÊ~~GåV˜ž›¶²„‘m ¿.f( oI×§ ü|V®Y³Dâ[KiÃ)ó…xÿ/_Ñòªño%ÆžìkÄ*}Ñç~t}? ʸÀøÙÐEd¢8WkÝ#cûÑ¿>~>ž>5"t€;,ÚäìvÍü&ºÒ¨’¿ ¥˜€Ù'á\.oaµ9-!û± äíê|€UG[[‹Æ^žÜ`†[xÛÁøûçãç^wâ Œt ÔLÊH[¢}„lž®*§§‘cÇE ŠúUQ ‡S­oìï»þÇwÇbV‚nÌûr/ÞF×£ ƒäWU˜U"•_„Êýw‡ƒ#ìÖî_±¯áíLšb¾òìëzØü¬ž?ô—w™†ï3Ô˜l}œ/k,]™™nT1.åÓ!#Kµ'ç G› åWæs˜¾žÇ=þ^þ +UØç3둞*=Y´”lxÊá1Ù¿búÆß½ì7qÞÛûì¼&Mñoo[>ÇáR.¬,ï»ÙiÇbUžôaûr/Ýuߣ äPSôÇ[tïXûWÔlö^ï±’><·Çï¨Þø·§Ê¬-2YŒ£c§‚ÖÓ´±ÝÊ@[—eäÁ¯/‹šj”üÜßH’f'NžµéÈq±qD|œ“4“ —? »½‡#myùkÖW‰R^ÍÆWœrq ñuãåN´GÄVâ”ù\&;7ì_XÛ÷½†î;Û}—„ɾ-àëgÁØü+žs§1Komo™±Žò {…¹Ž9 ãÜP@$¦b8ƒ¿ Õ¥(?ÿÕö¼oM`p× q‹Âclgd(ÒZÚ¤LW`è•ë`~¦Cagoysy ¤Ý]qö‰’0^#Kɇ–Ðð7éR)AO}Ò}7“¼’òÿ§ñWwRkœÓÙG#¶€lF΀ôU……ž2Î;; H--cß`ŒF‹²IÒd“újE(9Ã6ÈR£‰ ³•E 3cãâX’OÄ’jò£ÿ±Lù:æÖ‚”ï¬,òvrYßÚAwk&¹ÃˆôTŠPeì~ŽºGÔqçì0Zd£ßž4]¡C¨Áà6¤þoÇ~¾jâï Ž¾Ìc²×6üï±½ßd—›ßqx¿€tv¼ƒ¯…XRƒ?Ôý+ùMì¿òösìüÿæ«ÎÇw–¾ÿƒ½qñòÙùÓ¦:WògÚ¿åìæWÚ8ηþ×ýÏ[åçç¡ò­(+ñV™OmúÇ)íýë¹%·ýޱ{<'\bñ÷¸ù÷“ºËßÍô¡o‘¹šÎ×¥.ñ±Êï ¿rxîeˆU9qd+¡³î‚~U¸¥=î[#eÒë•l$óß,QË>6ÞUye{ЇÑÙAbûÅt=EHÍæñÝ9‡Ÿ-–¸ö{8÷%àÏÇ“|< °¥o×ý)Õ±aó–“ÎÎQ`bb•È^GŒn¯;^ÈÖ’¡É‰ÆÍ”‡).>Ñò§®Ú2¢ùð¯­ï7€~'ç\þ¤Ç~PýìÿòŸ²{›~ÓÏŸ;ã÷¼ï[üh,)Y>ªÅu¥ÍìW½/Ô––i 8Û»5x§`ä±iFÝAS­(üßQ½‹Ì'×SÁõÿ°ýgïw½ƒŸgï4j®.—鼕šÉ-ŽVÎYd¼¶71Gp‘÷ˆw1±Ýv%ýOÞðx…!âlæÀõ.7×r]½Þ›ÉäØ3MlaŒM­Ÿ}Öb’Ĉã÷|ë*¾Ç g޼žæÙ84±En¨ *C @ð@Aw?‚MlËFœÜªo\Žü+#pm_Xà䈖æÒD¡€f]žÅl/ÿh_í¿Üj¾©]3V18Rªjœbp¦·³y Y±yYÒÞ–DîÐ ÈÈýU×Ú2öþõÅœ êM³T_ ÷È•XOw0˜¥¡ ‡cÈüED愱µ»š=„sÜAðô>ÏLLp] k¼5Ó”¾¶0M!·ÂQÈøCÐ|=~EÆÚÜ7°F’¹à¹þ¾t<úÕôItKEuØ–¤r‚ÛøôׯƠOo 2bŽ0u°ŠÃðª\2˜BÍ3sº!ôIX‡”_å?Ãó©T¯—uK;QêIЬRú¨×W±[2FvóHukêÇýÃñùò¨æî{âVÃKÈ7.6§×Ï—†øŠ“ke  c&G×9휉?¬èxò~tº~;·ÌÁqs+F ¶­‘½ÕØ?x¼u¯€ï×ÁJËâ?çH¾ÿTÖ¢º-pD”¥+D¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¨××ÑØB%”1RH÷H~$|½~§@!7PÚ//³ŸÆýTN_25÷~:×ëƒñœ1¯¤Z¢vjœJÚ•RÝCh¼¾ÎõP=9|È×Ýøë^w®ÄÝCh¼¾ÎõP=9|È×Ýøë^w®ʼnW­Ùõ–Ôª–êEåösøßªéËæF¾ïÇZó½p~&êEåösøßªéËæF¾ïÇZó½p~,IÖìúËj§ÌôÝžfòÆýäžÛ%î{ä 9ÁÜ>•Ã#rQ¯yN·ãGÍ}7PÚ//³ŸÆýTN_25÷~:×ëƒñ7PÚ//³ŸÆýTN_25÷~:×ëƒñbN·gÖR]`2BáÁêüÑôòb³ùÝë®e‚‚â;5r÷SµÕ̲6Úi˜R€'@é@_Ë-[›‰Z;»È´4Š…o{ô#ÐúGëƒq„¹[Ëw#—z5WâG¯¼A;ñ£½·¦÷å[uäu»´4•Âk;k†å4»ëAÊûÃø¨ª˜ú•ôE´¨阎>þÈÖåOÇý D¸3¶W„F`5¾n®½ï;'÷¾ž¾ÓŠc¤Ú™ÄT–bH,Þ8÷Ä+klXþ³æªªæoÚ$þÔÿ¢³wÙ,wr7„Œyg?+½ÎˆJ$*–bdŸ…Výc-ûÉ7Tð×?Ň®¿:Ø5ð,®²MÜÈ ’¶¨ÚoÀ³)ÿ0ý~H«DEB¢€Thò’\-¬¢¶fpZIXË!äú:ñ¿—ãðùÔšRƒêã£0Ýacyȧ¹µ¶–B¶«pñÆÎÁ4ì‚Y@ yð¼yñ¤Ã`ñ}=ŽK E„V«£Â×"˜ú³h ±Ù:òkžúÿù§ý­+ªŽÌ*R”«ÿÖ÷¹ç†ÖÞ[‹‰c†¼’HÁU ’IðwPß;‡ŽòêÎL­Š]ZDg¹…®<1€ w]íWDŸEWõG½>¿ dÊÇí$øQÅ$xvß›û! ÈÛ_<´jî/,nzÏ caqhâÒöyfÇÁnâÞSÀk‰F÷Úc&¾âòiQÃÀ0m)YþŠñҶѧô,RÏ ™AµImÊŸÎ^ÐMçÑÙÞ΂JRJRJRJRJRJRJRJRJRJRJRJRJRƒœðCuo-½ÄQͨRHäPÊêFˆ ø ¬¾/èëêÌaïåÝî-mnYmîKr3±¥äÅBñŸà­e(+æúá³–ÂaLBÄÆáŸ›O$žŠª•z–%‰ôâ>õyV};6')‡·ƒ™Çp³_Ç”´XžKo*Dh[d“²jŒ ‘^Ù^/Õ_@×WÕå×Vð’îRá>®¶€ibA¾*o^u³æƒÔæÉC}ƒµÈØ#ÝAt‰44œ‘—cËDx>ž¾j•³BFêÒh@n+±ê|ïÉÒü>gu[Ò1'Ñ·K¾2ÿ=õ…‘¹çnM³!„°<”{ì8’9Ñ,|ïÆ†ÞîÞí9[Ì’ x‘¿M‡éªÏ$|.BÑ•›¾ªª,ÞêùôÑ>è©5\eœ²w \ïm(NývW[ý5±·!ö[Æ O"%_†µ÷uòó½Ó5@³ª«Ïè§ý课öJ ÷ †- üGæø?ëñôª[û»ûëÙ`´·6êç4ÊË @û ³ëü£Ågrs ‡KÜ”6zRY˜ébŒrbu¿A梦>æýĹ6mPíÏùŸÀxõòAÕsžÆ+R¬ï#’^iäß²5éëê>'ÁÛ¯OÃ_£ZýZôü>ïÃÙÖš3y÷ú~êäѳœxý VÓð×èÖ¿V½?»ðãöoOÃ_£ZýZôü>ïÃÙÎïÅ—¥?‡Çè×b?çH¾ÿTÖ¢¼ÂÏݺCéÇgå­Ñ­qýî¸ú§Åi÷?{ÇûÝkøº×Þë‡æpýµº1ŸÅ?‡ÇèÝÒ°Ÿs÷¼½Ö¿‹­pýî¸~gØï¹ûÞ?Þë_ÅÖ¸~÷\?3‡ì{ì£ÒŸÃãônéXO¹ûÞ?Þë_ÅÖ¸~÷\?3‡ìwÜýïïu¯âë\?{®™Ãö;dô§ðøýºVî~÷÷º×ñu®½×Ìáû÷?{ÇûÝkøº×Þë‡æpýŽÙ=)ü>?Fî•„ûŸ½ãýîµü]k‡ïuÃó8~Ç}ÏÞñþ÷Zþ.µÃ÷ºáùœ?c¶OJÑ»¥)UzÅ)J)J)J)J)J)J ž¡n6ûÚûP~ö½?1é­þÞÓ\×5÷?{ÇûÝkøº×Þë‡æpý¥êãa½¯µïkÐóšßá­í5Ís_s÷¼½Ö¿‹­pýî¸~gØ÷§ƒÁüCõ”ëÕ½5îñêHôÖ¯c¹×ç.¿7÷:ÐûœGb û9ìþÞî³à\\G íñ_SÈ=}Ýpüαò{XqýyÐvVêÉ ¬w‰³’QRPI'~ë‘âG¼œxÄêKHRôÏNö•q7ÓÞ\ÞZuedßÐñîl•M^?/É«¶7!it±qæm¦W ±±¾$qð»wÂ~gØó>çïxÿ{­ZáûÝpüαñÝgÿ%åús/iûõòpcæ™}Þvî[q¸÷A +²¥ û¼JñŠWÒJóЙ;Ë ÚÚæ1$‹ ÉÊEC¯M­AA  Hµµ4ã÷-† ·’YŒµ‚ÝCϹ´ xø[kµ+Ä('îñâ>çØòo/ìñp¬××pYÅÌ yä//€Ù+£îz{ºáùœ?cÁ“¦ñ“ôôvëoh )½í½ñ¢À¯-¶½äÙâSì)1òÒ^}ï>Óêd·ŽÀ7…¶îDZBÐxÈñ`«­F«¸„SEQ3Óé4ûž ²Eöȯì$±­·,"{M*'l<¦6wmoÝÛrn;^?$ãÊ?EÅû¹‡§¨×§À|?sé¯Íô÷uΰš(Š/ÑáñÄ¿ÿ×ôûŒ\Éo7³ß:3FC4ˆ ô:×?3óªËlVdÊI–åÆžf'gât>ø>C{>kM7íjÑTՅȈ)JÉ%)J úÿù§ý¡õ†O¨1;‹ÎžÃA”¸Š'c ÎÈàq*OsâJòRu¡²jfúÿù§ý­+ªŽÌ*þT³ú^ë~¤ëW9®ÞÑ/a¸|fD˨ßpT1*ÌGð5îv?K½yy”¹`¾;[ßÁ%¹À%’F`XA÷½F>*Òë¡°·=ocÕâ)!ËZ#¡xˆ 8d(;ƒ^J© £èÀ^_XYäì䳿´‚îÖMs†xÄˆÚ ©ðt@?¢¬!Çs…ê¬\Ëkyi‘³/Á¤µ¸×L4èv®§‹ è°ž¹·–2‘ 1ŽFFxe ©üA|+•úè<³ÜJø(í§™8÷-%xDgŽƒ*)àõûº'Éf£Ÿ£Œþ>á'Àý#õQ’Q”ãV‚8«q FçáçaèA ­¼VöñG  HãBª(à~6‰JÁâ¾™z,öñ&v;iæN]»¸ž㲬ì8=>ö‰ð Ø­†7-ÌÛµÆ/!i}¹F’Öe•Ch¤èƒ¯ÄPL¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥dò_IÝŠ·Yî:ŸèÎ Y…ÃoDùXù“²cgÑØ¬,‹ï›ŒžL\ÆÃÓ€XG Ç`ìøÐ?)ù1ô…•ûL¯\ÁŽŽovâÇ^(ž„E<‡¸¬GžD{¬|xƒIÕLÉ‹ˆ£ºžðò— û­ùÇ×ø+%nª2­2¨f•J4ð•,v<«§‰§¼ßøš›'I·Nbæ ›ê Á¸š?)ôÅÅ_î)Žùy?€¨vC³‘‰Q¹‘;‹¦;>9£x>¾‰ã׿+*¸¥®¥)Z ª«Ïè§ýè«Zª¼þŠÑþŠÎï£'ã´}=|þ£ëú7ê=7ã\—Ïú—#uêŒ=¹Î˰¾ ‰*ÄQ¬éãm¯_ºÒzOÇhúzùýG×ôoÔzoƹ.7J^¯Â_[ânf¶Æ™û޲B¼¹Æª †u>;ØR8­*ŽËÄéëUg—ËÅU›Éå-z^ÿ=Œê ™-câ–ÌñÛžn'hÜøˆ{º Tƒ¿wzñ¤ºöÛì_WXbÍô¹/a•äYR5{^ßûWÝ?sÞE¼¤i9uŽ&âã¥.°øŒt’=Ó™6ŽˆˆÝá#ræÊ|žGÀ q;@'Ý¥¥öëÚ±¸§\uãr¸ÆÌrZÈ»‰¦ £Àr^CDr „»,ÓUÙ×”rÇÏÛþÈÅÞ_õnôZ_ËŒ°ÇÍ%¡0¤fi&Qï9æ¥QC€N¶J¿Ùs™fÂu Œ·²[fºv$—6q ŽçìYã\†:îáï9Ã$i%¼¬@e`ì‹ÇÝä • #o‰^Iñ. +õ/Rägdzåóð Œ2FÑ6HÃ;•¨}iASÅGbµ<îÆ˜áñøñX`:¥ÿ&¯®s%Eæ"æK¦8‰¥Œ€½´÷XÒºSÈix…Sƒ¾Íd>¹—5’îÏe–˱I1ðâv¾ê¸ôÐäWJ‹éÜ_/€»›ª“6ÞYÚ]@“ߨ±ˆ;OlGaK‰N\Tª}‡’žð†?N¯P`¬sÎ:få®n²S_[B÷PF]£Ò³+ûŒ8³(´ÞAPb±TQ1TÓŒÏÃÃï¹m™ÊÞÍÔvÝ3‹›Øn^ßÛ./YWpÀ®ˆ•€M®¼€¨d/°öžLŽwº¹¼¹¼Å[YÜÜNÍ bTt(Ê£‡oÀTk·å” ìqÊâ¯lúªÛ©qÐûL‹n,.­9,MÙçÈH„”©%X¯º‡‰Œ¡I’;Üý¥í•õŒ˜ÌtÖné1§,Ë¢G1¢ R<ú²Ÿˆ‡lÏj˜ˆ˜Æ;ùù«,GRåð‰œ¶ËÅi=ÈK«;µ²E­¬r?ä°_yÔ¨B£ˆ#ÚªËõNRó¥±=QÓ÷2Ú‰‹3ØÜD­cšIÒ>{=Ž!•{ŠG:†ÞÂn¤Âà“˜?i¼²Ammx.-¤Eâ©#òq*h.Øk`ÂÚ#Š˜#ÛàîºbǦ±vXû¼ŒXˇ¸šå h²J­ î¬gߪ±¸dÔF´Í4Îg®œ8b~œuHê§•z2;ì4‹ëÛ&»µÚ(Ö>ã¹ °8ª… ®!ûcC@AkÒ³\ÏÒøÛÛËÙ.§¹·Žá¤uPÜT Pxøó°ïƒ(:Jÿ„ÏØ[Ãsy Ž{M°1F°E0ìÌÌ9 âYÇ ØQ¦1júU.íºjÂÒúÊ{;‹;x q3¡,R5Û®tB<• Æ~ï`3¹SF)Äëýáêt¥*£)JP)JP)JP)JP)JP)JPTõ q°Þ×Úƒ÷µè ùMoðÖö𿹝¹ûÞ?Þë_ÅÖ¸~÷\?3‡ì}¥Ý¤w±äg 7¸Ú;úþtFˆ@^ž´^?i?z0œ~@kîü5¯×ãh——Òú%Ë·6©àÿÐÒåz]rY«\«eò³Ø‡«„$£0®—ÔëoÇl+'æpÖ¹«eºîDcq,Äݹm¤_»"7Ž,¼OÈiH!B‘ÕzzÑxý¤þ5èÀzqù¯»ðÖ¼k\‰zzÑxý¤þ5èÀzqù¯»ðÖ¼k\³©t<+~мyKËÛ»û«td·7]µ[m“È¢¢F´¡yXõ´âÝ™؈míïíîfžöɤ’XïX:ª°Ñ‰T…   º]p;âT˜6«ÓÖ‹Çí'ñ¯FÓÈ }߆µãZàœKÓÖ‹Çí'ñ¯FÓÈ }߆µãZàœg0OBéÅçPôœPY¦>L®Jl\~ï°Îñ˜Ì`±³pY  h¸ØˆÐVÊÉtü¹r0Ý\ã²FÐûU¡Ec¸á׉U+Èl%‡Ýeóð~=^UxÒ*Œ­ÔúK!Žé‘ŒÍ]eW+$÷E ÂÊ! ᕈԨQðR¾cÙã¦íjq~îF!éê5éð#_Üúkó}=ÝEb0¶Ã^ü¾5è@ô×ÈxôøzxÖ¸§†¶µÅp¸-#hðȈ<Ĩøz*ñ´Ìaj:ýå5ÕÝ‚ÆoÚ$þÔÿ¢©ªÉnRæÖF@ãÜß¼„#à}ð‚EV×5Þç³)JÉ%p»¼‚ÊšâEDP[É×T}AÖ8HÊ# ®ŠòDAý#ÿ^¾ºÕyvO3’ê;äG2J^MCnƒ‘ÙðÉ>Îu­Õé¢jCúw qcãh¦I’P$!X4TüFµæ¦Öè·Ôx\;&ZdKTIodà™abNö0Ÿ'óNÁß×DF4AJR¤)JP)JPCÉbq¹›u·Êcí/ W±ÝB²¨m°½7øšÉß}ôBòK©ºr‘õ±²Bƒ@Œz|Ÿ_ZÜRƒÍÓè³#ŠŠ×òs¯úŽÊKm$i{*ÝÀ±…+ÄBB¯ÞÀ×½Ðb¾•ñw¶IÓù¸$E<ò–mlÑ0'aV¯$ŸàD¥ÇÔJ÷šÞû¡ñ¹gWÚ]c²‹o)Q㌻}ƒ°I×à>'Ÿün{>;Ú²= ÖV½¸»—êÝdžÛß,¾èóï< èW¤RƒcôÁÐ9 Èíaê8GÞŒñI |»¨Qéñ>}=kQŒÎáó}ߪr¶7ýw=’á%á½ë|IÖô}~Fºd±8ÜͺÛå1ö—Ð+‡Xî¡YT6ˆØ Þ‰üMeò_D½•¸Yî:jÑP ¬öë­“åceùõÖý>BƒiJó¹>…:>'†|:d°—‘?%¼Ç_Ȳ€T©]¹`΀?޶ o¢ûèKŒúBêèo#uxžîûÚb0>ôZPà€F‰×ÏcÁD¥yÿä—Òÿÿú¿òÓòKéÿ‰ÿýßùh=•çÿ’_HüOÿèÿËOÉ/¤?þ'ÿô å ô WŸþI}!ÿñ?ÿ [ÿ-?$¾ÿøŸÿÐ-ÿ–ƒÐ)^ÿýE‘ÿŸþ‘³“öÿiúª8ñúßÞçÀ7?EÖý<üëœßD67¨ ÉõgWdlË«Kgw”çÁX7AÖÀô üˆ>h=³ÿ—}ý•àÿÊ0ÿ:³ÿñ%ôyýþíÇþ%^Aô}ѶÖñ@+†)S%”nį,À–?‰$Ÿ<ÿLÿGÖ×ÀýExÜ£í¦u$xeB~ ~?¦EóÌØ^Ÿê|ݤoÃÛ1ØÂñâ b#Ø ~­¼±°³ÆYÇgai¥¬{á ˆÑvI:Qàl’MH ósÖý}³š|GѤéóÒ_äc…Ɖ ÒBÚaè ]ùø6´k¤–Ky'† ó]1‡ƒŸ).qÖòÏ.¸/ ‡ Öüƒã×à}”v>Ž3ù ‡Ÿ=ôÔ¸EH†/Ž=TIä«È1;t#úèù^ió ’ÍÞJüšó##J@P¡v…Aþ:ЉJ ݧº™"G«0ýÂ+8®b0ã»ÐmÝ®kªg3÷É_ì7Ò?O“þß!òøzxíç³Eg‹:5ÆôNøúzèxøëÐ… EÔ}{qmÜ6äiœýãçÔ÷ý@Ô–èÌÇXÞ·R–‚^7²ùT'Éõ;vüÌl€w[SµZ#÷#ZãùšãîöSdÒßîúquø|´GîFµÇó5ÇÝìk)S´z6×9øy2SdÒßîúquø|´GîFµÇó5ÇÝì>¦È/¥¿ÝôâëðùhÜkæk»ØÖR›G£msŸ‡“'õ6A}-þï§_‡ËD~äk\3\}ÞÃêl‚ú[ýßN.¿–ˆýÈÖ¸þf¸û½e)´z6×9øy2SdÒßîúquø|´GîFµÇó5ÇÝì>¦È/¥¿ÝôâëðùhÜkæk»ØÖR›G£msŸ‡‘JRªô R” R”ÿÑ÷úR” R” R” R” R” R” R” R”ì¦*Iïg¸[»¤ºã°Ñw^T\ìlÍš0>ÎIŠ:ø¿óW«êe°±¸µK © ªÐ™ž6Ž%$0ðÄ{ÇÆüx#ã^iŸ¾´â#šEUÞ”7º7ûÓâ«1‰Ì@õ‰‘%mÔ„w÷½äSè~( ÿuem:ÚQ¡³—ž°.âÔΉ¯´·n[ßÉ~÷Çåþjô`ú½ïøìßΧ°Gý^÷üvoçS{gœû£Ìëx¼c1.B Ò)$†h·ÍJé€ <ù~¿IÓ#šêëÆ0“ØÉw?!°Ñ ¶ŽØìx>wé³^ùs…²¼ŒGt.'@y–êVüô[ñ¥®ÊÆÙ-­ż ¾1Cu**ììèÐòI¨‹–cŸº<αG‹—Iô¥#BžÕ|tZîu”ñÑ û€vÞ=|è“¡Zª öÿ«ÞÿŽÍüê{ÕïÇfþuNöÏ9÷G™Ö(ñ_Ò¨=‚?ê÷¿ã³:žÁõ{ßñÙ¿Mížsî3¬Qâ¿¥P{ÕïÇfþu=‚?ê÷¿ã³:›Û<çÝgX£ÅJ öÿ«ÞÿŽÍüê­Èdð‹…·ÉuYLËÍc¹Ë4lWdlpu°|þ›Û\çÝfþÆ•’–÷ vòM›íÇsM>QÀ–5^lêKûÊÞ$xÍG—5Óvýþ÷RóÊ!›ža‡jCËHÛ“Ã{­àù÷OÈÔï-sŸwÔßÓÊ[ZV~¡é[k‰-î:ªÚ)¢b’G&h«#¢2l~.Ö÷ {5…¦oÚ/ åÝ·‹(ï$|N%±¢@;øÓykÇÝõNþžRÖÒ²9¢ø¬T·ÖÓÝ`de]JÊ}ñà‚ÞAô­u[òÍ;Tð^Šâ¸Ì¥*)JP)JP)JP)JP)JP)JP)JP)JP+Æó?óöGþõ/úƽ’¼o3ÿ?dïRÿ¬jô>oÿIúvý²ˆ+ìWÀ¨™X}ªÇÙ„‘«ÊëÅ$m,ÜO3üUð|àúTËæmFf"VK_kXˬf*[Í®?›^^Æ«lê¼b0g‰Wî¯Ü˜xðZC³ÄìH¼ÆF¸,¢ |vP_$v°ÙñN)+1E•‚íA,éé²jw¿tUèSÑéÓówã‡×ÛîkÖº­epX8LÿXO‹´ÇÜCw!-£U!ˆ-ÁK+n?…‚¾æÎälîr/8´6W‘NfE‹¶9rU®îçiáaæ^·Ìw¯Ž¾…j£b]”ëÝבP:ƒ!}ŒÇE>> y¥k¨!+q#"ñ’UOP°†÷ç\Iµ7¯Dìm?ÿÓô˜£HbHãEHÑBª¨ÐP=*ìµ’\Þb §ÆH¬¯à±™£Õ®c™AcÛ&_Rüô~åW^õeéÇe#0X߃‹¸¼D{Y£·áËÜpEÊ•“à Px@଼:mÕ/Aö+=cÇ×Y–RäÉadÍÉËyÜŸthC{>¤šªê+«Ü…Ã"ˆVË›ÇÀÉÉÖFc$Ï`ñeûP½¶_QÏ–ÀZ-Mœ7ô+"3ã!{e½…­ÜùŸcI¸4‹ÄZ,ÂI(]НlkÇ– ïIè七¤$71ÝßÜ;©qs/ƒ+)b7ùÄ}u¿+lb2ÓŠý¬=ŸWå!ÁÔÉ[YÉíIrÑÃmÉ8v–2T³o|û ú#ßûÕû›ÈçãIq¾ßf·\ãeö¨mdEhæ¹1ð)Ý'ÁdòÓ+ÐûÔZ(œ·ú+ò¿EXâÿ¦þ÷Õ…Wâÿ¦þ÷Õ…V^—Gý8)JQ±JRJRJRJRJRJRJR‚¯3ûn7þôÙITI|qÖvÓÇb÷7ðȶ’\‹f(ÀÊR0_Ayw[,• X]æmÆÿÞû)+ò²éq™I{’H;­¹9©$.¼*Ôëû7Žß•ÄC½·X.-MŒ·×pHÌá»nÝÆæ}§"=Ñ(}…ˆ·¥6§›e±y¼\–6C;”X-¬"X¯RÎòõåºäæYb“ÿ”BÌ<éFƒmỖ«¬òõ X5„Âåq±Ý4nÝÈû@˜TñoÛNÔ«hljÑÙÒ›FÒÖòÿÕ^Ã{ý í>ÙÚý÷¸öùïïüxëÓÍfì,aÅu–RY-óR\Þ_¬öݹ®Ý£hcFg<»#‹,žëûÀ*…p*"Q†3¥>±öûNÿÖß`o®=³½ÛöÍÇǵÜ÷8ÿD~Óîk_mq“¿Éà3¿UXÞÚd­}¢ÚÓÚ¢Xû²ªû’'#űcàèî¯iL“:åˆìñÅäfž¤ì»Z¤ÂõîKv„»Ÿ²³ð~Ó6Ê>ç ¸:¢ÏÍ•·Æ$رԅc¼¸|hT»y BÏkÞR ízИëì÷^©J˜©1V]#w5Þ »ëz­ Ôñ'¶Á$r„­Ú'¸7Ùvýã²NöKn©z´Éù_„‘'ËÛEm’M5Ž>k…pg·q C â'D¡½ƒÅ¶ô¨Î¹DN¹yîvníØ0YHd›oÛ³“ÚLÀ»[ÚÎŒ­Ûâܹà0äãÜÕNc ÝK•Í,£IvÆEDÆÜ7tD U!|ª*Þ†îýO~±J˜« ŠðËÞÛZþ[c¬Î9ÚÒ\uòMÆÉšÜ´ÒBä;á¶íÊH'ÉõòÃq163d:Ï1u)žK< ¹‚9,dˆË'²-¹q+é]?lUÞ·-ΕFÒ—«?èÍçð'úëZúÈugý¼þÿ]k_]–¿F=³þC¯£ö?²”¥Y±JRJRJRJRJRJRJRJR^7™ÿŸ²?÷©Ö5ì•á½Ky<]QwkkrÜK=Ä€K)B«€|…c½ºø×ÏÏÎô¾wÿCLÕE¸Žsþ>ÅG»ÆZ_Ë·±–%eŽD‘‘6·Ä©Ä †Ç¡;y™–׺Ëgµ¶¶[«¡$¡Yòð  ÃxØž|øü|õÄs]ªä0ZÜ¥³7yyÈ·ôò\o“.ÉÚ‰—ÎÚ³v&&?¸óñø¬aÄYCuÌi"Ë2!>´Çm±½1'É'd ;¤\cíï'¶ša!{gîEÂW@ZÙ @>6<ïÁ#âj¢~ ’ÖÙ„–\¯äZ˜£g‘9vû»P±>IëãÓÞ®×¹K³Ò™+hÞê;yR`T¡]í€eÙ ¨ß¿tÓnöbfxéž'ÿÔ¾Zâ1Ö†ÎKNר»´„r;Î\°;Ø<ŽÁ‡ZÖ…PM’¾Æåò3ËMV\Í|p€/1º 1ã±°7£¶_tT»~ »–ÆKÇÅöb›TY.6—½Ú]…ÙòvHÑÒ°Ñ2øªl܈‰þôïÉÌ[öùÃ+”å²× n<„„¶ä">Æ”Aªè7‹[´ºKÞŽv¸½¢O³v$·ËJ±ä£Ã|AШÐfî õ½¤Öq$tÖ“”œ°Gì÷”®Ôr|ñÑùú×í¾vòê;x °€ßH×£{’±¨†^Ûá $’¤#Æüy7¦/søû~©ðtþ2°U·b¶ VÜ<Îá*tvO ©ß«­hU¬¬JUKY›ÞrÇd’|Ÿ‡ŸÐÀ¬M—Qd×Yi-™í_m$>Ò [G¹‰ î‚ÎUAÑl\µ­Èß}_dg÷ÉQ§. »º¢ìùÐäÃgGC~¥ÕEq1N~þ«7ë]†õñYø3×-mg5ŒI#^5ÁK‚Â7ìwÔ¦Ðs|ñÑøæ¹[u6FêâÚÒ*™–ä–k°!F‚a\y‘ñßÎQ¯¼TÖš.F1þýò^ä±íÆÍiÌÖ­/g…ÙdP$«:^£~¡†Áë’ÅZåí–ÞðLcYP"â<”íNЃàèÿÔ Íu4óãú‚Ç% ÍÂÇicsuqn&nÜÑÆñ7İI$+éïpÙЦfêæã¬1â.ÚÒÎàBÐ[NbïÌm嘣Ž@6‚[‘²í|€mM5N'>+ÙzWqí]Ä»ý•p—Rñ¾w*ýÖÒè urºç7E`îv$†óá¦BácXÛ\£TPéGÐ^VEÖ1^DÑmêÍñ™,H³MÁKH†S´ v ƒá›Öç9 Žk™§ä@ºG¸¦Þà ‚Ç_¬ì’IÏOL³ÂYYdþi72@–îÒ]K dOºf#cÉÞ·¶c½±ß<‡KárÓ´·ö qÉ‘Ú7f1³©r›â[J‘+î“ÇÅeºvÎK¼bHú»·\ƒeexœCwÅ"àd`A_tóPHVÖþð¼´ÏægÈÃa&Ú;‘; ¥ŽD q˜ ÈQ°IõY;eñTN’žzcÏvæ;žåÜââG“YãÉžãñó鯙p"oiÿ”oÚ.c¹n"/u“\@Úz{©ë¿º>gv‚¾ÅL¾n‹÷#½[õ®&öë¡,·åv÷ ðíû£†ˆáîûܾ~¾jl˜èçÄÏŽ–i'‰ã’Vm¹äÎõ |ŸhzÕIZûZ‰mkœfx*¦Òe½WÉß°¼·òí£'ŽÉ$ž æÿ€@Ô»|qbä±{»™•ç7 ,œ¤…û›Tïh‚>GаZêµWD^®c*åÁEÙþ‹¹ö®ÿ´{g¹Üîpíï\x}Ïw\u¯>¾j£%Ò¢8­a·Kë»%yå’qNæIX6®6š8ßÞ÷¾<˜b×AFöï×LåAO\d-/%¼Žkûoe–4ìû±n>ˆG>,܈$mÛ€º½Ÿ—˜å´ži\¯{¡ù¡ ¯àqØe ­kǦ¼Wu®«F»Ê¦r¬?cú2ëÛ=£Ú}·Üî÷8vùkÚýÍqÖ¼ýï5ùŒé[l^B»küwþÆY„ªÝ×û, z„ôa÷vvY‹\­tZ6‹•cD“%Î[e=®áZÞ„@¼;l®AmíyojžŒ>èù×7CãkIî㳂IÄ®§¼ |Š– DÆ1¢]yÚ‚4+]­S]QÂYÙú=®§yæê,»HýŽMÆØo³!’?H~ Iü~;uÅ }æFä^\Îo¦ºKÃŒl'»ÅA×Q䟺>$“0WE£M¹6/-¤-u\Û¼’I$_`¼Ë¹w÷– ë²ÍåX¿hWÕ¯I­µÕ½ÐÌäžâ+™.VsŸ˜PÈäF M(xÖ—_q8ߊû^+–}ºFÃÜb¾µÉ-”¶ÆÒ(ƒÇ«xNE÷=ïtäü˜ è‚I?St’Ï”'Ìä½±b‰#>Ì¢º‡µ¢ÄK6öûC 4¼tô*VŠå›±èÿ`»[˜óùV‘åWšÛéLïÎCâ!ç˜V@ÖÁ¥¾é ›¼jÃõ®BÒÂÒ(,š±y`xÝÏ#ßPñ1Ñù=¿{ÈR}WíŠåCOÜÊ=¦lÍݤ·±X2ˆ^à"¯qK¡} ¥ßR ²Ãc †´ÆE<ÓÅkŠ7›>ƒÄàhz|<ìù©µú(©•Ž/úoèÿ}XU~/úoèÿ}XUeèôÓ‚”¥¥(¥(¥(¥(¥(¥(¥(*ó?¶ãïGý”•!d×Öê‘ÞÝYÊÍ&¶e §Dy XHÓ)„h€DœôÑ@qÒÍ"Gݳ°}”ŸQ~·Æÿ\m?Ã/òÕ/Û®­™¦&tùË–üLÕ„Ó¢-ì²¹ )#i§…£-+HÅä.®ÙÉm…vBñRAù=ºm!žîÒÏØ’Â{xJÜ[&ÂÄåÕ˜ÆÐ«{ÇÎÀÕ‡Öøßë§øeþZ™Œ¾³º¹d·º‚WIXä u±çÅeM«‘:Ó8ö)DUµ„ßcæß®žÇÍ¿]GÎ_ÍŒÂÝ^ÛÁÞ–$Ú§z³¯€õ?€øzÔrY8±÷“*ÛLPŤ‰ãpîG×}WaÇð­wtòtî¨ä¶ö8þmúéìqüÛõÕÇT¬=+o”AÜMÂé‚«¦$zñ îÿ (ØÞë›å:‚;üu”±XÃ5ß²3u9È|?l(yNÔj›ºyª94ÇÍ¿]=Ž?›~º¥›%™‰°Ön¶qd/LÐcfG#¢{^<‚~ zÎÁd¦ÉÙÍ,ËÙÜIK!&U>vOƒéê}šnéän¨ä™ìqüÛõÓØãù·ë¨÷¼uµòÙKq«†tN*ŒÀ3ïˆ$ t|éæ¾Ž^Ä]nó@r>?x!Öœˆ]Ÿ_)»§‘º£“·±Çóo×Ocæß® Úõ6öAµêË!¤¨ÜˆØ['Á<}uçZ¯«¢Ädn#·´¾ŽI¤Bêš Ôzø'^ºóéæ›ºyª9&{6ýtö8þmúêå(÷uu³¢#bX¿Ü 5ïï[w±çÒ¸·SãËXö ³¥án ûªd¾tT=|ïÒ›ºyª9,½Ž?›~º{6ýu[cž„à྽¸‰ŒØµ¬R2ñV °R9•1ÑîÌâ)ŸrbЧL-iXI:’{»ßØfî[“û\Vû+­yH<´7ä¯êñ©PãúÃ0¡šI-#òÈó?húëD Þÿ„|â~coLÛØý~+iZE4ÑDSLçËÉÑnŠpR”¨\¥)AÿÖ÷úR” R” R” R” R” R” R” ÌÜô>2êîk—žì<Ò4Œ×@“³¯v´Ô©Î_èÖ¯ÄEÚs†Wò?÷‹Ïã¯ókëò?§Þ›ZŠS2ÃÑÿœ3¡qƒú}çñ×ùµú:?§Ýÿ›ZjS)ôwEõ!›ÓîÿŽ¿Í¯ÑÑxáý:ëøëüÚÑÒ¡n¡Ñ½Hg‡Gc‡ôë¯ã/ókèt†<N¹þ2ÿ6¯éDõ.êB„t€þ›süeþJú-b?¦Ü’¯)Dõ;¬)GLYé·Æ_䯡ÓvcúlÿÆÉW¢z­ŸUP:vÐLŸøÃù+è`-GôÉ¿Œ?’­iDõk^ª³ê+Qý2oÖ?’¿FØ~|¿¬%YR‰êö½UwÔÖãóåýcù+÷ê{ÝËúÇòU…(žHTÁû¹?XþJýúªÝÉúÇòTêPÜ[äƒõ\»“õä¯ßªàýÔŸ¬%M¥ ;H_VCû©?XþJ}Yî¤ýcù*m(nmòq‚Ù-ùp,yk{®Ô¥DE1ˆ)JQ%)J)J)J)J)J)J)J™#IchäEtpU•†ÁÔP~¢ÃÿZ¬ÅÓù*”ÿQaÿ­V?âéü•ÚÛag!’ÖÊÚ#‰h¢U$|¶áR«™êœ¥¯OuccÄ6èíŒÅIÍ,‡{âZ0vY7Ë‹ò@Ð_Á{ËI¬åŒE6’r‚b@ è ±ô>@ññ¸¼5ý•Ä+/³{*\Ët±Ç#}‰`ʨ£ŽŠ€Äþo–ü=é×Y)¬º‚ÆÒeØïÑã†@%¸@_òv0ì€^Ñ’ê¥5:RþÛegHä¸2Êʲ*³7kˆB íÉÙòIôð¸‡ùS.Nt¶ì˜=š>7%M–ÙtI:ø}dúŸ‡Îbqóö.2½ÁjÏáÓ‡¸OÁ1¯žµ½ Å Â=ïQÏ“¶³šÜ@!7Ï@6öÊË­Ÿ øôóëW‘Æ‘F±ÆŠˆ€*ª ¾©ACþrª."Q}#¸»ŒÊ éW^5Äù‘ð5¡½Šù:bþLl1r³Im¬ÚÖc'I)`Ù^^4FüïÖµÔ ÈÜtÅür\.=¬Ò`0÷ l¡òå€äI'ùy{ïºNýŒñcæ¶‚f–p’Ì `ÏÏC[c¿#á°G½±s{™”ä†;±É,L¦òi1À¾‡‚7#)]û ‡oTY3÷Ýuw'PÊÂZEzÑÊRåÎôXlÐïïÎcµ]kDòá]¨ÎÛ­•¼¸[Ã-…Â%±6Ó¼¯m$îÊä¯f‘,ÊFÁ+àMž9,&bòúöæ9lyKd,з0 Ÿ/µó£²H;:ö/1¹k ų\c®£¸‰\¡d?úˆ*Àú2²°Ø`Lʲ̚tÎAVêsK›HíDÇlöñ¨ ¢‚4Á†¶v¾I:s¹é+‰-ï’%´ s,Q͇ XÀâªÅIx®÷±â¶ ùŒ8DŒ¬àEW@ŸŽ†Î¿Y¨÷8Û É—VVÓ¸CK±å²?•J ÿ¨°ÿÖ«ñtþJ}E‡þµXÿ‹§òU…(?ÿ×öÿ¨°ÿÖ«ñtþJ}E‡þµXÿ‹§òU…(9Á6Ь6ñGK÷R5 £ãà éJP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP+.zzâ|Rtã·fÒÿÚM­Þƒ.y³†²Èòh1²Üµ¨¥=õÅÿQâähøXã¹Ýw9 É;#DªŸt#Ê[`y1è0¥ógü"æ¾¼ë\V2!$Ð[ãé"HöT–~ãø×”øIñæ½èc¨ú£=Òp¶~ÊImÂcË‘«+"òçÌ}â=à<ùòÞ™^oô=+ãpù~޹mÝtîBXp4m$Å㔂H÷Ér4~è_˜$="”¥¡å£¿›s2xà½dÔRH6ýD­€ÅX¢U€âfRƒÿÐÙ]ç^aéž£’³,ËÉí’X¹bCÊI-È–Rq‹+/qÓ9h1±ÚÛ…lHŒFòŸnP<"“çÙ†‡ŸY½OÙèI³ê,!ËØ:À!öË(Ò\ÆÌ0„mñÖÇÍ]y#V6vÆ,eÅõÛµ¢Ú· ˜¦i ž=£{cÉt|¹)^A”œ+‰¢1O{šäM¸Å=è}I=®&!š2ÚdàhI&ἕ‰¢äQåü6¸†v ž\jðÙ–ÃÚ_„T3FÑX°Gôe½Fô7­×˜ÁnùË÷êLÜw bÒv1ö Aš_ìcÑlT»¶ô5¢Ücæºa޼‘Ó ÷Km•Œjß±¶‚Õ?¨„ñÎ3ã™:.@#‡ÄsLîãó-LŪqT¶ÔªÌ6e2‘É‘{5ý¾…ͱn\7½2Q¶ÐÞˆ!YYVζâÞ'%)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J+…Óˆ$_Q;²To×YUv)œ1®ôS8ÃÿÑ÷úUh–OÝ·ë¯Þ쟻o×XŸ¬G%*»¹'îÛõ×ïqÿvß®›èäürXW›Ì¿Pý?[J"-z“Ñ’m%º€ò,Ê[Ç•T?;Ç«Ü÷÷múê-Þ2Ã#qkq{cms=£ó·’x•ÚØ;BFÔíAØù•Nö¾ŽKšT0ïû£úëë›~èþºä'{ T¨ü›÷Gõ×ï#ó?®§mm·z¥Ìô¦'=wou{3ÀF‰eÒ·ÌM£ê9¶ˆäÛ´üÍ}lüÍNÒv˜Üpi27/E‹)n;>Ì’Ö}ŇçqŸ‚åtBðÇfMMÌb(‘˾Ïo³mr— ëjÃc’6‡%ØÞYU–’Öñå’[k¨}šþß]ûrܵ½éÕ´9#hñm è‚••yîS9Ë–í§íå³Ë$WV³{5ý¾ûñå­ë’2ìrFÐ什‚¬ªËy…Í&Z)#’/g¿·Ð¹µ-È¡;Ó)Ðä£Å´7¢VVU¨f¨Ö^I ä¯-É6×q€%޶Qˆ:Þ†ÁØaáŠQ^Î’[¹4é<ªU<×îÖëYH“›*l$èØöIÖÈ ¤’„€IYï+¦':ºâs‚”¥JJR” R” R” R” VO«^i/m!-%”J†6ky;{©RÒg@Ax¹‰Ú±aÉHRÉ›ƒ5ÓýU–ÃÁu=ýÄÑEaŒ[Éä”™á†Ûí$¼òö¾rÂé-Ù´Ä’Ô)^Wa†–÷Òw·9î –ÿ¨Ùç—ëY£HÉŽK©xG*€ê† ‚Ž$y”Œž/%QÜbqõÌö¸Å’Îäå[µÓÏ9G¹(2¤eÅÉ@ÁÃû ¦R³}uí1t­ÕôRC‚=åÌ1»Æ×QFŒÆ!"2¼D§š“­h†©G–ÉAÔ==g‰ŽX쬡ž+¹ò y+ VBQŸ™xµ¿kɉä0i)Y8úºúO£™º´á£ˆ­—·Gg-ç—ˆF‰uB×.#GcŽøBóŸ®%·¿Çc%Äör÷R¡“-Úwc·iÌK"„åÜn*de]„T~N4¼ƒaJÁÜuócº~é­£›)‘{‡±ÇûZˆæHHO°—¶ ‚M#F³9™uîl¬ÌßVe Æeo0ب.-íbš;{›‹Ž"k¸äXû" 6ܲ®ˆ.ñ•ðƒaJ‡Éo W¢6t·Œ<¢nlòèóÞ‘¼½Ÿut7H—pÚÍ5ïNÉa/dÃv’'nÎ^ Hò¡Y‰ Gp†ò•‹ü¾•æË-¿Oä®#³y"†X­æe‘ã˜Bሌr%‡lÊx#’¡‡Î¾¸™ñj1¶¯žò%œµ™„ÜÒÚYV 5/ Ž8³ 1B>C§ó÷™ÜMõÀ´±K«yZâŠøÈŒÂ5n2¼Lв4|—‰ð|Ph)XÆk‹Ü®BÅ^°b3´`êµûBÚÞ‚¶‰b 7¯?o¤,£bn2ý;Ãß6Ìù E$nÅÙÜ6T²Èt¦E÷ÒÙO쇧勵IdZ­3¬hÈxö‘÷'˜†åÌw4˜7¬=Æjó#Õ]=,VÓÁaõ­Ý’ÍáÔݨnEšöÈC!÷ü)$¡ò {¬¼ÅU&’ä¡àCÌlxHÀ<‰â­e”éXn¦Ê^û^ROnˆGwg ‘•¹‰Sˆ{ƒÜS¹>ë!ܬKzqáÓ]=söYl¼—©z÷S^ûÍ -´¯Éž1ÊN17lr8ëÝ]*­cV1‡KW´lV!/­ï§Ös=ßdLú.Ò}Óö!Bl±QÅJ²¹®¤[ƒ€‡)OÎÂl[ä£Yg¯•m’¼¸Žâª0SÌìéSNeCôyg±?\åÞK 9lmei" OAÃQ€Ž l:éÏ£3.…Yßtä7pÅ,öqÜÚÛÚ¶"…Ý•B²•â{Œ¬¤+ã^»ŸÊ˜ÙB›¬î-nòPI„ž_`¿ŽÑÚÞPC‰D]ž%Â)‘še7¥‰o¸„sv0÷3Áˆ‚\ŸtÜÚûaTg–Xß·¹$‘â`ŠoÐJ†½§­#žÞnäí,òßóf¤‘ÒHôÇ^URN+ñoBª¡ú>ÆÅ-Œë{{ív±4-vD=ù³± 'o’1îI·Œ£·2Y‹h‰Œ-)¸î Èßõ-ö(b!±¸xî.ý¡Š…1Ç$\AŒvJ¹ÃdžKË®C¨Ÿ›žÞâÞ±¶ÖúâòIØ?ÏŸn0‡¹ÃŠr÷†»«àìcŽÇCŽIÄlîóÜIq,’]™›z'^BŽ(»ôTQðªëî“´ÊÞÜË‘»¾»´Ÿ‘2H13B`b…@q´gåÇnÍ­è‹FŒ+®zÏ#b×ou‚E‚ÖâÎ9;Wm4Š·âU# Ì€ÆÆ%-± Ó¯)¶Wqp×¶Šíåbº6ðY{@bãµ¼ä`5¨™C‘ÈáK–@ßXÞŽ³Ç[ÚÛ‹»© ¶¸Yã…–(á÷C•^ÔH‘è;™675BIâ |žŠƒë½\ÆV9^[‡Æñ+:Nc/pœÂ *°`ê ÀÕã # Ìvc+ce=äV©rrYÙ-’;¼Œ«B©ÛqÝ(Ä!¸…ÕPu”ž#yY8:Êßaƒ‹'‘Lm­¼¶²À†%[¸¤ ²Ê`o@ŽkÅýæ<¶ÄÖ²¥gíVæpÉ•Š9#—Ù¯íöm®Bò)½mXlrFÐä»Ð «*²ÙWЩKÍÔWFÇ'l–·Á;Š‘ÊdŽTñïFåT°€À¨*HØÓ+7FjÒå±6Ù‹?g¸æŒÜ†hÈC BAÑÑ#È ‚T‚¤ƒŽ/sgxØì’¢^*—G@Dw1‚q6N¼I% ’ ³c]Ö÷-ìë ¸¡I Ñ?r â <.”BAA ‚ GÓýBrE¬o–8r‘'&TØIÐ;±ì“­ ’J$fÎ;Ô;˜ûݶYá~ä3Ä@xœ);„‚ ‚A ŠöKuÍ>Ǧҳý9ÔŸZò±½XáÊœa'@@îDzO ’J$fÐWLN]Q9Ö R”IJ}oŒÇ\ßÞIÛµµ‰æ™ø“ÅÇCÉÐÒ²ùn©Êb,pÏcÖ¹+¸Í¿/vÒš8ÜìÍ{rfæT•WÉM6S%Œ»XÖâÑÖHÊ–òo¶úÙÑä²!Ù1Ò†­(¬xl´Fmoz‚û,’Ì!·ŽÒ&¶šÛíJÑ’&‹²³¸ä÷ dËÙuQ\t ÎZ ¾VI§Þþ{«¬|pˆ.•Ñ!å ¬‘¿Ú†:“AWL¤‚Áè ÒØgÌI•6³%•&•û®WEUBé¾/•Ø<[lºbI‡ùÓÞÁ-“[]¼¤èüò ÅftyG"ü´í’7çÞýÓoŸH^K}>Uþ¸ÊßÛÛ˰'b–ÒG A#0 mÅ–XÆ™A TtúEÆI‡›,–7ǽ³ÛV•vudi&ЉJ0%TŽL…âôþ=r–Y/Ùmwenm¡w½™‡lëa”¾œ),À’UI;Q®˜ü-–.òþêÕg_Ê&¸2\É g[ ÌBø{ xUŠ5Fke-ù[X2W†æÞÒK#H•n–dšExË2•òžÔkÄìpPšáîÓ5i™¹žÝñWþËqOÝM ï9MD6Ñ¿1åÌo\tQÃ{´ðu|Ö¯eu‹Êäoì®áÆK,ily;DȉÞð¥J¹8«l+• Ô˜ïaö/gýí~ÛÛ~ÝÞïòÞ÷ûg½¯O†µâªóý=-æRÓ+Ž‚Ñ¯ÕãŽf¼žn×i;ŒÚFá#¤ŽCñÓ!Óòõõ”X¹ò-ŒÉu²|±-ÝÚ§rÆ;žY¸ÉÁˆo H ZGÔ–~Ë›¹ºŽ{8pÒ¼wM2†÷V%—š„-µ(êGç|ÅqјfÇbl§ŠyãÅÚ 8K\:÷"ÒIU ¬ŠÝ´ä¬ zjº\ô†ìÜ™m$ÝÇcÄ©Ûa"˸ø°í"+±N<™AmŸ5Ÿ^ª¼N£ÈEwfÚßž-³ÅoÊÑçžXϽä±ir¶×ÒZ\ÚMv.aD’4X$኱ý¯{,6¬‘Š‚tVæ{‰®-g™®.Åä«-äÎ/î—׌P¦¸•Ò@s ‚rW$÷Šù2×O"…$Ž.d%HäãjAÓ¸ôv×SKsÕX+k}œ¹ ›9\† ®Ü3s´]%ˆ¾½â¨Ø™‘ëKNfçye’OgH$kˆíû±²L̈GX“"öøñäIØR¡˜…—Oc1ÙI26pI ïo©DžNÒÄŸq.\/iF¹7îŽí+.Ý{‡Šëo0ž¿•­×º{s L&=ÜŒ$Ok˜_ Ä#+ølÝÖG©1ün/’ÒæÓ#ݲ¼H9E5½ÔqúƧ7O¼AUSå¶Hl)Yû\wQ.b9î3<¬EÝįoÂ3¸J…Š-ˆÔø;“–Áp÷>øÐP)JP)JP)JP)JP)JPÿÓ÷úR” R” R” R” R” R” R” R” R”ï?iÛT*›yûHþÚ¡W-îÓŠÿm—Ëut¸Œ–VÖLSÍ…œwæh¤$>Ó¸[j¸í0TÙ.Y~èÉð½cpÍ}m&6 l…´¯öW7¡"H(eie”) ÄNŠB‡÷‚Wn-®:zÒêK©%’s%ÅÕµË7!µì2:F§^’ãó‘È×*­ºè[ «t÷—^Ú—’ÞCtñÁ,‘*J¯8ØhvÓ‹]B j«*ÆÊF7¨27ù; Yq)f—è¯fö‹†YQ›hÑ;~ùB1%uÜ_@?Þ¦»½ÂÚ\KŽ2w»öknŒ…xè?uŠ/o¶Ä«ø:ÊÇwSÛ,ù †ÙŒ%Qõ/<ŒÀŠTX™½ß»]n:Ë#.† >³[4½¸°–é£í,…–(ƒù4ÎÊT O¼${¼ëߥïz}±vØ—’ÏföÖÒ㽉f÷ä ˜L<"âPr$9bIÝÍÒi•»Çåò2û>j+U‚æ[ 0Ñä¨î¦H×o #é¼…Õ´_ò¬z—9ù9‚—)ìSÞöå†?g·‘û’¤~àø·½°>$kc{ªkζ¾¶1Çåºk×°koh÷ÄÆÛÚ!_uYtÊU]‰ ÙÛ(åRºŽË#˜ËâqÐG{mc¾×>F”:«vã1ɽûÄ?. Å‘47ï%—NÚYKc"É<­ißu0!晹I1ГeôW@ \ИÂcV§Tän/ìí­16²‰Úx ›Öf…_¸Bö‰ì¬ª"2'“p‚¼ª¬:ß2*/åÆÚÞ_=¸Éá@-§f6ÑÚÛLÇq**Æ=–”5Ì}aæRâÎöúËëãJ¶DHᓸ©ÜfG*™T¶ÂŽ+Çäô(\X\C=Ô7vþÍß·Üx¶Þèb„Â=ùؘôCAP-ã #‰zÎò…í¡Âòö<­½ŒÓ ‚#Ìa¸bƒ”Ÿn Œl·N|­Îbã=++Œ”"Öý.Þ>ùŒ™¤÷{ð´1Ì¡˜ÍÄ…âVJ¶~˜¶‘"Qut¥2_YHÛF3¿"U$ä¤2(*â¢8ôA@j¦£‹(Eúë0òc쥰´•¤ˆ4Î?ˆ¬åÎ?‹ËÈØt¾ä¶–ö–’[‹5´hâSÀ]+ë©^]…¶Wˆä4%fò3[Ä×Çå‘#rê­¯ 1‘¿Ž†þB¢åñ¹«/f¹æ¥[¹ Ñ$†@„ƒ£ä ‚ $ÕûR<Öaua|Øì’¢Ýª—IÄ`ÜM“¯PI% ’ ³|3Öû1‡µÍØ[ ÊU¹Å4d !¡ èù#È ‚A]EwŒ¾lvEUn‚—ŽDGp€Í7½z€ÊI*H «6Ña…vñ¬9Ü)s¤¯ ð¿râ ”U²Š+š^ÓJÇt—W5ô‰ˆËH>°Ñì\h*ݨ> ’£Á²rTØÖñ9tÄæ3yll9œ5ö.á¤X/mä·‘£ 0WR¤‚7£ò5›¾éÔö6·yq=Žh{2Ý=ÜÉ‚ »šUI*O2ŒÞú‡à …*R§ÆXÜ}y–Ë]ÇÚkŽÝ¬òö!æU›[÷™å”ø?s·°­ÈUÅ)AŸ,Mḗ;•›„³Oj’´,-%8åíò,^RÂî¾I °·{K['옢¸}žÄaȸôK÷ÉÙÞ’”;Þ²ÉKz×™<”ÑÞ^›Éa&%_05»FŒ7…¸<½ÐCÙ2%èø®mn–ë/’žòáí˜ß·dJ‚ {±*ªÆ#ÐrÇÊyIÖ’”ùlJebƒöLö·Ò÷­î`ãÎ'âÈH¬§hî¾òŸ½±¢»?£LT0Áo’ÊÚÛÛ½µ¼¯ F„@Á4GPcHå¢O" i†Ò”±öajñIwy3±w¸¹e.N€UPЍ¤‚I'èX †8„²¹¯§¯ê©t©Š¦8òÙG+»p$×5ÃkÓÿB¾^Å$3r’O¶×!ãáé¯*•1]QÞ#›@ZFJ@ Oýn¿E¤`ÉåøHIdß‘£ø×zSnDQbXw$$ÇÛëa~^”öñö’~ÕÚøy_ÕR©Mº¹˜V_ac¾l[«ˆ_t.bhømŒ«rR8•‘Öȃæ£aú^Ûq ±ÝÝΖ¶æÒÊ)Šq´€•ÜiÅAaöq¹v÷Ÿ-»ÊUF]úÂ{û«ë«Û뛹v žVŒ½ ï‰Õc`€²¬ŠŒ«'0¼@‰`̇DÁ“йÌå]N>æÂE/wVãÌ®IŒÄ„ ) ¼*…ÚE(2ñtZÃya:g²½»+¶½H·àÓ8q+1ír÷û²’s'™ X¦?¡þ®½K¸º“2ò"]*s[])¸~äâç¸Æü kŽÔë)@¥)AÿÔ÷úR” R” R” R” R” R” R” R” R” R” R” R” R” R”ï?iÛT*›yûHþÚ¡W-îÓŠÿm›¼ê‰lº¥ñÒcç\}µ¨–æìð>ô¨(~mÉ’dâ±~ ›uÅVšaM0á?RÛA”’Ñ­n¼ cº¿Ò {Vwˆ– £‡ˉ]ºï`E»ë8,m.î.qH– Y/cGHÕî Œ¯qÕKíx‡BVN ïh) ö:]žÇ+‹›"ç|·*!Ž%YÜ3<ŒÎwÈ‚íÃA@Lè‹®˜»ËC/Öù&žH½—vö¦(ųº4ññ.ÍÊE@¥ù{ )P¤ÖŒ-/×ëŒ`¹Hb‚öpòÀ«,Pý™Ži;QÍÌ fM¨ü沫'½Sl:–Û!˜ŽÂ[®ÔðIqmxÁ;7ŒŠÅ=îZÜ‹¢TTA1¯:jk«énEòjl½Ü‰,÷ *¼ ªex ÇjÀ·(¸.~‹ÇÝÌ·ßÛ[Zñ†Þî$HÆÑ ;±v¨´ßÝ÷‡Œ-Â/ZuFRÁï,1öYt¶²’öã'l–Ó£UÚ‘’òß Ü >].!êèîЛ NFòBÌcŽÈ2BªÜiˆÜƒÀ’À%T¨$F\4Ùë|ÍÅ×;xò¯ ²ÆD†Áå/‚…Ë\yûê&Ó/±¾Ã_I˜“!É%›ÜÛÇmsÎۺܔÄyö¯å•ÇÝ÷|ÖÑh ý a£’PVèÆ¶PäREŒ-£«1œ.ù@ËS¾ fP×8\Ü9±xb¶º·6—‡[˜Â3n4‘X.ɬŠtÚaäÕU~FÛ¥¥Í¤3öíåö;xã(X%•¹SìͶ÷Õ¾Ø|‘1U®66L”—)q-íëÜ—XŒd)UTVˆ%Qy» Ù7Ñ}¢¿kðWíL-Úúó_B¬´û_•ûR³ôU~g iÇ›K°ÃMÎ)£ I €@t$²<‚$A Ø T¥ä9+ –ê;lªC©‰÷PÛ›[ñ¢6 ['ÆôÍŸÃw¯`Èã­2ÖXßB&·”i’=Áy#D Šò\æó§/ÖÖíÚkiI·„ÝÐß× ’ƒYu¦Tƪ1¬0®Þ5…|ê²§ä4CV*ÊÀì2‘ä@ €Eo:[®"š&°Ï\Å Ü1³­Ü…cŽâ5™ WU°ð—@2¦Þ£ÌEã"+€Ci†üƒ°AþŠŠj´Õ4¶Ÿñ—#um£´}žž•ý“턜ݔ$ï¿*¼€Pžc±Å}.¿ï K»Y ²‡ ¾OÁøtAø+Ù:<ÝCÒwRŸÙpòµºòH3Fx1ù ‘È~ÏÖ”Õ–ÔUž-%)Jºîw°k5osc‘{µÇ܉d´”Ã겈×Lï3·ßRX5¬Ö“À·6²ñåop‘ø;û§Ô–Û;bNÉ:½70­V³ÇE›u÷NÇ—¼ÇËzÑ­›ç½x˜ZG/ÆÓ낺û» G—Um¦¬œ0ÅmpAE j#E ª h á_¶ÒÜb­»XØá1¯‘m+0M,|ˆ—jžŠFƒ{»mÕâôLêÎmOsWJåÄW)Ê6Þ½AõÖ¶‰Ë)Œ¥(¥(¥(®sÏ ­¼·Ç !y$‘‚ª($“à<î©àê6½¸‰l°Y™­ÙÂ=Ì–ël±|í'd€;Tað €”¨s ”ŽZ[¢\)%Ѧ2ÃÄr;oË`|ÑÞ…|ý/íijÞäó3;9(#ÈËl±!;€³ï0fù±ÐÐ\O<6¶òÜ\K0D…ä’F ¨ l’O€óº«ºêœ5§`{g´É4§‘º5"ÎÂY•½¾±šëº¤I ›Ä½ŽKÄÊÇ‘´Ü´6­ PC¹“$–÷-iii,êà[¤·-Ⱥ]—a —з¡älêÏRIyßâ±PZó’ œ’ºø:Ò˜:üáóóéW ‡%ìè²ã.ä/qÙeV‹q§";­·†€:m0÷w°+çêe²¸–+ì>fV)c²k¥˜凳÷ Cö ßàêò”á¾·ŸÙÂÉÂKˆŒÑÃ*˜ä(8ìðm0×5cÁ`t‚xn­â¸·–9 •Ç$l]HØ çuÒªò]5ÌÜ-ÆS ¾P"Éuj’°]“ X­’uøš JU]– jH¶wy%2H,‹ày |U„Ãuoż±Í¨9#`ÊêFÁx ; éJRJRJRJRJRJRJRJRJRJR‚=çí#ûj…So?iÛT`ªYˆ ’~Ëw´â¿ÛE¼½íjñ‰$a÷Ï…_‰?ÿÚ‘ ‘Éœ(.ª}?G®ªs<‘;Q‰•äÃ|‡ù«æ+K†¶»M L³l™ÔŸ_Ñ6­ìDLâ|õ—ß8®­¬Äf"X̦1"™ÙP|Ñ\{òH¨é$1Fä2 —ß§ŸôT1a4ÑF{}¸]G&Ùiy$ùñçøkâSu{íR@ŒÁ”Fœ˜Ç5#翟Ë×Óv¢ÅÒ¨ò×Ï I¹V5„ÑH­å’FŒ”éFØ“~šùl‚5çZ®–—ªÐ–¸¸¶æ$#(Ðõò~'_ª«û}Û‹{aåv¡€<€HÇ…†É>~^*CãÜ—’΃›Ž†m…x>=6|þ¿^mÙˆÅZg_—™Mw'X×ïþ,ÖX̦!"Ù@Ã`|›»eåÊâ!Äñm¸ð~GõÕPm,æ2ÚÉ*#xfÛ4÷ÇǯãºäøÙne ,dw¦-+X×î¡Ñó¿ŸîªÓjÖÖ&­>þ^M·—1˜§ïþù®#š)Õ$Fd:`¬ Sø×ë\C«ÍÈßuY€'øWcb¹·‘¹Ú;371¸Àêøõòóãæ·µ¹:Éfè–f¸ƒ·óÁ”hø>ZùTͪbg]=±÷÷ )»TÄiþ¬Öhšc‘ Š6P0ØÁúkå¯-W—+˜GŶãÁùÇÁýUÎÊc5¤“!Œ[ÆÞ¶Í#}â|Ÿ¿ŽëŒ˜Énf4Dwç/3X×î¡Ñó½#ðùUâÕ¼âjûÿžIÞÜÙÌS÷ÿ|×QÍ®ë¨ì‡L*•uY‰·–¦€DÒIÈ ‚@ô ãàµú|˜¬ë¦)ªb%Ñj©ª˜™Œû_•ûUjý ¥JJƒ˜µÇ^aî¡Ëˆ¾¯í–¥~ о÷>[Jë`ARºY^½Äç38m†š"¤þȳsÚÐèp2ïÜ_$°âyè)Ð,yO5ç0†Ie¶0‚iãíÉ$šÎ¿šOèù•BJ/Ë5r¿kÌ4¼æ6çvTK0#Á+ ñ­‘¢Üw±¡ð¯••%dÕÑ€ee;B a1‡4ÄÄêúf­?Ñ–Xãú¶ë,œm²‘w¡S²=¢1¦ühÂ|DGÓ^r„Ô[©ç´ídm9{]„‚ê+È–_ÍϨÚúrÞ¼TÓ8”Ñ8—ô­*.7!m–ÆÛd,äY-î#FÊÀìóŠ•[:çý¥«ùîûþ–åÿïóÿ®Õý ?í-_ÏwàŽ­Ë‚4}¾õÍW÷#½'5ýúQô¾VÿÖX¸ìîå†;›Èb™½Ù·z u¿MìhÕækúô Ëá?é®û¡ûE©ž {†R7—-0E,}ßAéàW4Åpó·}Åÿy«HÈCu±°cQ¯áâ*mŘoz/ù+ðýÇ1—\^Ùˆ§Á^¨¨¡QB¨ôhWí}227Æ¡Í{`„<Ûðô¨Z5à’Ìmˆæj÷à0ù?º#ýYä˜ûíãåðÎ"Žm/K»H׌ìI÷=¾­g:Sÿ{þóÿÚ­uÛìÃŽ÷nJR•vOÿÖ÷úR¡ßä¡Ç½œr,-åÀ·†4lÜY‰Ù ¨ŽÇgÑH$/¯bÇÙÉu2Nñ¦¶ æs²„@Xúü_J¯±¸Îß^G<ÖPc,{‚r&¹—ÁJ7n-¿^@þañS1öMko ]KÖ@[Ç Åè…ciÊäè93¾ƒ‘ÕL ‡g‹´±H$’G#šâWžP®Á˜w— •_þjü†¦R” R” ŧYCi–êéÔŽ—Çæ0½g޼2ßYZ%¼1Ã#ˆÏn5Eå!]ûÅKÝ ­7M›·èÜô]41L1¼ï0Pá/$/«uˆJ¢hÇoíIY‰àxh®¹ìÂn¡Æ[å:IäóXÙÄ£v×yBðG<—JÌ æšòî¯%×x›<S#mߺk+GºŽ?g•ʯçDÅ5${+¹’¨ebtA2!Çæ,3×òY‹±ÈÝÇu4ÓHýÈxÅL‹]6ÄCL]t_î·6Në¢z–éïY-&{Œ=î:K¹ò·d™SŒ¢Œ¤ ´~cŒèñ¾Ú]uF&DZí3Ov%·i)ìFÞ6—ìÃy“ˆ÷[÷-ªûήˆuV bÐJ·Ws[ܼÁ÷!‘Ïdñ 'N.CJFÛݯÉôæS,2wøŽœÉ]\ZGlâú2écÂIX4`¡3x”7.Ð>ï-'Eé¬ôYLbÁqL}Žbã"dpï,Ë?|²ñW¾Tyn^ÝãÁƒA’êf&á`¼žEr‚G)’,(IåeR"O ï9Qî·Ÿt램"ÌdóVQÛÏbîų<‘:‰7? Y@õb4 ð½wG×]3™ê+{«{c’ ‹'¶HäÈÏf¶ò0`d"%a8`Ê8>€íøß6«L?1išËÝ^‹ío¥K‘2<Ž$ìC/"ª©‰´tKsÜã¦÷™¼Åžs¨#Ž/mqø¨ï­¬áÄóHýÐ#çÉóÖ“~øýϽWÔMkÓ÷Ù{+ÞŸÊcàÆ\ÞG‘µ‰»m,EuA1Ø*²ûáÏl>ý¥æ3¨9Ô¶ÆßÚñQÚØ\4ÌΓÇÝegCP¼¦?ûƒÁå¡W—é|öRß6Ëo†·¼¾ÆMy ™Ñoš@гL;d¡U¸¦äý°¯0<¼²½ÌZu œµÍßµZMs¶–¯oÛíjÂÆö,…œwP¤éïBx$yG‡§Äyõô©þÉ®S»k,v÷è…aº0¬…eb¤%¢†‚@ðT€@L¥WârYE:KbòÒ_gº€71œUýÖÐä¥]¦ ÛQa@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)AÂéKD‚O/€¨m ²•h˜‚4A_Z³¥gU½©ÎX×f+œÊ­-Ìh!*£Ð*èWßjOÜ7ê«Uw9ã*õxŽõwnOÜ7ꯉ,’f -²»­´{«JTŽbIèôÏlV‹ûVâ=úñMnºˆß÷ úªm*fÞg3)‹BGýÉýUõÁ¿rUJ¥7p¶êòÞÚÛÞ[YÍs wW\½ž—ˆÛqSå´Å+Ÿ:r©Â])\ùS•0>¤%£‘ÑÁVVPEd2¿F=/’•î"³|mË¿7›ý’ÇæÊ=ÆóçÊŸ;ùëyS0Ï.µ²ÌÀ:>4ðGÈÖ>òwÆH"ËZÜâå#|ob1ÃN}Ó½B}ÈëúSsž8nahn"ŽX›ï$ŠOÇÈ5Y¢%I¢%çŸD9röŸ•—þOKj¤ö$ÙÐ%pà|‡òߥVcÐý;†Î¦_b,.$FKg)Šú$þ睊ð ù JÉõE½­Óãñðœ–QtÖv66­3öjv>ÈÙUn'SÂ5^#¹a—¹µ´ÄÜÍ{‘n‹]¼ˆ‚|Ûíw²5°FõàúVo5Äæ’9ï²¢ý_‘…Ë+#vÂò}÷žM*lòjvN¾"Žæy ÆVå/n•Ãi#1Eë¸Ð³p:fÛXò`Oª°ïp÷8û¸qÒû]Ì'&Þ0ÊÓ©-¬ž…–N.HÑ~Ú†%}ÚÂnDËMÔá•êÅÃ#´m-ªúNƒk¯mûŸP<ü}7X,'ý5Áÿt ÿhµý—†3´s"µ$èÓT3t7M_f¬ò°Û½Õ´Ë0KfŽÊA‚5îþn½NüÔÅØ˜Ä«UGÿ×õuÿ¤?Ú/úR­eœDʲ<×àHØØü6?†ª„1\g/aš5’)!âèãa °Et\l¸ÝŒsò‹ï-¬Îx¯ƒ¥FòQwÇÀÚ€º äšã…®kd9dn.Ú+¸'³XáXÑ£f $= ë@‚!? ¹zÙ¡­UÃØI¢vl¢=å¬åDºº4b‚”¥ 'JïÞûU£¬çJïÞûUw}gŒ³’òþî KXõÎiä¢ì€6ÇÀÙ ~šê·Ù‡ÿÔ”ŠU=Tá²—‘Ûco=¿žÇ~Î'ž U¦@cVÐû¬Àù_Fæ Ùý¢Þ/«.ÂJò«ËÊ.0…'‹7¿²[^ Ÿ>ðZ»$ʧK‰:Êkùãݬ8øá³~CÝw‘ÌãCÏ‘·¯ËÇ«T~}auîv0xÍyïw¦¾åûÞßuóåÈúk‰ÞÅ„8é~±·È]]÷n"´6åHù1Vw]ƒ"ìªû¼Êè ‚Fè,)JP)JP*ù(\¬%%–Þ>ã'0< ìxß‘¯—Ä|êmSÜZ]-ÆLÇqn¢UR ¥uçã²ðoÎüV¶©¦gó}êÆõUÓ³÷¤üÓ!X€Ñ‡+˜Ì€q,6'Ó3]ö°‰eŠ9eUawòùÿªaauŽm£6ä+ Ó’vOŸOŽÿú¶±¼ŽæÙÒÙ¢ÒÆ—FVG £M vãôkiµo¯ÅÏîæ3Lû¾þýË©®`·ãÞš8¹zs`»ýtö˜;ýŽô}ïê|‡/MúV43ß%Ôö*Ë%¹‰¡.¬ƒì?/ŸÂ¹ý_ußíö½ß¬=«¹Èqã¯O]ïáéT‹TcYÿMë™Ò=“÷åÞµ¶Œ[¨H;Ñ€ÙýCÍDÈä® ŽÅñÖk~.nÒã)Qg|ä䇺:b ë@ò*¦°º÷¤ö6õ€¸ûɲž|zú—ãVXÈ&·kÑ,eCܼˆÛ2Ÿà?…EËtS‰M«×*«S{î<¶6l¤Ø¸²…9Ëh³)•Ç–Mìy|‘ñ:I–ÆÃ”‡.BÑ2'8­eºùò©½‘î·>åYþŸ°ÈAÔw’ÉŒ’ÎÁ^ë·í/ ¾ô“‡ånÉï„“M$‹'£ÂøSU}SŽê 2Ò5–>ú{S³¼X{C2Å$,Æs)YLßfÀq!x¬Cz°t´—½MmoÔXì4;™î. &9Óv‡±$ÉÍ7Ën#<|k@ÜÏWX~P¶5$­b´¹žæü\ÆcàxÕâ`Õ”J¹kC^» : æ7-ÌÛµÆ/!i}¹F’Öe•Ch¤èƒ¯ÄW8s¸{‰nb‡+c$–²¬—LR3pT`ºÅ½Ð’|zÔ>—ƒ! •Ëäb‘%šàºµÂÂ.]x"î~ÏÙ—Ú þ`Œ Öûtz8GéØ8îñ0ÙÙdÚ ^2·*†ìJÛ· 'fO~^@†‡¢IÔ¸qpå%ÍãS3ðŠí®Díç¾ôOºÞø•H“-‡).\…¢d&NqZ4Ê%uóåS{#Ýo |ʱscº€_]åàÇßZûuÛÊc³ö6¿…{6ñ…-1hDl`v`¬XýÉ€çѬÆ3#Ór9í%wšh Væ ˆ–Ó³ n]8«z=²\q[6Rl\Y GÈBœå´Y”Ê‹ãË&ö¼¾HøL¬>¦Þ˨yÜ⯤’,…Ýê_>M¢‰žR½¸;‡í8ÍÄî5¶Äë–âJRJW9ähmå•!’wD,±FT3>èä@Ùôò@ù‘AÍû¿Xîÿgµ'.<;|¶šå¿–¹k^î¹róƤU^#5«Ýß_4o½uy»d²DªºH‘ˆÙEò|ëlîÁWŸi@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥+ð ’@É&‚³©0õMd°ÓöÂ^[¼AÞ1 ˆ÷_‰õ*Úaäyȯ¬m½®eжy$ŠÊÞ;hËXª(QÈ€ô>¸Ýd{¬V"Dcãûª‹Þük¢›:Ê2´k¶oŽ¿‚¾{õ[ÞüiÞükMÊ2²ïÓ¿U½ïÆïÆ›£+.ý;õ[ÞüiÞüiº2²ïÓ¿U½ïÆïÆ›£+.ý;õ[ÞüiÞüiº2ÿÐöþý;õ[ÞüiÞük³t®V]úwê·½øÓ½øÓteeß®S®¬ª¯5 ½øÓ½øÔMˆª1$NrZ€Ï$lã½lk_úEBaÛ•Éä6KA;óùºø!õøT]ý!t«ÜËÔxÖDÖÄ7 +ù:ð¨K_€ükî×®:s0=Ÿ’¶½»hñ[Á"‰dڱ⡈ô§`WÇ-\W:.;–Ô]Ǻ·/x1%´ßãó×Ìk~kѸ ·÷‘wåÄF]Cú~w\}=â7â¾ ’ÞþÑ.±×0\ÚÈí$ ‡Ôºñ½xó½øø×Vp#b¡Q¼òWóóãç{ßé5ÉÂum¤ðO†Ì­çµÇw±(éÚ!Ë8ž\¼¼kÎÇ‘¯3X{ÊwùºÕeæY…ÌWby!rÉ…O*Fѵ°tX|ˆb=*M†Fþó"o+åÆ*›`†ÕJ´¢D^`‚dÖÙ—|xi¶DÞ#<]¢x¬3}Y1ןë ËV›#<7X6¸·•%†UGŽHØ2º’ ñ¬Ý²»ä³€˜‘È*–‚†}uOÑ: ŸLeÑѦ"‰™æù¯›nóRÏ*?Ú½Ö»ž6êÜ‚Žãj§@¡Vd$UŒ}•›#ks{‘ƽM\c^ÉåGä :—î(ÂòN>öʵÁ}̵Õìláž5·ƒ¶ EHXß‘rľKÃdl©µßR.tŽêUØnš\e¼¢ã!wwq3ÆòIÌÄ ¡ä✷à–,gU¬6v÷—7ÚAÕ×h™#åâ4¼˜ym~•W> #5IJ§Vf`GrËqY•@OÝ 'CÓÉ'æMZCkÛöv’âyæ†#‘ß]ÍñÛ2®±*<ññ²"·ˆÃšfgYH¥SÍÓVÙÛZ½ÆTGoËLµÒ9ävy83þ‰× Ð®–}9ˆ±·º†;äiÂéî žK•ÑJòÒ 1:BÒ³ÿ—}ý•àÿÊ0ÿ:­'¶ïn¸ûAÛ­«Æ!^- ‚25¢€3¾ƒ‘ùÔÊí}n½À²w)R24nÜt.ÈðêÇ~Šy5_}ÔøÜmä–×bú.ÞŒ“œ}Áòi‚v€|±m.ŽÈÑ«ŠPG±¿³ÉÙÇyawݬ›á4 ´H:aàè‚?EHªÿ©1Ã1õ´vý«ãûd°»Gß÷xŽèR¼G…æÃT·´ÈÛ{Z{T1óö—»·S4Ûûºhø"hþðìè|°¥QÏÈYÜKÇM䤂7;º´xe·¿ ˜”ž:ÚˆÉÞÂóðM¤7Öóû8Y8Iqš8eS…ž ¦æ ìx,Ñ ‘JRJRƒœó-µ¼³¸¤h]„q³±o¨%à'áTóuUŒ:­á»6Éo»i9x2†ŠìoGÉÞ‡’Hš¸že¶·–w °Ž6v øU±ü$ü+ÆøƒöOb¾ö¿Éÿbö_c—½Þìö¸öøòûÿk^öøù ØeóøX-¥¹IÝn.á´NÌEôò¸E,}v|’GÈl Éæ[kygq!Hлãgbß…PKÀO³}av$é«+ˆ­¯¦Y2ᲚIâ9X´j¥—HŒNÀò5ê@­×±AíÒs؈Lü wÚž^@óotû«¶ôñï „Eoå°î—g™ORLG‘…‚1ò;k¢(9õ~ǦpÓå2-"ÛŒǂïd)`»ôµÄr *»ÛfXß[ä¬ã»´“»o&Ìr 8ŽK¿U:Øaá5öÃÔém¯m;öíÝ„¬Ñ²0Øxœ©:aµg‡ª¶ÁÑÙ™ Û!H"Ž$.ÎU(,ÌY‰bI?I éPòXœnfÝmò˜ûKèìwP¬ªDloDþ&¦RJRJ5õ¼ÐNr[Ä&’”É CËG‚íŽø0J6j¾û#™[É-q¸ï j¼¼H q¡°¥’rÙÖš5ϦÂâ¡ä²ØÜ5ºÜe2–03„Y.¦X”¶‰Ð,@Þ:ü G‚×/=¼MŽÞu¸°ˆqíëö–iÞÝDdøÐO5a +C!ÙýùÎÙ‹,IÖÏè€ÐPUÚåo2Ýÿa°žÒß´Ý›ËøJs“Ñu+'yrçÛ>A¹ caŠâ+¹K‹Ä·þÓ1ŠïdèªX€[ˆâ»ðªÊP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*.EÚ; ïg@Ÿ5*¾&ˆM Æu¦ò7¯Æ­LÄU#-ºn»Ím$q¢?Ï_³^œLJÿÑõ=ÓuÓ¶iÛ5êæsÝ`>’ñÖ3ô¼óÙ[K4™ÛKw‘âVfˆ—&2Hò¤þo¥zlÖkªzc!Ô3ãL+kHl.â½E{6•šT-­‘"ûº>šßZ¥zÓ‚Ûü_Mã¾––Þ| ³Ø¶ ˜··Æ×¹ß#Ÿn4m r×á¿5«è+\—O4Á’¶´†Âî+ÔW³iY¥BÚÙ/»£é­øõ¨˜Òt¿KöÑÍôw‘¸f˜<¾&uCÊXÁä ñÃ:øj·{¬÷VtÆCªzlá›%ml³*‹©E›9vVVppSàòð}|lØ®?2×Xé¥ËBï¶C Ÿºä4šäÌÑñõðNÿ ´v¦qÈd:‹§-—©:U±áþ¼öÿhžù¹w%¶EÜÆGQ­Æ€Ì*…]ŠÚäl×#dÖ¯=Ì ÌŒ^ÚcéX6ƒ/´u£¢|ŠÊŠê™r7w2u»Çã:[cQF<ŽBÌÈ'®‰-ä’Mõî#;?ÖžÉÔ>Ëí=¯bý„ì|uÏÔý§?>¿w~*)ïÐdzjÞÎËéo;mibøxÖÂ>6JšŽðþˆP¾âá@O&>![•ìïu2ÁøÜÍïM*€ÆÖ7ÚhøäHâ üIm0F •½Žbç*š¸´6v×0ÚðŽÒ?QÆ2ÍÈó÷‰f;ð‡¬ÖéŒuôÍš±°Ê_ED÷wq–äèƒÄIÐð7JtŒ ÷Ñ)ÿðÇÿ÷¿Û=k®m-o;>Õm ý™ÑwP7Œ»ôa¿yªÎŽéXúG¦àÄG*Nѳ¼“¬"3+3²6|¥ÞÏ…}Û5j4¦"DKkK[>÷²ÛCzC4½¤ ÍÏ«6½XëÉ>k¾ë§lÓ¶jÙð²2©Õt’U•`«uÇÓø?Ì?ݪüíšã(f‘-£ó<Þêðýñ× î¬/[·]9­4Õ1:&á1Âö Ëó’È¡š$fdFÈÙÑm¯A½y´5Ζ xáRJÆ¡A>ºUÒ¸)¦)àÒª¦®(Òc¬åYÃ[F;îb£‰‘€#É:Uù>Þ8Ò$ * ôU¾©LB¹î)JT…)J)J)J)J)J)J »ÎœÄ_[ÚÃ%Œq‹DájöäÁ%²è"xÈhÁÇŠYà Ç[ÝEgw’G¸N=Ù¯¥ºhÎŽ™;ìà½úhèlU¥(#Í Áö‡·ºá#Ä%–0ñÆã—¿¡Å›{½k‰Ù4þÍÖûÿZàî8ùìýY4=ÏÞ÷;ïÃ~œ¸¶½xŸJÐR‚¾âlÂûg³XØÉDzw/;»ûýÍD{zøkžþæôK›Ùà·¹–N†æR‚®ö ô‰°Éc`pò3ãÞPÊ[Ü —D/‚|ò>@_JçkcnÿÖ9¸”M^Áb àÇóÏqåäÃ^ï¢ù<ƒxÕÅ(#ÃkÛöv’âyæ†#‘ß]ÍñÛ2®±*<ññ²"©ÿ!zM¼ËÓx©ä>Zk‹D–IÅÜv>¥˜’O’I­(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(?ÿÒ÷úR” R” R” R”æ‚9Ô+OB=EVKfÐŽOÄ.ô?3¡ú}?][Ò¯Mɧ…7bгkhÉ%ABH'ðìøôó³³ë\;7 ­¬r€¤³)âIóà)Øùzµi‘„>Å;(Ëoº.* J7¯¾îüü tŒG*ÕÐú2A©Þ˜AìS±V=ªv©½0®ìS±V=ªv©½0®ìS±V=ªv©½0®ìS±V=ªv©½0®ìS±V=ªv©½0®ìS±RåšÚ 4ñFÄoNà~šŽ/à“ú9®}þà 펆¿OƛӎÅ~4!T³ ’}ud§Uû8-A7&î2ü´‡ùÍunYdº-u(üé~èñ£¥ô¢oV'vñŠXF’:iœéü¾gô|ÅZØc"±/ f–y>ü­êò‡òTêVUW5qIJRª¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(?ÿÓ÷úR” R” R” R” R” R” R” R” R” R” R” ã-¥´îkx¤`4  '_¦»R‚3YFÌ\I:¹;LÚø ×èÖ«óÙ%ÿ·Ü?æÔªPFhï ’·߀`$ü<ëóµ}ÿi·ÿoçÔªPV2惧W~  Á_šÎý;ÿó«JPEí_ÚmÿÅÛùõÎ[l„ŠßEÞù%¿ŸàòƧR‚#YJêTßÜèõ…®T[´©žâuø÷'s¿;ò×ùª}(8Gei ‚H­aGŒ±€Gé®ô¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ÿÔ÷úR” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R” R”ÿÕ÷úR” R” R” R” R” R” R” R” R” R”ÿÙprocmail-lib-2009.1202/doc/article/pic/spf-system.png000066400000000000000000000422021130547513300221700ustar00rootroot00000000000000‰PNG  IHDRèÉò/SgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEݽ¤Í¤LLLàűޱaÕ®zÛ¹ËóèqqAУµâµMÒ¦-Ί¬Š/Ξ Ì™Ì›¡¶ìÛ¾ïàtÙ¶ Í›ÆøÆŠßÂ…Þ¿¡É¡™ãʳëÙÌôéj×±žäÍayaEѤXÔª åÎÃðãRÓ¨ÀðÀޱŽJÑ¥:Ï¡¸ìÜd}dÅñäªÕªvvv»é»´oØ´mmm“áÇ^Õ­+Íj„j$Íœ4Ο›Á›UUUÊýÊo‹o¾î¾Ìš~ž~¹ç¹h‚h{™{t‘t_v_…¦…žÆž‡©‡–¼–y—yeeÂò½í½m‰m·å·ÄõÄÌ̲™™åååÌ™êѺحžþÿþê÷Ö€€€???ÌÌÿÍÍÿÍÿÍÎÿÎûÿûÏÿÏýÿýüÿü™fÿfÌÿ33Ìöÿöóÿóéÿéñÿñ÷ÿ÷ÕÕÿÝÿÝ××ÿøÿøÐÿÐÐÐÿòÿòõÿõáÿáìÿìÓÓÿÚÚÿâÿâÛÿÛÝÝÿëÿëÜÿÜÔÿÔæÿæÑÿÑïÿïÑÑÿÓÿÓààÿäÿäÙÿÙÖÿÖÑõìããÿúÿúÏÏÿÕÿÕææÿééÿëëÿîîÿññÿßÿßîÿîôÿôÒÿÒùÿùóóÿõõÿØÿØ÷÷ÿ²²²çÿçùùÿúúÿÏõëûûÿÎôêeeLüüÿÐõëÐõìÍôêýýÿÆñåÀïá®éÖ===ÈúÈÌšÒöíÇòåÏôë̙̙̙ÌóéÈòçÇòæàÄÉòç½îàVÓª»íÞµëÚÉóç7Ï ÈòægÖ°ºí݇ÞÀÌš=Ï¡lسܼ[Ô¬°ê×333^^^¢æÏGÑ¥:::rÙµPÒ¨¬éÕ¼îßßêèÔwÚ¸±êØÄñãcÖ¯›äË}Û»¦çÒ¨çÓªèÓþþÿ–âÈ»îÞ?ТÁðâl‡l(Íœ¤æÐ¦çÑòüÝÃôÙ™™ÿÖ›„åÓ¿ss‰‰‰v”v‡‡‡˜¾˜¼ë¼‘‘‘‚‚‚¨Ò¨“·“¬Ø¬¯Ú¯œÃœÁñÁ•º•®Ù®¦Ð¦¬×¬|›|b{bÌÿÌÿÿÿ…H@'AIDATxÚbø? FÁ Ä0£`0€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€M£`P€Ù òß?òäŸ?þQî܃ÂÇÄ0‚œ(²bä’!0sþ¡Mø ZùŠbÃàÊÝdfuDzFILÈI³àÃg׿¡” á¾  €Cxþ£0T`zÐ"¦j´á³Œ‡Ð;ÿ Æ„D-@Ã!A"ô`¤?D™‰-:©“ éþ ë @#/AþMƒÐðJÿ AÒ;=üÞ  3fŒÂÀÿút¤¶¸˜È …–ããƒtN^EÉx —IÓ¹o0AòK0£Pl¹D˜âp’8L ­˜7¦IÍ‹Á ¿Ž-€m‚ü‡ è) _Ÿ˜”‰¿˜VþCS‚œœðº%êQ¶éÕÔ<@ ‘ Oˆx$Ö‰ê&Èÿ¸ë}Êä?¤Q‚Á’ ÿÿ£w’ !• ÿýGn¤ÿÿÞã&¢ÝOa‚ÄAÔIÿi˜ Q‡uHKtO‘4„ä¿ÿ°`F3ܺIKÈ \=\cLd´!1ÇN±ŽnQž ÿcmÿÇÕ†D Vú¦H€ ³ôû‡9ôL͉§Sƒ;Åaº˜È‰,€UŽœ‰mޝá¸B_ðÑÐ`‡Ä_˜kɨš QÇ#1$ú!cMxÿ0¦C‹5¬r$ ûàÛÄŽø÷û°Š4öö @ ö‰YâìçÓ©!˜ ÑÇa°631ä?"‡–þc›ÂÞœÃ2"„ÖšÆã}|9»á8CÞ  €í]ìí ¬¡ƒ%戼À¶{©‰6ŸˆÕp¬S‡ÿÿá˜kBµ =×`q Žiéÿµ1žiœÞÄ ôìÔÐ Þ€1ˆ3A¢´’þá\€Ýj ½èrÈ+.°·ð5ÿQ À®GMZ8’ù?ŒiLᇹ svÃ1™x@£ rTÙÿÈßðNw@£ ’ˆ¨@‰?èh4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ah4AŽ‚Ahx%HRÎ ÁvØ(p@ Ã*âB“Á*<š àOd 1BÉèI×q¦ÊÄ0XS"ž4J|úBQFtZM“ˆaÐ%FâU‘’nHLd£Ir @1 ªÔHí¤KAúM’ˆŽÉ oƒÔðöik4I z¥Bü=c’Ó ]ËhФ? š&E¢UÖ®þh¡7 ¥Fšôfk/kPÃà‰ÂÁ÷ˆKÂFÓ%}@1P;9¯àù7ZXÒÃhrâ…ø0Ä0šG}9˜@1ŒFÔ¨O j%ÈI£I’v €FÓã¨w ZEÐ?¬÷¬Ó"2ÿ‘Ôý@\†>š"# Ú% 4]빸ÓÌ?1S$,§ ‘ âm[¨†1«AÅ ú%ÈÿtNÿ‡b‚D8ìR¾Âãÿð§\Þü‡—ÿo  €hûÿjNHV‡Þ?¤ ,„´¶^$@ Ò}ÏHÅL/Âhä$÷Cí /!åû?„+ÿ‘éŠdyf@Óã€Ìš9 ÿÿé‰MŽM´T°fö¾5$B±•)»ÔÓ„ˆÒ觤L‰…ð»ˆG† õjP¾ÃØžF_š¿™<ýM¥sdE¾ŠùXðöÆ\t“%óeŒÂÀÿºuR[*“'H œçÀ½ÝÛM˜¡žA´ðƒ’¤É7„¬=iB~ºf§º ê¤è¦ßöÕáõO¼¨ÿÝÊîFÏ@ ”¥D<Ùe¡ã?´"óZ‘÷¹}ü9"O(A"úÖ4N4k£ z#©e‰;;"5Iä”´ƒ’bÿcšñ5”Ð**äÖ-õ;x-“@úÿG•RãM¸’°L £Å¹Ÿlp”À-gv%?€ä-˜7RÌÓ€Òòú°%GÈ‹P/%ëz—:¦†æiLh7ƒ@†öÿ=;Éœ-ˆ¨S E)SžBãN‡sHz– ‡“íh`H”Àiø…©‚—èÞå]×0¾ë‘p—Œa±YN"¶<ã’Z–^'‹©UâÇ¡˜ˆa¸ã‡Fê))i ÿІ!a2ôñ ¤yX¥GƒÔ,GуÜKA h ²÷¤^ JËÕ&Ôn) €or„ uSøÿÿh]b †Á›É¡í"Zt³ÿ pjüG¿z~ €ÈÈ’£`0Êåð‰€bMC4AS@ £á?š" Ú'È””L  È&Òê¸îßh‚¼ €èPBB“*J…pä´‰ÕZ"ÚH(côê™&Hª€¼Ö= ‚pÇñW餩ƒ¥"…$>"D“Zü_¬âw8DÁ!HüL7ÝÇo¸ ~ÈÅ@:céÌSº<µÿu¹~Ó­Õ©›Ð…!LqBŽ7J¤xá/îˆ @ n¨A)å"Æ xq@‹3öðqÄOì„-,¡Mü{ŠAÑ¡—½„DabVÞˆ ”õ(°%-ÿÿ¡.MC[z‚±^ y…õ$Õ Mp@ ´Ü =¦ÀeÿaN°" `[´†eÇÌÕDØëÿ~<Úh‚„€"}¦æµd F¿IöÆ\ì,H)í?Ö‰Xüˆ1£‹î­—G$‹+H: 2CI ¢{ókúÖ Ñš™è‹¬ÿýC_Bƒ3!‘<-ô4AR?AYËÏþý#¥%†-A¦ÀŒ„J WÙ°­Ø$Úb5hiˆPöÿ?ŽÕçÿþQ¡ êäÈh‚„€"w.ñ÷»@K=L ž aiô?j•ý± i}Ù¤ul˜šÿ¨¤EøÝÿÿQ!¥QwÀg4AÂ@1™1Sæð“ûGßâq4A"€b ,9O@ðæj[8š á €hQ€ ßB’F5Áh‚„€MD{’†Í’Ñ Ø·ƒ€A ÃÝÓÎÐ \ý¯/Am„"öЛ ‰ (ß!íqå–?ÏÈ £ÏâI+)œ^\™9HH@2€$‚Ôñ’¤v ¤Ò\£z†ÑR©¢zä~ù"öåéŠìÛ! FáSÚÌÞÿOÿm 3h0˜d`|<0ìƒ<­ùêÃ6AÚ£¬Ÿ ‘<’($ûB’A…$ƒlR"Y é í‘Hr!Mcˆ¤¤5.<ö!€F$¾q-zY†¨°ÿ«l`) ®²ÿ!UÙàôtÓ$ n»˜ AT˿ӀT>‚KH” *+û÷¯éß?P‚ü)!ÿý%È*û_f‚hzÄ‘ ÿ%àLðôˆ¹9™@C« Ixd›Žc?4L 2=ABÚÿ€%ä?x ùRB“ã´¸JHP• L‘Mÿ@é¹Ê¥ß þÕaM ¤W‚WÜ ò¸ IVÉÄðH¥H¤íÆÃ(=UBÂä?`•TB‚ä4B ² ’ A‘ %ä¿ `1ŒùÔ©•ÿp—ÿp$ÈÕ0DæÔá@’Ã?ABÛØdí?p‚DjCþ#>A¢vj ²[ ù¯¬ ÂhLJ psÆ6ƒ0œ9£°ð)üc£¤"E(@²(Oö_ããU*_ÑÇkBæW€âô8Ü$@1 é(ñÅãðKÄ0¤£dÄÃ/AÃŽ’_<¿ @ C:JF|ñ8ü$@1 é(MŽÃ.AÃÐ-‡rduÒãpKÄ0¤‹ˆ! ‰N”0¿cMÃ-AÃÐ-‡C‚$&Qâ+‡_‚ †¡[<—‰?Qâ/‡_‚ †!œ‡x§†¨4I x~  €¦té z˜ç$J‚ÅãðKDÛ›¼°numУfJ܉’pñ8ìÒã€b YZÄ)2ôÿòþÿó [tÿcK”ÄóçÏf  €èy=1Tbp5èÿ‘ÈKÿ1NËÅâ´Pñ'¢xœ0þp+"ˆú ò!¹ÁÒ ')¥‘›*‘ßý‡œ ž=×(‰+‡_ @ ôLÙAР';y‘¬ o‚Ä–&$áâqø%H€€r`ô”7 IÒt:>j‚{˜&QÂ)Xˆ+‡_‚ lCÒ¿AO½Ëmˆ¯ê1HÔ6$¾LIDñ8ü$@ Ž^6ôÔ¿h‰(ÿ¡“ÿ±wì@^š)ñÃ/AЀŒCÒ»AO»[¿šü)7âKЈ‘) Ã/AЀÌÔгAOû+è\޵qˆ ¦IâŠÇá— h€¦éÓ §×}ˆ˜iãègãM¨i’¸âqø%H€°Ió=Ý#á4‰' °&J< ­x~  €2AÒ°AOçÄHr$ˆ+‡_‚ Á ©Ü ÿ70©‘$ËÉKX’ã°K4$Uô™Ip9 r>Öô8Ü$@ ’Iý`HĹ„Œ‰=9» @ƒ'ARØ <‰«ƒþQ˜ çãJÃ-AÐàJ4èWjÄH“ÿHM‘ÄÃ/AÐIC´AK“èÙ2öOdÌÇ“‡[‚ !’ ‡rƒ~w;’|l+€ˆ0À—‡]‚ ªÿh” ‡|ƒ=t‡»°”ÄÃ/A•ŠL&õä0hУçW´¡,%qÅãðKD…ù/—œ9ìô“êXÆ»Ð%qÅãðK4%älÐc¬ÃÃ1€¾`rv  €  9ô8÷¦ã.(‰+‡_‚ <¹b7èñÏVùC–à“‡]‚ öÉ zü³U¬J\zn  €ÈOAäÂ@$„þ@á˜=^]ÑÉqØ%H€¢ „¤JŠD¤Ê€ AÚ ¢ @ "§OG@‚ †OH%å`lÐÓ$=BüŒ'=ŽØ @ƒ¡„„§ÉÁÙ §YŠDJ“£ ˆa°¤G0Œ zÕØ£%$V@ƒ§„„ÅË kÐÓ¨„DI“£ hJÈô=FI1¨"ƒ¦5vÀh ‰h`JHirpFÍêìÑ^6@ֆĚ> 0ZBbD…±pȃÑ(²Aÿ‚å@"°4ˆÌY%äh/+ *”ÿÐðä Mÿ‘ä€áL…Òáß¿¡QBbíô#!‰Ȱ^6<7Ž&H8 j”ü)"³àiš"Aé0š2‡HòŒü‡æ/˜Ì?xzÄ—a*!µÃh ‰ˆJmÈH$RŠD¢rÀ²á_¤düøo¨´!Ñüöïjþƒ§ÃÿðæFˆJpý€È£ ˆJ½ì¨%ã?ôXD‘– Aÿ 5vÐ+!QòÞ?Ô:xs#LR®-!‘@ѧ„ B/!Á)ò_ÐÐ*!ÿ¡–ÿPå`a€?7þ‡çBX®-!‘@ D J‰àÒœ.‡J ‰<Ž€%ÿýƒ§Y¼¹¦-7Ž&H (!!)Zc ÉòÖr­g‡§„„„A@5ÚÃ,=þ ª–Dö²àíÈÀ!Ú†Ä^BBÛD”ÿ!½9Ê{Ùÿ‡ ª–8Ç!QäÀíyXZ¢½ìùÑŽ$ØË†ª¤B 0ü$@Q¥„D+Fb! cŒ"ÿƒ´"!¬!ØËÆ2‰%?bÉQX¾$¿„ ˆˆv  €FWû?Sƒœ÷ÐfJ¡òÿ`,B¹157’• Aéqø¥H€Ò«}þÓ±„l«} Éqø¥H€«}þáôHñzHxzn) €¢„ÄYgSÔ §Ùºƒp×!Rrn) €¨„  ´„DnÐÿûGË’ážšaœÿÐÀí©  ¤„DkÐÓô&š®ÐEO‘ð öFfrüÿ €¨—@Q/³A?KHœ568MŽÐôø €ª„   „ÄÖ §aIÃ]‡$—Ã<9þÿ@pØTÞ³!ÉmÐ#_Áño0†4Æ‘ÎØ.{$TBûôø €&AH“d5è‘ä »"½üÆxKÈáŸÿÿ :Ž[„PØ G9Çwð]¢„ø%Ö0 éñ?@ ¶*›Z úÁUFþÚ)IÊ”#"9þÿ@SBbO“4iÐÿ\)%A’’)GHzü@v‚.½ô[R’œ qdÊ‘’ÿÿ êÔЯA? ’¢KÜ13åÈIÿhÀªl4èÿA›Žÿ¶QIl ÿXÃÈLŽÿÿÐ`ª²)lÐC“"ŽI·Ž7i×£`ógè rD¥Çÿ4Ø.ß$¿A|3õ?â_èÚlÄ™ Q%0A‚ÓäÈLŽÿÿÐ`J”5èÿ!5ÞþH-ÿhR2’¨!p¥IxŒ´ôø €ÆZ4è —´íz“hf2 `/(Gfrüÿ €(AÒ AOJ‚¤ZIIvÃ4`I”#4=þ LTnÐÿCÃÔìãÕþÒ䈑& 7QŒÀäøÿ?@ p‚¤bƒþÒàοÿ4M‘0Õü„åÈLÿh€$-ôÿHïè¢Ößÿ¨¨’ÜD9“ãÿÿÄ0PÉ‘ úä¥GÌr©Øü÷Yì Ã-QŽÐôø €2=Î=ž‰®4h=?ÿº «ØÚ ˆŠŠš™=01ááã377ß­¡qðî]N…“êêÜgΨ¨lWTäôÔOrrJˆ¹üèÈKÄ0ÐÀß ä¡G“©tâá#p0,‰  €p§Èÿ#5A^¿qóÂÙ™ ˆa¸[‚ü¡7š ©ˆa¹-EþJ òß¿¢ÿÌÀƒ•À ¶Ä ÿýC$ÈÿÄÿýc©—’øä?`‚üOÿØÙÿAä¿á’ ˆap9‘ ‡DèÁä?` ùïŸÙƒÀò°„ü*!ñ$ÈÓÀùVBþ?ÿÙœ ¯þ#\Bþƒ'Èÿ`%ä¿a“ ˆað9 œ"ÿÁiföÏ’ ÿ«ìøä?‘ðR\ü°ÊþL’D%HÔ’}˜•¸­C€A ˆ¢ª¨­Bá{£^Ã]~˜Ù¤ ŠkÖ¾ìÌ:Èï€Ù’è‘ Õ!!#ú~)i] ¤#º0tHÞ ©CÉ7 SdÃÙúÇ€lˆ‚ùwȃÄpêujþ$¨ kC‚;5@šûÌ?P‚•ð‰(!Ñä¿'þýƒ%H öÿþiþÛ·ãß¹mÿ€é‘ ÿ«ìÀùo8UÙ4š ©ÕËþ-!ù %ä?H/û°ÊþwFå¨ÊþG(A‚ú4¨ XBîü'JÀòJ ùÞ©ù7œªl€MÔHÿð'Èÿ mH`• lCþ;„3AJáNrø'H€MTHÿ  òtò|òßIH ¬²ÿAä?`‚üwZäßEÊä?P ­²ÿ “ @THÀÀÀ¤°‚Põ´OjàFÄ®`'ÁVØB¤¨ Áâ@œ 4J‚õi¶ƒú4ÆÀNÍ?Ùÿ@Ãÿ@%$R§(s2ìîÔüû‡Ò†ü®²ÿÛÿ”Ñ©r†W§ €(Oÿ •ŸZÈIa¤«‡"†¤LdWR» I噚#t¦ €¨ReÿCIšˆÄ.šà¥&¼dú/ÄRÁ0©,…•x¨ð?$ƒavÁ„ä˜QÿÒê OÿFêÔ!@Q#A"§3Ô¥XÂTˆ”†ÿa)lÿýř汖ÍÈ)%ý¢8bˆ”#5A5Ú(å– o¶¡—Hm=ä¤kìý%"AþÅ• áìèE7õÛ£ ’z €¨Ó†Ä‘bð•©³¢EOÿHJX¶ÿÐÌMƒä?Ô²îß?Ô¾.¼‹ª¡¹Ej^bŠ!ÕÁÿ°µ!‘úÏ(–üCnŸ";p4A>@£ã£ rP€M˜ ÿáOÿFb‚ ÑIýù˜ùï"Û?ü ò߈L4š .AŽ–X@vÍØ`xƒñÿ7œLŒ‹>à#€ø“q!°w!íòN\ÁÉÏ‚šÃ ¤,©È¨Zû€Õ>v1®ê VŒãꢺìi?™ ¤œ ÏÏè< ä@£ ’*‹+þÁWüƒ—ÿîrþƒ.?-Ðý÷ÏøxùÙ?D ùï0Ã?  äù-ÿ€%$hO °„üwâdêðß?ðâ !èò3è⊈- Ã1AÐh‚¤N ‰=A"¯‡¯ö¹*úPªìà=5Øärl XBç @£ ’Î ½ ‰-A‚ªì›#4AÐh‚¤E‚ü‡Ve£$HX ù{‚üßSƒ%A‚—Ÿ ë @£ ’JmH †vjøh§Ö†üïÔ€ÖCECæ—ÖCþUÙ pˆÁë!ašm ‘ý @£ rÎÔ€KÈ#s¦ €Fäh‚T €¨²… 5š )™ËWÙ#3AÐh 9º¸bP€M£ rP€M£ rP€M£ rP€MÔšË&HÐÆlh‚ü©9 hDMÿˆN ½à ¤·6fßû‡ü÷oø4¾á– h4ARe¦– ‘JÈ 9ý %Aþ#:Aþ»$ O qP ùï2dµèäŠa˜ h4ARgêtß?3äy)AªWBþVÙÿ@G©hþ¥"¼ TB‚ªìÀrϦñÊ ê¥òmÇÕˆNÿþ!WÙêãøÀë!!«}@ r¤3hù™Ä¿ýà©C#pÕ~Uîß?Ð8äuØâ Ô 9Ž؆ü7lÛDÛ}Ù#1Aþ6õ)A‚š* Å ³}®ì%HÈaSÿ®þÇ”Ÿ ûXBBNÐÏeßÀž — û @£ ’: RàâHgÐâ Œr`é?x• Y ûTB¢$Èàãב¤ìÀÒQBµO?Mà5AžÁž Á%$,A¢z+AÂÚÃ8Au:5ˆBr4AbMÿP«l, ò¤Só²@{‚„õ²‡s‚ 8Žoøî©C"ë@‡„wj@Ã>ÿ ›¼ @üôž`• îÔ µ!Áãÿ0Æ!‡o‚ ºX::Sƒ{¦\BþÃöÁ:SóoøÎÔµÇ!ÄÃ5A‚Ʊ%Èá¼  €Fä`™Ë†VÙhS‡ø/N†  €Fä`I£‹+À €Fäh‚T €Fäh‚T €FP‚LLLDáÁh‚t €FN‚LdddD¹y3þ‚Aˆv Ýáÿa‘æA„&ÇJ\ºˆMKŒ£©q0€¢Y‚'è)I?jÝŽ­€Ã­$RïZ§BK¼ÿhµg8J÷µ_ƒÞÝ GU7 †! †Ñ ƒ Ðh‚ƒ Ðh‚ƒ Ðh‚ƒ Ðh‚ƒ Ðh‚ƒ РLV`0:°3@Q7AþC”§ÇÑ9@1P==þû™"ÿýM£€(@ ÔNдø-Aþ#/=®¡ˆÚ ò?®ù¬ô¸r4EŽ0@ôKÿÈJ£)r„€¢c‚üGVz¤‘ˆ. v<Yéq4EŽ(@tMÿÈJ£)r$€¢ú°Ïœ56‘)3=ŠŽÿŒ@ÔÇLÿÿ‘ІĖGG$G ºL‚#±Ýl¬éq4AŽ@ô›Ë&v$r4=Žh@ƒ/AbOOž<¬‘h0&Hìéñ‰×hl@ôL¤¤H,éÑk4EŽ@t\IJ‘½@àÛh| {@ƒ3AþÇž¿©ŽFØpD×IbŠÄLª£)r¸€¢ç’–ébO£)r¸€´ ò?jzüM6Þ£q6¬@Ñ7A’˜"±¥GïÑ9¬@Ñu×á?’7ÁÓ£*<=¾{7kÃРN~XÓ£žÞh´ _@ƒ½„Ä–GSä0DçIjŠ ÇšííG#n¸€¢ïɤ‘ÿ±¦G{ßј¦ €}‚üí^£¦GßÑ9L@‘Ÿ awÀDƒA Ä@^^^mmí¤I ÕÕÕ---Ó¦577———WUUegg÷÷•••555ÕÔÔÌœ™žž^YYY\\9ÎÅÈŸy @¼£Að7ù’X¥²°?â‹÷<7 —\b!’VS-‹ÃŽ_É)‘÷”unÙ\óthú™6¤&’[6’í6$Ž“ú™ž`Cj ¬z6hC¢iȧaCxI¼p€1ÂJ=„}v7Ã)ŠöFó/–YèžóPS¨E*À)œã¡fñ:ã³Ùºš¦Yþ›ÉKQoµx±$=æÕþUÙÿÀk+ ºü ” a‹+@é´ ºº§˜ Ó TDbM ‰%=ªñN‘TõÑ;ÔDí ¬¶ÁmÈ 6ä?Ðò³NX•Ý [~†– 6$AþûÛÂ^1þ^B‚$¨ÊnGOññæ#Zzäå¥{8ަG*€¢ÖjpzŒ‰ƒ.ˆ%ÈÐ Jà¶ü Ô†vjþè‚KH`• Y  ¬²ÿÕ HPr"¨›ú/’1:5³}°¦Gz§ÈÑ%TDÕùѧ©õi€MHð–šPÙ ]~îÔ»4Ð )"ÿÚÀ"’ A Ö©IwjÀ$– NŽèéÑÍm4j‡& ú ûü›Y öùGòLÍ¿ÜÉ“ÿýÖ C±¦G7—Ѹ’ €è— › ò_?Y ²{‚ Åš]FSäD§ñàN 4AÂv’4—ý{§¼)kzÝ!h¨.®@I¡XÓ#Ù)r´ƒ2€ €†G‚ ÅšíÈHŒÁ`0š0 Ð0I¡XÓ£i1=I‚x+Ðh¢¡% á’ ÿcM¿IIaÿQ’$" Ž&Iú€˜ êÕP9AþÇšIIaaÁx’dðh’¤ jž~Ft‚Ÿ6Eíùkzôð€;ø%á‰^H‚!Šä¬éñõkXzä°' ™Â0«mpDI’þ€'I¤²zF x‚ ê6^\‘Y\^ Y\:޶RB‚ç²AÇñS$(9R#AþÇL¯À – 'HË㸒d0Î$ùÞÃD´,Ö¼Ì ª.?ƒ&Èà*û_CÊégÐæ  ²ü vß¿tê$ÈÿXÓ£ÓË—ôhíN0A†aëÛ€KÈ+V ·,A`ìÓuä’ž÷7 H :&HÐê Z'ÈÿøÓ#1 RÜ” Þ$Ñ M¬—´Iˆ’@è_^Õ–ŸANЃ&ȉv¤Êþ]íJÿ`+ÆÿUR'AþGKN(éÑ'<œp‚L~ƒ­w/%QºßtI’ܲ£o¢ jž ;Û´²¶É š ÿû4åÈ vÆ8$AR©„üÿ_z¼Ÿ¨ùþ)8EþÇL‘å"“ä êÓÉ4ãÿ²i4ìK‘Èéñ%jz$6A¾ÂYoãO’C3 ¦¢ €è ÿö0Ð6AþÇ“MMÉK MÉX’$<§m’ü7hÇ®i]bÝä¿lš'ÈÿxÒ#ñ Òð8¶R˜A€Æ¥äà^GÓ4 @Ãfq @¤G´ô耻[ƒ‘ -™ I2,žCA0 [’Cb¿í @Ã3AþÇ™HIL§°%HüÉ18dWˆƒ¿ @Ã4AþÇ™IL§ŽCK„’cHÈHH44\äÄpjztð §$ANŽ!!#(ùP?аMÿq¥GŠ$É‘Ìùw¡‰³äüGõƒtí#Ú%ŒôJ“D½™””„ž “@š ,ú&Èÿ8Ò#ÎI8A•C¨YÐ`¿yîžžÅ?\DºíÈuÂGVS5IÕ$09¢%Ȥ$p ™”JIIÍôO䈞µÈLD&GêVÙøä ò?™ ’”#ש›$ˆZ ˜Ѫl`z„TÙ  Lô®²q¦G-#?ø$ÑÉ‘ÔIÄ$ÈÇ¢Ü_üíA´SþPOD9 ïâÐqä#Qn)þ|èé?:%I€¢R‚ÕÍ1àj” 0A‚ÚÀ[@ÒÍÍÀJ;) ˜ œ¢" QÄ5II° RL@2£H¤qaR¹ wzÔÒ"'A†›IK[hhþa9|óFøÈWÒÿÇrU<,5¢2ŽÖ@šF§ãÄ@Qµ„¦F`ŠÌKÊ«&&P§&©œ$!%$¸E LIÙýÐÙM‘à™”T JIuII()’œ‰4܃‘ÉKaĦÇRkd¢JHX:û‡Ze£þ ¿‰íÌð(…%–tŒ\èb&Áÿ¨á¢@Q­„—à™OI°™”êeKH`•Iè%$0=‚ªì$H‚¤´„Ä›ÿü ''A†=&*9’’ ÿý'5A¢¬ŒDOÿ0ŽÿYBÂkò˜E.F’þóGDÅ îeƒ Áƨ·CB(I$Œ ¢“胔ˆÛ?ptjPoßApü‡|ÑÓ?ä3Ñÿ‘<‡D… @ÔIÐ3A&ÁjìiÍÐqHh‚„¦Ç&p¥IÀ&$4AËHPzœª´ÉJá €3=ÊË“ Q“d­äÈDÅ écƒkmð°h\œ"Q$0E&õ÷#%Ȥ™  êcCÚIH ’ì^6$MâHä%ȰǨ ÒBB(IÃsÞšb_5$ŽqÈÎ$p‚¤÷8$,MbKXSä¿°ÿÿñ'H8À—Gv Iq‚ *$Ȥ¤è$lsÙˆ™š¤–I°4‰™±&Ȱ°ÿ†D%H¤éíÑIÝ @TII8W$AAËÀ%HXšDKÎØRdXX °Ä“ ™¨˜ ÿ&H¬ €†ïjô4‰š±%HpŠ û¯„d-!iœ"hd$HhšDJθF~€…dž*’"_Œ&HZ%H€1 š&aé{ *$A-É0AÂ뱆P‘ @ƒ-Aö %Gv´‘N©ø¹´˜È`B òÿˆÔËÄ0¨òWïh½†’ÃÀ Zÿ™ ÿ @1 §ô @4%¡UvHÒ@ùÿÿÄ%Èš†¨Ú> Á“ »„…Áû×hé|£!1 ’üÆCähq:tçh°$È®ðÎ dŒ:RM’„$©M.Œ›\Gt€ ²mP€°$ jG Lh½M(A• ­Þ9m\ @ƒ"A6éo‡„!‘ðB_‚ÄQÿ#}4r¨$Išå€ ²b0ä;7ÁCA †ìÓ§ îãÇ))X$<ýQçÖÖC 9ÒÌh€ ²tPH½ -ÃB pŠ Æž i?ÿFbb€ø™3ØÀ?lG“>…’˜UöêÀúÄ4à 2k0ŒrĬÞ~úô_dR‚¤yCmд)éå€èY2HÀ?dPRö±6²ä"$ø_Èsè€$ÌáJÂ`4AÒÐЙ©00šé h WÔz0Z@ÒЀ/?+ä`4=ÒÐÀ/ÐÍÔ`4=ÒÐ ØÂ3ˆÁhz¤7 Á°ë°tЂÑôHw@ƒblÅ £é‘þ €ÉɃÌMhМíÓ6ÈÀhr@ƒç°©®AFÓã€DÇñ ôùgH`49 Á” ÿÏè`Æhz8@ ƒÌ=3zŒ¦ÆÄ0è\4£oÁhrh@ ƒÑQ3¦ MƒÃàtÖŒSé fÌMŽƒÃàuÚŒtºÍkúhb< €µë€é„ÖWŽƒ àw!(½Ðæ"Ø£‰qð€bÎ%*Þ”=c4-V@ CÈ­à4´€20c4-n@ CÎÅð$µ„x0ŒFú`Ä0t>ƒ40×CÃðñÊh €Fƒ` &@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *@£ r *`¦ð¦ÆusIEND®B`‚procmail-lib-2009.1202/doc/article/pic/www-page-email2.png000066400000000000000000000263701130547513300227730ustar00rootroot00000000000000‰PNG  IHDR œ€'ÓgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEôôô®®®f†¹yyyÕæø¢ÆìåãÞ]}²q‘ÂÆÆÆþÓ]u–ÆŽ±Û%%%yšÉóòñŸ‡cÝÚÓò©:€€€&B‚ÛÛÛ(D„èèè¶ÔóYy®ˆªÖ;}žÍ $jºººáÞØ¬U ßßßm¿îŒ.(ŽÈiмÙÕÎ-qûûú1M‹4PŽ’´ÞNl¤”””Š¬Ø†¨Õ¡¡¡Fj8U’ëq’!<}ªö²W¥Èïkkk.J‰Jh¡ 9{¢Ð_~³°“¶à‚¤Ñ~ Î=Z•EFFœA^™ÀèEcéòü›¾æ­Ïñ™¼å²ÝŒ®ÙÉ+„¦Ò0tRq¨Gež†††ÿÿÿUt«zœÊnŽÀÖÒËß²Œ`€´öööc‚¶ÕÕÕhˆº–pH6xÑm*3vTr©B`š^^^Kj¢Pn¦ ­íy#ÊðŽŽŽ6S (m?OmÀÚõQQQ ÄëŸÂêë¦or¶æææs”ÄWv¬È—o´´´ò̧É;›››¡ÏQp§l‚©R9®ƒ=W‡öúþ[z¯é˜C>\—Ÿ #AO'-L¥Ö+G‡ÅßýÔÐÈ*o,5UÊÊÊ¢ýýýùùùìììâââÑÑÑÏÏÏÐÐÐþþþáááÕÑÉ&&·ÙÙÙ¬«HfŸIg –¹â—ºã;X”üüûèæâÚ×Ð×ÓÌõôóíëèžÂé÷öõœ¿ç…§Ôw˜È˜»äùø÷Xw­d„·\{°ñðïïî땸áüüüøøøúùùëéåîîîýýü?]˜#?€ãããþþÿíííoÁš½æb‚µkŒ¾ýþÿ£Çîr“Ã|˘»ãv—ÇMk£ŸÃêCa›cƒ·š½åÁ镸âaµ××ׯ~ÂÓÓÓñöýüýþùûþáíúúüþ¼p¸ß >OABh´ÝþÁ:•yn‚¿âHx­“Š{^¼Œ²ô$SpŒ™’еÎC?D]6 '²˜‹ˆŽžÆæ‘Èæ999]oW`|àYåh Š)~IDATxÚb˜< F*X¸paLÌ:uõµBB llknس[`ý¦í4Wž1þüˆ€b˜1 F@ÀÔ1š‰FËe@¦ŽÑÔ;u “~[ˆã€—&ŠòHñäJò'J)BÊìŒ8 %IˆšÖy2Γ]žX^ÃýñlݬMݳi1îf»»=óF|¿¿»ßCŸ×ð!;þsE=ø†|ÛÔ u웣¦¨_7ÕCÜûf¨aj„Š“¾GÏ q …Â*:¶m¯yv€$I²,Ï‚sT­VÇкǢ]âär¹^$Šâ3hC àÔëõRéÐqœ|>ßBƒÄ;bf¼¢vdšf"‘è *•Êê{¨\.÷ƒe$ÂÏ8Øôth”XDº®)Š¢ªêg6‰Djµ7–e5M …\×M§¯-Ëây¾•0 c]Rë  Æã©T h6ÃáF#™üùýþ(£Ñ?„š:Z[ßË ~M£©’:–:¾Çʵþ}ÛúîM±ðKÁÑÔ1üSZûS¿ÿ,0qD,uÔ5XX4üøüëçkÁ—/GSÇðO(íC‘”vÇLHê xêಈ­hûøâéÓo_¾ §fꈈ )uDDh¡Ôtúhê rê×3d”眷x&B’¨ì@IÚ ‚R³€èU¤áIGŽ“Çhê ]ê hêøó/O¥[%×äÿת*÷—\ɸS¸Ý¡‚‘:"`EöÔ+<@4$u€RJê¦ ´²#½ì€¨©Ã$0Z³Ð$u¬Ïô?OEE±ß¨ªêy#—ž²’:B0ËŽpña®X°”híqX«–:@‰‘: [ꀷ;FSÍS@ÁRG‰J^ês#£6.®69D«Wê¡rê'rRÇhÍBvꨬ´µåãÓ:>’î,=òrsMr?¼L-–CêÑBZ¥ f)¢G I!`^Rê€T-8Z¥ØSžV)–Ô± Q³Œ¶J©:0z´O_=‚‚þ™˜äæ~PœJ¥‘tPÒ+Êc¥„˜…ûûÍØBû¿Ê¦Ž:D@ <<¼ @O¯ ˜:êå9§Í»-vLbÖn†xhê ä9Úâ/@0utD¤w((--ÍÌ´b /hÕ+Óéã0u̘? €F×wŒÎàãžÁ ÑÔ1š:p§€]98ºr÷ÊA€M£©wê ÑÔ1š:p§€M£©wê ÑÔ1š:p§€M£©wê ÑÔ1š:p§€Âš:\ ìJO_¸RîW*©a© €PR‡+LvÅNyHHbWå •#0ƒˆ‘"9u¸b˜Ï×ÑÔ+ujê N®h©Wê (›báJž!£©ƒ’Ô1”:Kêç}¬yÛ)w»bU⊢ŽpÄNKà@¶IÈfº«+ÎhG5‡s‘\‹§Di©c8uŽš{à iœ5 ,Ò©Oê Æ”„€”~]æã+€\ ¸æãÉx|=‚S@á(;\]qf5âRR:Ãj"Rp7]à$¬8é„JÀ ¢Rî"¥½5š:j€Â•:ðÔæÄ–“ñ¥ŽÉ“IHÈeº4îhÇ0¯C&¦ÌV)@áId•(qB ñJ|ê@J æO&6uJ¦£©#ui­Rh›Z¶ã˵®®®øº0pƒpöhQ›”“]±Ô,xzƘ­RÜÍìÑV)ÎÔ@£c¥#w<Œpê Ì>‹+þ1,ü¹‹° „*WJŒ˜L¹+02š:ÐR@–#N4š:FSîÔ@£©c4uàN4š:FSîÔ@àÔ!2 F(€ï…cdDÝ §¹o0u8uŒ> °€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€BIà)) —z×lò8•ã”qÅÁ9€I®DHàBxÃqÅ"çŠÃ¡`qW˜nW8ˆÀ©ƒØ‹p%:RI4‚§A„Vvr,ñ¸b%àÒáŠÓ ¨:x8%HôN‡¸âJp8Å]Ѳ‘+ ±‹;w¸R\`7‚wê B©Ã•²ƒÄäíJ¬bËW" @þÄ•\]±€d0r!LJê FÙA­² €FS©Ý¨ºýÔ€Ï*:(A´;°ÿ$ï#S0_—rülÂy·Y¢þâ”%Kðu7QL®œbÎÐÚÜ ¹mÄÔ‚Œ” påŽâI¥‹s7´uüM;vФrb°Då¬âJ)®$hoºÖc;>-c€aN–òv`•lŸ4±}~ <²é·¾ö( æê‚•¨ùÌ#T†ÉêqŽÕ)¤‰ :œ“TŸ§øÈûv=ï anZm&*Ô‘&“1¾T÷+×ïÝñÀwå‚ ôtªÛ·µ¶Dž}õ4tνÃþ¾”“õjª§b/P'¢z3-î‘d± À«hšée¤­‡"5¥%ûY^âò’1F&fpü&Ë€°²;aðtîU¾í½Š‡@¬>’ðÛã󲨠};¬K×Á=\ÈN“7·VÈ·†¤Çö1)ëWhÚKÐ}„­4®!M…T$‘î}\¨Gâ–¡ãf=´ìšI–™þlÇ)€°¦WDj§FêÀZ³àO¸³‹+j¦G’•˜±…³¼Ê,©èÔQ‰%rQÄ!)v©[‚!œ:2Ô€Î28†aàÝÊ;t•›½Ÿ(%+—‰I¡DGÉ)KW¼ábIZ8D31C#Hb¿\Ú'¶Dˆ,ßE§ƒÿÞc€î;œEGýÓÕüK£éÐc°K§ƒ™—…ƵzÇs¢ã€k»´Ý';°J·¯E^§¦M¨Bš:H ñûìÃ<ˆâyWDG0 RÇ¡Ý ñp—4š:Ftꨖ8İwá@”¦lþèÐÄIJÇ$vÇkâL4:ƒ?¢S‡˜Rõ!†8S@¦ŽÁf Tê¸-vìÃ̸Ü@£©cD§ŽD±Ù³ð¤€M£©wê ÑÔ1š:p§€M£©wê ’Rµu)©ƒ–Gi¢‡˜+±±À"¬†D 'üHJ2h”˜‡JËà×G\ê -;ðæJDz¥fZ®t(e\É);p$È’2øõ•:hЦ¢W´ަt9`)!ƒ%1ž:}mÒ„¯@UèŠåÄž)ÏJÀZ°¢°m}&S¬”@a™:ˆf©{q‚±ÈË–IÔ3/±BjêÀ^)FàZäHFêpÅe'ªéôK(摟:-u¸b?ŠG&G^„ŠçÄQôE£Èy k˜G`T=(¥ÁvÚ©ª®Ø˜I£åŠK=zêpÅÙ\rE¯Y°¬ÞÅš:p¶;dZØR¼]+ƒ+uÙî Rú,h+JÑ¡¢ztŸ‘+úaØð.¢ý޲„åƒÔ §æÏß11Þa¨ÎŒÔgŸïŠvÚá§èþC8"…F^ÖŠmI-ªç]Q›°®èý˜u”Õ»°†#$ÂQÚ‘ð>‹ ¢Ïk»B:,O+Ý0u20"@|Ÿ €°Ô,4Î nltž…< ƒwxƒÔñ€MÃlN†”ÄA(uæxÖ‰1ÚOAŒèŨԜ£•!!qJ4:ƒ?ÜR¼A…Ô@£©cØ¥*®ï ÑÔ1š:p§€M£©wê ÑÔ1š:p§€M£©wê ú§W«ˆˆíÛ.†1¬Èr)#:à·9æøå±ihê˜ÉÐ;[,qÎܹsMç@— ³@á<¯}]¨+²‚Ä᤮®ÈS»X®¤'x)æ•ØADß>Í™'$ÀíFC=P»£Ôý7d†Ö|'ê%ð¸=_7èŠ>‹¾²—æææ¸É`­Ìá, ÁØ™¨ÆÀ™ûö÷’¨>fj:Ût6˜ššBi0 ¦¡B®³ÂºŒ!TÂ!§à¢pŒÀù„ïDÊÔuŸX F /ÐĹÓÕÛ™—Èk$0ŒA[¦ Ä'"S‡Ô;kV/ƒ@/ƒE¡R`Y×YàŠ \áX‰ gºÂD¡à³gêˆÀ³–×ÃØõ8Žm kDÖOQ§é ©#’: }XÍbAp…4æšY¤Í˺Xäš=²ÍINh¢`jþ>óýñ½ @&P©^ à ® àŠ €ì~$ „ŒBÓNàÜ0€Ây"%–›èa §Ô…œø#Åqº+VÖ,Ð-h§$zꨌÀ8£ßóŬ+\‘Óé©# q2±§Žˆùæû4Íg˜@¥Ì!4 Ït‰®pÚUÆJ¸¢¨Q•HÚ œ9@øÎ+%;uà\§‰5¿R–:À+±¤¤k¾#"Я“ÀrW9ÊmäØîˆX ÁKL(Ì…@œL c`ÔüùKg˜@¥–BhžQ9*át%ªL%”¨DQ‡¦hóJïy¥ØŽuEO®®ØR‡«+®Õ˜èÇ‘b¿ëÛ>WôÔ!mw@RÇoŒÔ½@ÆB¹NõVùÊ,©§²‘ÀPS.ÅH1|Ll©céÒ¥pÞRTÑãÒÔ4Œ”z+#"ÐS%†wѲ!@¸Î+E[Œ‰¾b<¹Ÿ}{œ+öÕ˜˜Ç‘bôYP5a.Mx ž-6'¶?Â’8øø ×Wb/ À ¥ ðôªD ì%K–@qƒI0 &#" æ¸1P6 b.” U1;*¾Ž‘‹´ÊÊJd"»ÎDõ'$tˆOdmâÈ3¼‰Ô»[›I94+cK7›ˆÔÔA¿ÄAè oúãÈLDZê¡câ t†7A@Õ‹åA×Ô;v ½@‘\³ š3¼Gí@ÁRÇüÁ—:ŒãڀĩƒÀÀ( = Aœ:̎ڀĩƒÀÚƒQ@{@°Ô1cð¥ë–Fí@a¤‚ƒ28¶_QePD†˜±3öAèj%¨@ª|iiiú¦ 1 ,ê R„‚­¯”H-DR¬:éx4+@¡§2F9ÐOȤhTD†pꘙ˜ži‰ˆ¨ÏÓ"@&gF`Š¡„U‹f *'Z1:É7ˆt@h©C†¸R'dRTŒÈµšþ@x.â6˜Çˆ,e…D¢ F` â”À ¬HSަˆ„%ôV˜:éxt/@Qž:°œIŸÔÁ¢Å0SÖÓKq ¯·¢ÎKe&Q=V'2GPítVb@V® `†}DØy/JÞµ©MÓî°Ë%4•¶ÐSª:FwŸIóK¼†qÝ!s %¬‰Ò}Æ=6Û#Œ{Ü|¨ãÜêX?£pÀ œ¡0‚£Ñô”êƒÈ@á¬>¡†ÔÌŒ.L¯¨MËѵv´Cÿ¸n„™:°œZ…r<¦ Þ3'¡Y…„ÑÔD:òLåt,’RÇl0MVr–˜âP1=8ÖÓÓ‹@DÈé!‰è!ë@Öˆª.“ÓCbF Ø®‡f ª™z®KBYz¨’hv£[FE@R‡ŒŒ Æáwˆctepœ‰F£%5´HÐÎ<#2uìƒ,ñˆ¨ó¦aÈBq„!‚¢ áLT98 I „`.-†H:rh–£*BS…i4ªaØ$ŽBq;5@aI“d #1J…I'dÒ1uìÑ`Þ!­Ï‚ÔAê!—ƒdÐZ§xRtòeÍ3 ôÌÁQ@1 ¤³ŽAçƒÎD€òóJG… €F@¦ŽQ€Ðhê¸@¦ŽQ€Ðhê¸@¦ŽQ€Ðhê¸@¡ßG Äh%VÝ(² €0î…C¾‹‹pò Àa kê 2ÞGSÇp„;u \öùŽ?¸b˜¢Ñ3¼@á©Y Ñtñ#êm®ˆ{!G“Çð„™:à­RØ=öh—AŒ‚aÙ”JFSÇÈ„§UŠш†ÇhêI €ˆI®¤V/£`˜€""uŒÖ,#‘íôš%~Ó=JŸe4u /@¸GÒ#ê°äáêêŠÒ‘EH#Ô¯'@£³p£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔAo0it·ÐhêM€~Ì#@¦ŽÑÔèGÄÐhêM€~¼4@¦:ƒùƒ9u M@£©c4u úµ4š:FS _‰@£©c4u úuZ4š:è f æÔ~@¦ŽÑÔû’W€M£©wê Ì]Ö02I “X€¬ˆ³PqË"l7`À•he®¸ôº’o2¸d@€xmxD±¤€B?¡k Žy¡Fðâ3¯ ®$DМþpu¥N.‡¦…_Q¢ØR@ @êˆp%3wºR/q¸’[,PTʸ’_v`Ïÿ2„J Ë€".uÀbu`Sö{§hI ƒ3Â)L踂B¶ëtöŸÄO(ôx‰’úêŠ,èhжÎÒÈ( "(Л“3(?ºpv©ÃSlˆÆ´”ΕÐÿ…È`qO£‹×4þh˜F$Š3.b/Ÿ«ÁnaŽQcÿ3ïaìnV訫T‰›ž'^—å2Ñq ã ŽAÐ"®ãî?I×Ud¯:­DûÙÏ+µO$OZS¨³ ¡Ã˜(µ‘’§ÁB¥Àæ>.ÄMERˆÚ™Ç»ô#ó–xðÞ¢ˆ¯Ðmt`Qèa‰î&) ΀«G'YÞ¶)òk6ÎŽ!£epÂÀEX§;°ÿ$~L ¥^>„&¦Ge™‰%A™\cGRPyˆ?rz:LhIšÒ®eðü+z"êÈ÷8›÷gaÿÉNÿ K‡•Š\D_WbAÇ@¤§äò^s`É(5 †ùÈU 5SªSð§„Z©£RsEªþ°¥„‘®Hú\QŠ)RS¼]-uÀJ"RRû„èÔ@Ħx™%u¸FDàO¨a’¨œ:\ñIàu+±©§¨¦S-u`˜©Q2¸JâR@:Ð O´¸pÅZ—G` ,Ô¦)–* [†»ÝhLbs Ö¸ƒ0]ÑÔº¢ù-yº¢ÙÃX̆¢= ±kêÀÛîÀlp —'ð–-¶QˆjŠ-øS@ÂÎÝ †‹°Žw`ÿI^Á'gzE„BQ _Šðê•Ê'Njê/¹f »ËœdÓ¼˜ˆªø¸DRœà’¶ TêÎ,1™¥.ÙmEÄÛ+À^HL9™8)mXÑ#Ë‚YÃc´D—m»@p>CÁ±Œüò_ŸÂ;ÏâJÑxò( õ<‹ Cͳ¾Ô1š8û,œ uFê ’çhG2Ls´2TM© €Fgð‡ö ¾ þ9Z S@¦ŽÑõ¸S@¦ŽÑÔ;uÐhêM¸S@¦ŽÑÔ;uÐhêM¸S@a¤\K|ˆºÜ›ZÊW‚b56•‚ñWÒ¼ö9æèò8U›?y‚³÷ÚÁÞO%®"Cœš>© €ÐS‡+Ž bbØ[„Q¾”zëɳ)7')uàTm,;ž¥¸¦Bˆë½ÊÈ—‚ÐS@a™…£¼ìÀÌØ®Ô/;(¾u%΋ÍqXÅp§Ž™ ³f‹%Ι‹ LÁ¤+’ˆ+E‚0p%B¦ÄôÔ@4N”ÿÃ6uœ8&vûÞd` &]‘D\Ñø(„+0%î¡ï… ÔÔºžÓ}­$Úl$ê"NÔe—®˜©y*Ò¼(¶Õ¡¨2HKu"°¬ñtŶ(iš·“Ñ @_1ꊼ<ß ê  \DÊ0GRW\É@„€áPµ’˜i¢©i"˜‚(S0™èšˆ6Ð` ! ®98…%B¥ òý`Q;¦º21‘/‘Ä,Í´²AßG €n+¸a„•ònž§®Ð!ò´º‚™ã¦©x0Eÿ«Èh‚€ãìÃ_nISrF›x,ê êI†lqN²€NwVbÿgåCä‡5»æ|tqY•ý½xé£7¬9—aÝ RÕ1¤¦'Ìïçþy|ËsŽÞD“q°HG})-Z÷È´oTy5nØÖ¸¯BÌððqî6Â0E¢†šE(©Y!«œå 6‰‚¹0Á>‘¬³GIì§”y£CÛj+_B®Ž@Xä êèp¾¥ô0óBœ‰Æ]‘þè€xÚ’ Ø]ý¢#Y:î–§Jßdd—µÚº©')v¾}öd€: "–f&4TÄ/!¼Â¹š<­HCŽ"õÿï8¾ÔQY–/aɤ^ÊTbÑD(u@µ“›:´WVâLðäŒâd4 P ¨Dj xB/à%&”@ŠX²¦ +=Æx†Ý‡¦Ïš5k:Íš£*g!@%œ®D•©„•(ê*Q™p•©Jt lgÍâR¿gÍ*R"'ÐÏþ@Æä°%Þ}Iÿáij ÿñèOÔy®Û€¬-P(|IkJ:‚¬BïÞ@°ÒîÖ©Õl79Áío΄ ƒOcÁæaȉð~áés«LÙaœÊÔ#Ÿ×sorˆÔª$?AØ  ¿‚p>x©e€.š Î…ÞRû2 ÿ†}Ðqm7‚0pÝÃ!n ò¾Üĸ—?"PúŠÈÝ(C‰@-ɱ;–M#cJ×är—‹Šþ99†ý÷½0CIƒ ìuÈ/ùbÇi5Dì½9 .Ñ+#sí˜+ #R ^{S„À¨Fl":§â£Ï(¶Öˆçh†¯+˜)ìÍ'ÇÄÞÕÑ;eÊ¿ô¿º`†ŒnAzc2Ý‚ Ï3Q âÿb!4Ðú¸¹G ß3smX51ü]![ŒÑæˆf®OBÈgʉNËaˆdF SŒUE uP$ˆ ¸üÀÿâ€Z2:(„aà3ûÝ]Oáam«â· DôLð3™ÅÆ"߃q,°(½C#g@:ûñi\lÒˆ]–¥KÙ^ íÿJÉÓP/.5xâw4˜!bþ˜Žw£8ZéCߤ:À—B1sõÉÈü*äöç´”°=\“Þ[6›b@EÍÑñ!ÐÌÝ Æ_ê"ÐUн ‡ŸâÇs²}¥ÿ=Kf©í€„Ý]ºÿ$æP%àB-´?£Yfüøïˆ?Ã,Ϊ8ÙhOQÞq„jï_NF{JH±Å®yó¢y¶µ€›’AwL¸á©2v0´u¥xûw,İ:bõê‘8…p»À üêOŒ¬@ †Ã‡ÄÔ!€]@¿z‘HÄ0#bÆŒ˜8âãã±a -=,@1Ì@ÝÂ0 FÐhê¸@¦ŽQ€™ß¶jëÛIEND®B`‚procmail-lib-2009.1202/doc/article/slides.odp000066400000000000000000001546361130547513300206030ustar00rootroot00000000000000PKH=273&¬¨//mimetypeapplication/vnd.oasis.opendocument.presentationPKH=27Configurations2/statusbar/PKH=27'Configurations2/accelerator/current.xmlPKPKH=27Configurations2/floater/PKH=27Configurations2/popupmenu/PKH=27Configurations2/progressbar/PKH=27Configurations2/menubar/PKH=27Configurations2/toolbar/PKH=27Configurations2/images/Bitmaps/PKH=27-Pictures/200003980000CE300000A5287E783C84.wmfÍ}w¸TÅòmõô‘Œd#$gœsÎ9ç,ÉIrI*(HPDI‚(I$©ADA˜®®WÕ—ñÝ÷ûøg>û'_ݳkOÍZµVïÙ»ëŒr$лą„ øŸ8‰[ƒåBr”8ðÅ“¯âÅã#p/ó?AŽ|œð;áiþþ'æÙ+Êý ªžUÄq¯Ñßø"ü?ˆÚýŒËï—N²éñPͦ†Ö6 ô·ñ`¼ ÀÛi¥}JìcÚjÑûöÏ¿ã#ÎÃñ—Í!›žã}>ÞJ]Ì«ªƒyMµáŸC¡\¨#G[ŽšU¡b¨2ô±øO?;˜ÿw·}Çîµkì»Þ·ïÙïív{“ÏüeÚ„ô­ÍDlºnËÓ=[ŸžØv¤¨7ŧ!”„FQ C)i<¥æHÇñ ͦ×i¡ùTˆSAZNùi5ŸßFÙèSÊH'(]¦Ät‚l“±Iá¡Íwm>¸iKÀ5[.ÚzpÎ6‡Ó¶-|k;Â7¶3œ°Ýà¸íÉ?ãéÚP×åhÈQX'ÔÅt<]B¯T ‚ËT¢àbþYHÐßвà×´Ü㮃ð#×QøŠ þ}=ýÏëêü–WÅùûºª r]eƒøZúÀê O +€êÂÑ,´áf›ÂS¨á øJÀonAø’ÁE~÷¸GÇá2}Çi7ì¦÷a=­ƒy´FÓ èAc 1 €òÔ òQSHG5 .•áÕ| ~¶9à;¾.Ú”ð™M ;ùšÞnµëå¿Õüþ¬ß空}r÷sTqªÚÃvì ËqLÁq0gA'\pTÁ î‡x ²áYȈ—!;ï²Û >fçŸ@ŸB\ ñ9‚T1‘Ê…©TQ̬ª`Õ ‹¨XQƺj.¶R°‡Ú‡CÕIœ¨nàÛê .W‰í•Ù~¨ Ú=ª‚ýR5°ÇU{Zõ·Ô{UͰ7Ôb{G­±÷Ô{öÚnÿT»ì#µÇþ¥øó¥þXm›mÖÚ8°ÄƇ™üú› úòUØÆf€š6+³¹áe[^°%á1¾W±.|…-ÜÄz5÷œÕœêV³"¯Æ¼*²:¿óŠÜáÕºÁ«v…Wï¯â ^Í/yU?áÕÝ«¼šW{>¯úd^ýá|ôâNÚrG ¹³ªÜaiî´wœ‡;aXI*V”„•%`…¢4ÀЉ6ó=v6>pñïÝø·W¤ø[G¿[:á9Ž&qŽÆ1jœš¢æéÒT€cƒËÿÝ'/Œ,¨ÇiA0¶ ºä±E.]ºôsS8äx°Ò~­—qL£JzÇ>^nOh9ï‡a›ýF¿Ç±„ªèïòñû­–ó~öÛ“zÇFª®×Q5½“?µ§´œ÷Ãð­=­¿æø„jê8óñ {FËy? ×ìY}‰ãÕÑ_rœçã+ö;-çý0Ü·çôo稾>Mõô->¾gÏk9ï‡!@ßkk¿×7©¡þ‰ã ]ÐrÞC º¨“r<¢&úG>NF?h9ï‡!†.é,Ah®šéôtYgåˆqç|0¢+úUŽTÐJ'ƒ–:]Õ9伆ŠtM—ãxÚè,%éG]žCÎûahH?éz¯A{Úéô³®O×µœ÷ÃБÑÚqT€Nº tÔ-é†nO7µœ÷Ã0ˆnéþŒXºèZ=9@¿h9ï‡a"ÝÖã±-t×-9Þä|<ÝÑrÞÃazÀw‹ûz ÒK` þ”óƒô‡–ó~ÎÑC}†c Ñ9¾áã³ô§–ó~nÑ#}c/ ןp\áãôXËy? Ñ_úOŽãð¦>#õï|üˆžh9ï‡!><å§ôS}Fës<•ê¸ÒrÞCZ0:5Çm§or$ã㵜÷à ¬ÎÁñ&êG0A¿ÄÇ9´œ÷ÃPœ_*‘@MÖqÔ$]‹‚ Êy? Õ ¬Ì‘VMÕ©9ÊóqUÐA99·Ú„#—𡳩éº>7…8A9;Ä vá(ªfëBjÏ]qƒÝ ^PÎûañƒC9*«·uEŽ|< 弆i08™£‘š¯ësŒçã)((çý0,ƒÄÁÅÔ"ÝN-Ôóà…à9ï‡a ¶ ®ä˜Éû¼©Køx5¶Êy? ;펼Ï[±Û?侜÷ÃpˆÑ¾`Ôm¼ÏÛ̱ó/±]PÎ{z>0ÚŽýö‚ÞËq‚Ïbû œ÷Ãð £ÝàøÖþ s\ÅÁ›Ø1(çý0„í1Ç5{™÷à—õ>~‚‚rÞCbÛ)˜€ã¾½ªïrh>Nh;弆̶K0#xfí:5çm× œ÷ÃP€Ñ^áHÁ;°$¼ßËÁÇùl· œ÷ÃPžÑÊp¼Ì»²,¼ß+f»ËrÈy? õm`ŽB¼++Àû¼ê|\Ïö Êy? ­GEÞç•ã}^ >no{弆Á¶w°?#6¤»º.ýª{q>Ðö Êy? “mGGºÇ{ðßôh>žhû弆Ō¶€cï]ûÑïz¶í\È!çý0\±ƒƒ?pìä}ÞvÞçããKvHPÎûa¸Ïh¿q¦þ‚ã–¼Ç!çý0hXñïó‚øøu”ó~ª2ZeŽ´¼ÏKÍQŽF«pÈy? ÍiL° #ææ}^vŽúœ7¥±A9'£uã(Îû¼"ù¸; Êy? oÒøàpF¬Îû¼Êƒ8A‚rÞÃ,F›ÎÑœ÷yM8&ññ š”ó~V1ÚrŽ”÷àIƒ‹è­àJ9ï‡áCšÜƈ# 9ïÁ“7qþ>MÊy? _0ÚçÓ!%ïÁS÷òñš”ó±exþ·[áßF÷£~0ŠjñŽ2—^ek¸<¶È‘¿“´¶&,²µa–­ãmS`Û@;ÛjÙ¾PÔŽàÎ[ÇÎ…Û¸ ¾Á­°÷Â<Ãñ"´Æ;PC «$˜Q=4¯¨L)uÈÔTï›æj¹éª¦šAj¸«zšiª­™§š˜¥ª®Y­j˜µªºY§š±ÁFfL°¹y3ØÎ v7}ƒƒM—àÓ*8ßÔ®7ow›¢ÁoM®àM“.H&A0->ѯá/ºž×Ýðˆžˆ»ôjÜ ?ÅÅúNÕâHÌöѹm]Á6ÑMm-ÝÓVÒ£l)=ӾλÿzÍ«7ÚÜ»kGŸûÍAø›ÈÿMÍD§¦žS³‡Õœ|¦0A0þ¥ á-]ÏéîxX¿…;õ\¯?ÃEú"«yÌjR°š¼¶½®ÈjšÛšº·­¨ÇØ’z–-¬—ÙüzÍã”l±9µ\+9p}Pzù'UÿýºèØêt4‚&ÜK3,ØÑ ö2=ƒCMGÖÐ"8ÏÔ ®e ›bÁ£&oð’ÉüÃ$ &@| èbø³®‹gyUé±¼*Kp³þWè¯pŽþ'è§8L'·½tN^™R¶©®cëèö¶²`Ëêq¶ëyW'¯NnkŸÅ:y8ò>‹WþŽeöU=‡Wu<û1ÐVÐl5]ÏÖ×¥m Ëvfïúê{ø3NÒÇqžÞ«õRܪÇãÝêú|•À›:ÿÔ‰0üÓ¤ ^1YƒÇLþà.S2ø®©\`'™ÖÁá¼–}LŸ`g38ØÚŒ 6ãµ–hú,šp4v1úYŒ Š—ÿíulÖ ·É`²‡q/ãLúàtîk¡IÄþ«à‡æ±>`~Õ§Ì5ý³9«›#:!ëɺ ³¾j¬³ ëˆ#ôTì£WbGý6åu¨­/cEý×qÙ·´|½ä±Yt ›VW³Éuc›H·³qu«xMl@b Ç g1Øèÿ„ÒƒžE/dßè&6 ïòSé’6_¯1:=¯Y<[H?ÄR5s«yØIÏ®z öÐã±·…ý´ÔÅ–qРA'c^5s©¹˜]-Ƶ³¨õî·V­õ2l§`G=»h©ósÏZŠYÕ*̬ÞÅ ê=L«>ÀÔj7ÖÓ;°¡Þ†MôFl¦×`K-u~îË[1ÚŽ©Ô'˜B}†IÕ—˜XÇ*ú0Vןc-½ëê±–:?ÏžÏ1‰:„‰˜%¾:‰qÜïÁ®`}Ëé3XQŸÀÊú(VÓR[ÆÆG`ƒ¿C›Wæ×O± ~ˆ…ôoXDK]l«U«ñ ³X¼Aû+$´¿@R{ÒØÂf׉m.ÏæÑÊæÓR[Æ *D`LÌ,Éí fù 2Ù«c/C›Ng·u›E§·Yu*›MK]lK”(13³d³—˜å"¼jÏÃëö,”¶Éu1›R¿f_ÔùlZÓfÐR燱 =Eíf9ì7îw³um|]Ã&ÔoØtY›L·)´ÔÅ–±P¡B+1Ku{œYŽB#{šÛƒÐÞ‚neº©£ëÛxº&³KÆ&ö´µ ³ý z<û]ó@ûW`€}èmC®m¬ÒR[ÆÈßdjÝ£°îÛU78c%-räïÝu™ÒÁhˆKc‰hd 9 ¤£~êÈGíŨy Õ Ô£ª6T&Ћ^Œ ¼)XHéë(y`;% 8EOÔt_= _”†k*%|¯bà”*ÇU8¤ªÃ~ÕöªV°Ku„TWØ¡D™ô[UÏŸHÂ~M…Ã*-d¥ùÉpPI[ätéÒE@´ÉpÃN…›VP%õJDüNY'ÄqF§Ä1qN'ÅQqV§Åqq^V@VBVDVFVHVJVLVNVPVRVTVVVXVZV\V^®€­!MïP\ZE‰h%'F¤9CS)£b4œ*Q?ªG]© µ¦^ÔˆFPMšB¹²­£×h;å¡üŽS”ž~¤ô€’†¥„§6þ°á®-ÃîU‡k¶\²­à{Û¾³]ᬕk[|ˆ­£×OöG›;GóB*J¬ÒPBõÅQùÉ@yºMègèCßÁT:ïÒÇp€ÖÁešOh"¤€! ºCIh Õ )4pª0DU„ª8ŒQ`‚ÊST:˜©’À<îe±zD+ÕmZ§.Óf^‘Ô!Ú©vÓ>µ¾Pë訚Eß©!t]µ¡Gª*Å ¢Ô¼ 14”'’ò¤Ï÷i+–~¥sQ JD‘(…¢T‹rq@œGÄqHœ’N^ ø*-䤇PœnB-:íé( ¥=0‹Þƒu´¶ÑbØMsáÍ€S4‰ñÇÂmh ZºA:èÙ¡ àîŠC#¨õ Ôâ«»>ÿݧ&üy|™R«šÌVú©—)S@òXßsÏŸ€Ü‡Ò+¤#€ìUÊ¥$ÿw;È0r/z‘ÑR)AíE¹•ä±E~ðàÁ? #é[ú9òH® ¹V_ ×r…DsÍ>0—žƒž›PgjFíùnÒš:RsêNM¨/5 ÁT‡FR ¾ëTáØ#i' æk°/}Ýé èH‡¡5ƒfô cœv8±íˆª½üœŽr¸Ž’C' 9ºpt¥1c9Æs>ϿůOböÉ.:ðqþ„uà×;Ò8Ž1îý±íäù߇†;9Eeá4Ç޳TŽ£_†_/Ãu¥YIi¾ŽJq”äãÅÝûÿÝuîd`dY‰œÌœ-‚'1Ï|ÉËøçöoåqïm'Uª­ŠðM-i"5å}j#šMõi>?=–ðÎtUã]ieÚÄ;ÔM4€ó¹aüÚH®͵ãø=ùÏdΦ“àø™bx7û‘씆#c@r?È…)~ 0]PEèŽxÉc‹ynú¿»© }G³›ŠŒœz1ZOFßÏè\î ù#ÉÈi9Ò+Éý —‚Jª({,^—‚ Jr?È%¡÷³•‹( =•ä~®âЗç”JŒXÁ¡Jþïö"ad¤V¼·lƯ4ähª$÷ƒ<•qüÁw»|»ïòØ"GžRCm•*«ÜP‚£‚’üß=·Âȯ°Çy¡äßȯDqmDþ;TÒ@]‡îWr?n|Å»ä¯Üß´®ð(¹7®ñ¼q•çŽ0²ä~Ü8NgZ¸_ÉcÝósç»ðp„gÛƒô#Ç·üœºÁñ?£Ð-Ãóç¼TŽ!¾CTA_ͨkéWÞi=àÖS÷Ú¿[Õÿ;óPÕ`(ÚǨœ0M%ƒEê1mPi—ú”ŽªÕtQM _U7BU‡^£ ì”#† ð$÷z !培i)K '¥ çûR-úKµ§_ÔP¾óÍ¢cj}ª¶1ÞnúP¢÷Ô)zW]¦Uê6-QH~ 2K%q¿‘ߎŒV`8ßy©Š<•×€^ªtWÒglGžÇq÷#)O`0åôåy´; t¤âÖT:ÐŒÊШftOµ¦;ª#ÝTÝé'Õ—®¨ÁìÆH:§ÆÑi%8ÿÔÑ¿.=Ìt=¼ía—j {TCø”Påá*ÇT8©2Áw¼ —øÝ?©‡t[Ý ßÕ÷ôX#Ë+'ð%¬£””50ˆ rßåU¨^ µ d¥Þ4,ŸÆºˆ÷,ârÄ¡1Ïb´‹¸4ÊE2ÈB=©Uà ªhIeÙ›é”9°–’Þ§}|E!užªëtWýÁž(¸ª’•NóÝæ„zލrð…ªŸñjíQ-Xc;øÈEûgÑÁÅÇ;ŸÅ.ÕþYü·W±ñ0 ÅQéÉ@.úJÐOP‹ÎB{þœ¥]¼OÝÄŸ—å°•Â.z¾ é<Ù¾x¿ÎÓÞ}ž™ õ…øÐRB'Èì~ãÕ A~n7€7 Ôr¿oªµŸE5Ý+ÿ‰Úÿ© õ¡44†Âü¹Ê­! tàÏqWH½ÀÒxÀÓåMi|KSàKš»i>l£%<)­âýöN{xþ? uè<”âÏ|~¦e$ É(ž’HJñ]$qO½@qŸE•äYüoÆîßßΰUBm¡J¨&³’Çö3ùï {“ÒÑ›T˜VÛmvµ]j%ÿwwøWr*×ó »Ün°[ìû©½hO؇öŠMD÷lV²öuzªRjF¹¨+¢TŠFQ%z‹ªóν6ïÙëP“G‰îØèýŸWãk®4P-Ô zÛ™6}žE_³8f»èc縨Á|ÕŸE5m8Z?‹VÇ?­jä§«¬ät*锊BÉýì*™óPÑ܆<æ d5¿ºÜÏŽ ŒÜ„ ƒ¹òó¯—ð·oLBUÅÄQµ ¨Fƒ0•æþ‹˜ß¡€yèôH—&›÷9@os:›/]îÇ¥0ò*s6˜ƒQ!Gvé-ó#Lã§èÛæ{XbÎ:aÇý0G` 9îôH—6›e°Él…9fŸÓ!¹—ÂÈÌgð•ù *äÈ.m4'`«9 ±÷{ÍçŽA˜ÖrÿËÍX`v9=RçÇ¥¯Íd8n–Àv³ÑéÜKaäŸÍføÕ, 9²KÇÌnøÖ|çØûËf‹c¦CÜÿgfì2k©óãÒ=3ã-8kæ;’ûq)ŒBRœrd—îšwyߺž°÷ ;aú…ûÿÑL‡‹f¶Ó#u~\zC vƒ8„»»ÜKaä8 *`¨#»”'Cùp4ÆŽA˜22Kjì I°¿Ó#u~\z+p4‚¼ØÁéÜKaä–Ø:aÓ¨#»TBUìuØ•ÆØÕ1SYlŰ9ÄÖNÔùq©+æ‡.Xjc§Cr?.…‘Gc}˜„•¢BŽìR'l =°ôgW†aCÇ Lí°"4ÇÊЫ;=RçÇ¥©˜¦`>è‹%Éý¸F^e`#¾rd—&cM˜U`»²Ë9a`$¾ƒ°ˆÓ#u~\Ú‡–öaRXƒ™˜1™Ëý¸F>‹/Á%Lrd—öðjîÇÜp³Ã7ã„i'&‡÷1¯IZ§gO4WoD—®âmº‚†aB§Cr?.…‘cb ¤¨#»t ÓÃO˜n³+÷1 ƒ0}ÏýŸBÇ0ˆ©óãRÀ~GÊÞ¢[øØéÜKaätö eµw¢BŽìØxÇ ±µ”Ò†ƒ0…¸ÿ‡x—îâ§Gêü¸”Í lö %´?9’ûq)Œ\Ê^§Jö\TÈ‘]б)§½GùÙû"ö¦c¦ÌÜ{’ÙËNÔùq©©]KMìÇTÆdÆ]$¹—ÂÈ}ìab?‰ 9²KÙö$µ·_S7{Ô1S=ÝKí~§§q4WoD—†ÛÙ4ܾCmíN‡ä~\ #ϱÛi‰]rd—†òUù¦ÝGØûiö#Ç L¹ÿ^vu¶ï9=C£¹z#º´Üޤev&·ËÉý¸FÞaWÒ^;'*äÈ.-±[i•ÝHëÙû­vµc¦Üÿ,;&ÛENÔùq)ÏÒñÍ~ø-ô Üp¹—ÂÈ/™“Ë|rd—âš+Ø\€”æ;HoN;a ˜ „‡¡¯œ©óãR^ž¥ó˜÷ ¹ÙãtHîÇ¥0r³ª›mQ!Gv)·9ùÍax])e>s ”ûÏd>„ÍÇNÔùq©ÏÒ5Í"(dÖ;’ûq)ŒÜÑl„žfiTÈ‘]ªavA]³š°÷­ÍfÇ L•¹ÿ²f3ï8=RçÇ¥¾¦?ô1 ‘™ëtHîÇ¥0ò$3f™IQ!Gv©—Y ÌJÎÞ5 ƒ0uãþÛ›©ÐÂÌtz¤ÎKo›Ö0Çô…¡f´Ó!¹—ÂÈÍXøÀ ˆ 9²K³Íl˜o¦ÉßkkÌxÇ LÓ¸ÿ f0¼i†;=RçÇ¥¦:l7-a‰éátHîÇ¥0ò1Ó N›6Q!GvéC3vš!ð){Ðôq ´…û×´‡•¦³Ó#u~\:gŠÀw¦*ì5MœÉý¸FþÍ4ƒG¦FTÈ‘]:cºÂÓ®±÷·L Ç LßrÿGMm8`ê;=RçÇ¥'&þ2…ኩètHîÇ¥0r2|ÒbѨ#»ôØ4cê€Æ«8azÀýß1%àgSÆé‘:?.eà™:=¾ 8’ûq)Œü„ørTÈ‘]J‡å 3–„ììý+XÈ1S*Œ0ÄÅŠæêèÒ›˜¾·Yh¿ÍçtHîÇ¥0ò}û*=±1Q!Gvéœ-C—lqú™]¹c_s ÂtÚf¥ã6´¹œ©óã’±OlÈ&¢m:§Cr?.…‘SRFÊ@I¢BŽìÒS›‡Èf§¸”•^ ÌŽA˜þ´/Ðo6Ý´©œ©óã’ÅN„8„~·x¯1Œ$÷ãR9µìžžÑ Gv)„ I¹'¾<ù§:azÌýÿŽoòÎl¬Ó#u~\zÉÖ£,¶ŵýÉý¸F.jº§g4È‘]ÊlÇÓËî‰/OþÁŽA˜ÒÙN”Âv£D¶—Ó#u~\ª`KSy[‡rÙÖN‡ä~\ #7³mÝ. äÈ.•³}è ~â×dïØöŽA˜Jrÿ…ùÙ–Ÿ{¢Gêü¸4˜ïzƒlAjiËñ^£IîÇ¥0ò [Á==£AŽìÒ@vc˜{âWå'%Ç L}¸ÿ®¶(¯II§g`4WoD—ñ]o¡ÍD£ì+N‡ä~\ #o³ùÝÓ3äÈ.-à«r)?ñßaï7òóM„i÷?Õ¾LãmN§gA4WoD—öØÇv·MH«lZ§Cr?.…‘OÙôîé rd—vÙÜô©{â¿ÄOþŒŽA˜v0Ë›”wš)©óãRFoÌL¥m^þLg&Éý¸FîÍ;¹J£AŽìRCÞ56wŸ,ù„p ÂT—û¯Æ;³ 6‡Ó#u~\fÙ¡6>ÏËÑ Gv©)?ÃZ¹û܇â’0Sî¿&O‹oXtz¤ÎK#í×v„½bÛÛßœÉý¸Fžkw÷¤h#»4Ü’Í÷Ÿ·Øûöc¦AÜo{Ýv±¿8=RçÇ¥U˜Vb1z +Ó(þlKîÇ¥0òN¬êîxÑ Gvi6¡5XŸ6amú€ïI L‹™åm,MÓ°¼Ó#u~\:€Ééf£ øšÓ!¹—ÂÈßãëîÎ rd—öcE:ÈwéãìÊi,ê„i/æ 07mÅ|NÔùqé:¢ý“Ñ1ÌìtHîÇ¥0²Á¬ä;D4È‘]ú Ð-ÌC÷Ø•Gø²c¦Ë˜‚ÎajúÓ9=RçÇ¥’ö¸-a/[‹ŠZÉý¸F®oï¹;^4ÈÏw)ü7€¼È»Æô¼_ÊÊwïÜ|ç.Äû£Ò|×®Ì{¦Úö¾cæ"öªÍo²Ùí-›ïSÉùõ\àzÑ+8~´¶²»lKû•h/ºû¯ä~Ö'Œ\Ñ~ïŒ 9âµÖÂÞ¶mÝ]\îæ—\ïÂÔ˜YêØomU{ƱJ—>µ'ì>^“‡¼‘ßÉJîÇ¥0òZ^yyFƒ¹çÑŒ9Ê~Ì~p¨’ûé9ŒÜÉt«rÄ•½hSÓU÷ÛèÄôïûÄoqg';ó¾½a7òŠŠSRç‡q™½cßqÈÂpÙ¹%Ú†²®~v¯ín÷;RçǽPh< ­†oCŸÀ‘Ð{.÷³âaäæCHoÖF…ù¾u+ôÜ †ßC_£Ð~0¡½ Í.H`>‚$f»cæG¡wà~h-×®‡ŸC›árhœm‡Ó¡^Áñãb&32šÜÅ2§Sr?.†‘ ›PÊÌŽ ùþ=ó¼dÖCN³ò›UŽA˜^4³ ©yâ›…NÔùq©¬éeÌ0Èn&;’ûq)ŒÜØL…ÖfdTÈÿðï˜ÅPÁ̃jìJ]3Ý1S1î¿ yÌx§Gêü¸ÔÞ4€v¦T1Éý¸FfÃXÓ5*äø÷ ÌDèdÆ@Oö~€ê„©÷ßÐô€Z¦Ó#u~\š`ÊÂxSº›¶N‡ä~\ #/5íaird—Æ™~0Éô„™ìý|ÓÑ1Ó›Üÿ`Óú˜NÔùqé]“Ö™Ò0ÝÔt:$÷ãRyŸ© M¹¨#»´Ö´‚¦)¼ÏÞï4uƒ0­äþ™Š0ÇTqz¤ÎKGLŽÜ°Õs:$÷ãRùª)·Ì+Q!Gvé©ÇM%8ÍÞ_0¥ƒ0àþ÷˜°Ãrz¤ÎKwŒ†Û&5œ4ÙœÉý¸F`Hˆi£BŽìÒ/æuøÍ¼ ²÷Æär Âô3÷Éd€ïL§Gêü¸ôþN‰QÁ&™Ó!¹—ÂÈÙ0¼‚Á¨#»”³B2ÌiØû̘Ê1S\Ô@&üe9=RçÇ¥øÀß(5"‰Éý¸F®‚Duð~TÈ‘]ʇ/@!Œ%ØûòìŽ0Snî?RüËé‘:?.ÕÇ#T/P1üÅéÜKaänx‡úᥨ#»TŸR#ü“Z²÷ð®c¦Ü%¼J¥ñg§Gêü¸4wÐàI| \m„yJ¿Z BËà¯ÐbÇ(ÌWC“ùõip*4¾ Í…¡E°‡k> ­rzÇ‹ñxß×ô‡»¡±N§ä~\ #gæI1‡räÏGžÒòÄžœ×&-OV LÀ“Ö“ÐPvs¤Ó#u~\ÊÍûî\¦5$5½œÉý¸F.Ç“bUÓ.*äÈ.åä)ýžØ ±÷%x²aŠáþ3ð–Ч1Ñ#u~\ªÉûî¦:4ÍœÉý¸FîÀ“bS+*äÈ.U3Ý¡OìÙûV†ƒ0ýÎýÿbîÒæÓ#u~\J(ž!2?9’ûq)Œ\¯Sq<rd—Ò𔞠ïQ6¼Myñ¦c¦”ø%Æï)^vz¤ÎK¥p+•Äýƒß8’ûq)ŒÜOR ü"*äÈ.•à)½,^¤ÊìJ-<í„éuî??Oa9ñ+§Gêü¸Ô—P+|*á§Cr?.…‘á>z·E…Ù¥–<¥·ã‰½+{ß?s ÂÔ„û¯‹R5ž„EÔùqi,¾EcxrìŒëÉý¸F^„i. 9²K£xJŸÀû4öþmÜì„i8÷?WPO|Çé‘:?.}jçCanhL q¹—ÂÈ¿‡†ðŒÚ-*äÈÓðæÐ ØZ ;yzÿ<4‹'ã)Ì4~ ½ wBã0Ÿu…c¡ž°?Ô'à¡<í‚•¡‰°04Õé?.†Beái¨>\ µu:%÷ãb9…ééM£¨#_kOØËîÄáy.1O2 LC y n7B-œ©óãR&ÞÇf2e@óŒ$:$÷ãRùuSJ›òQ!ÿÓ·þ­à%Ó”§Ý†P€'a¦4<¹$3!O4¢'ƒ·o×Êñ>¶¬É9x’ûq)ŒÜÄ”„6&_TÈÿô­u¨Ès\uv¥O2 LŹÿ×LÈËè)Í߸ößú¡yªò4 :$÷ãRy˜É cMº¨#»Ô–g»N<ÇõdWð$# ÂÔ‚ûoh2B-žhDOÛhþƵøÖÿ>Mà²î< ˆÉý¸F^fRÂZ'*äúÖ?&ñ7“½_À“Œ0Ó(}y¢=ã¢ù×"º´Þ\¢wÍ=šÁ3’èÜKaäO À!ž)¢Aþ§oý“À&žã>`ïwq¹0Ó*î±ù“Þ6Oœ©óãÒQs”Ž˜‹´g$Ñ!¹—ÂÈWͯtË\Ž 9²K‡MˆŽ›Gtš½¿`~s Ât€ûßc®ÑsÝé‘:?.Ý1Ñs˜NòŒ':$÷ãR9€ç)ÏÑ ÿÓ·þ7é7ó#O»—ɘ ŽA˜®sÿ—Í×tΜtz¤ÎKIp5½Àû܇æ€Ó!¹—ÂÈÙñKÊÇ3E4Èÿô­ÿiJŽ'(-{Ÿ…ç:a¦xø~BOÌ>§'Q4ãZD—^ÅTWÒ‹<#‰Éý¸F®‚ïSž)¢AŽìR~ží ánžv?¦ò<× ƒ0åæþcpeà‰FôH—êã0ªÓ¨ÏH¢Cr?.…‘»á2ê3£Bþ§oý7S#|—§Ýw¨Ïu L5¹ÿ7p•ÁùNÔùq)ü}êœëæÕ¨¾O}®–Â9-ìÄOi7OîŸñLzwÐq^ñS<ٟ畾ijª|ƒ+Ìp,­Åq<1O¤e8‰âTžqgÐ œíºZϵkù=ïà&ZÍï—ï”Ûþ騔§êîÔ‚µË:Nâ¿ÖŒ|•„‘×àçj4È‘çÜþ¸ã<ÁÃé4'³cãi1ŽfwÞtŒÂ< {òšö¦áØŸ¯Ó!ÔƒÏwäšÖ\+zû{ûûNzbEꉨë,m©gÿÕTdÃÈã±³s0äÈ.6ÇQÔŠiC©+¤ÞØqÿ#ع1ØÅ1 sWlÌŸÅf\Û’³¶ºØªóëopèœ×Ñ«®£azh L M‚1¡ñ0,ô& …!¡Á024Æ…úÂTžÊ焺ÀÂPXj+Cm`'ŸßêÛ¸f#ׯæ÷- …¹¡‰0“±Óϯ ÕrŒÒUÏP—ûÑýk¨ÜÕ«¡šð}¨2œ •‡ïBeáB¨4\ •€ë¡¢p;T~„‡¡üð(”’ð¬Ø”…ø¦L%ÀPUxª¸«ßBu¦ÝC£tuõvw¼ÏBí=ÞÞç‰o¯ÏZž—³¦Eæ[Zb¾¡æ8­áYg£9ĺ¾à©p?íâÝün³—Nñüó­9ÁSäI:dÎÐçæOŽècž ?d?ÓÏî1›£t%ÎJîÇÝ0ògæsÖp˜¾6Çœ® 注X"»{Ñ¡ïØÁox:Âl_˜tÐ|ÌSðv:aÞ§3f 3n¢+f=ýdÖòt¹†Ðì ÏÍ.ºoöЯæSºÁ]^3_Ò%îT0ý¸{ÃÌqŒÒ•h–Ü»aäÛfkØJ™®8¼ï†%²»qq)Þ?5éfûͬ ßÍrž8—ðä¹ÈÌcÆ9”ç”$d»ÑQÛƒ$÷ƒ|Ë6§ë¶ =´µé±­G’ûA~‘ÊR *Í^¦ìT„$ÿß5È?ÿPKÿ©òI9ÈÒPKH=27-Pictures/20000033000489FF000675C0FD0A4C7E.wmf­–_HSQÇww§9­éî½›®&á¦s»›ssLúRöô‡‚ûP"ù`dj‘½TÆ‚FHôP²¬èÁ B|’ºQõRX!a=,‰Öù©³u çÂs?ç·óùÞ —#€@Ø@ÀxY‰Bc€"ÎàÝFƒÂª½…»¾¦iÿß.þ~ƒ €‰¿ØLssóâl˜ s2ŸšÍfÁµØ–ÖYØX)èTúš|R{ãSï¸Úÿ,ˆ¼°–®ÜjÃR:siâüø¥æº½½½ÿ<ËJÉçÅ®8&c"À»mȹœ•Ì©ÔZÌcRQbLRc6_Âcóm ó1‹bAÍhÅ/qä|æÉÉG«˜íóf3´«£RF=ÉjÖ˜–E%-4dÔCjFMÊíj½Œý|ISSSkH¢ðÁB¡ÕºX…Ë)Üfu5Љ˜Œ}>»…&4âÚYÀÏœ–÷–¦å­öŒª˜2jÖ„œÏ¬i»Öd¾ïJËg*>ûrF=(#ózæ  ßä ö&1™—ù‰‹ÂÍòŸÂCgZî¨@æõ_»tÒX©“ n 2/óQf¨ÒII…!72/óWf=P­“A…h2/s7³~ôêÄï¥0îAæe6ùtÒ¡êdÔGa™—ù³þöëd‡ŸÂ{2/³; “Ë5:y ÐæGæe~À¬ŽZ R˜ ó271ë½Nfj)\ "ó2¿dÖhNÎ…)È!d^æ$³ŽGtR¡p'ŒÌÇœ²ü¨Õ¤¹&¥,§j‘y™•°&m®Ó¤ëá”åZ™—9ʬ Mz\—²Œ„‘y™÷3k2ªIo#)Ë«:d^æNf=Ó¤L4eùAæõåï(¥°[¢@¬i¹ÚŽÌÇ<,Ø”aርÇ4cï1ݵ!ó1÷›Cö~swiÂzÅ‘°n/CÎg^ý •3; Ý̺iÞê,LÚ‘ó™²y͆[¶!ñ«AeÀЪ /g^ÍÑb”ìÇÉaVŠ­Å8¡ ¯×ÑVlª¿X²•9ÞVü<†¼^‡ÇÚSß,½`Õ÷XcqäÿËí»qE#ž"Ó²×…gÜ©rù}7‚ˆÛ PKfÃÈ- PKH=27yå?:ÍÍ-Pictures/100000000000003C0000003ADFD79719.png‰PNG  IHDR<:ÉÎe³bKGDþðˆü) cmPPJCmp0712øêÌ`•ÇZÖÛòÊÁôhCæ5²¿¹eªÅFê°À‚< ”^ÆÍ(âÌÚÛÇ ›Ü]·çT\ÀºžƒÕ°'ÝŽ¿¦·šcæ.2Û—üh#¢ãÌò¬3ÏãÞh5"/€Ýw":ˆ|¾8µ¬¿ÎO$_ü÷ùùUH%‚Âg­Gƒ*]¹ÞeQâ¤ìþÁDã+PK#ƒñL ׬»ÕqxH'j>“6mÛHR6¢Vk9¶ö½FÛì¹ÌzüãUÎ'wË6GRš1RŠÙ NRaCDyÓÌ û'Ÿr©ñ…)ÎP@¾Þ¤3$Ò ÓÆKÛÓ?;>ÉÚ´Ûk‹X2pèxIƽå7ÁÐâ+Þ4Áù³n{c+f[èÙì4;1Øûaóò*ÄÑÝÙ|´ºRjÛ| ‘¼áÈ7-æ6–#âþý× Ù¦•ô¥ÔÈ…¼ìu̪&0ZšÅg±T%…Fo¨jÅÁ;÷¹TœEÜÓoU]ö-Ý®ûŸ‚ýª‡é‰~‚á&tEXtCommentOptimized by Ulead SmartSaver!)ãö·IEND®B`‚PKH=27*žyø,ø,-Pictures/100000000000021D0000010D41049910.png‰PNG  IHDR œ€'ÓgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEôôô®®®f†¹yyyÕæø¢ÆìåãÞ]}²q‘ÂÆÆÆþÓ]u–ÆŽ±Û%%%yšÉóòñŸ‡cÝÚÓò©:€€€&B‚ÛÛÛ(D„èèè¶ÔóYy®ˆªÖ;}žÍ $jºººáÞØ¬U ßßßm¿îŒ.(ŽÈiмÙÕÎ-qûûú1M‹4PŽ’´ÞNl¤”””Š¬Ø†¨Õ¡¡¡Fj8U’ëq’!<}ªö²W¥Èïkkk.J‰Jh¡ 9{¢Ð_~³°“¶à‚¤Ñ~ Î=Z•EFFœA^™ÀèEcéòü›¾æ­Ïñ™¼å²ÝŒ®ÙÉ+„¦Ò0tRq¨Gež†††ÿÿÿUt«zœÊnŽÀÖÒËß²Œ`€´öööc‚¶ÕÕÕhˆº–pH6xÑm*3vTr©B`š^^^Kj¢Pn¦ ­íy#ÊðŽŽŽ6S (m?OmÀÚõQQQ ÄëŸÂêë¦or¶æææs”ÄWv¬È—o´´´ò̧É;›››¡ÏQp§l‚©R9®ƒ=W‡öúþ[z¯é˜C>\—Ÿ #AO'-L¥Ö+G‡ÅßýÔÐÈ*o,5UÊÊÊ¢ýýýùùùìììâââÑÑÑÏÏÏÐÐÐþþþáááÕÑÉ&&·ÙÙÙ¬«HfŸIg –¹â—ºã;X”üüûèæâÚ×Ð×ÓÌõôóíëèžÂé÷öõœ¿ç…§Ôw˜È˜»äùø÷Xw­d„·\{°ñðïïî땸áüüüøøøúùùëéåîîîýýü?]˜#?€ãããþþÿíííoÁš½æb‚µkŒ¾ýþÿ£Çîr“Ã|˘»ãv—ÇMk£ŸÃêCa›cƒ·š½åÁ镸âaµ××ׯ~ÂÓÓÓñöýüýþùûþáíúúüþ¼p¸ß >OABh´ÝþÁ:•yn‚¿âHx­“Š{^¼Œ²ô$SpŒ™’еÎC?D]6 '²˜‹ˆŽžÆæ‘Èæ999]oW`|àYåh Š)~IDATxÚb˜< F*X¸paLÌ:uõµBB llknس[`ý¦í4Wž1þüˆ€b˜1 F@ÀÔ1š‰FËe@¦ŽÑÔ;u “~[ˆã€—&ŠòHñäJò'J)BÊìŒ8 %IˆšÖy2Γ]žX^ÃýñlݬMݳi1îf»»=óF|¿¿»ßCŸ×ð!;þsE=ø†|ÛÔ u웣¦¨_7ÕCÜûf¨aj„Š“¾GÏ q …Â*:¶m¯yv€$I²,Ï‚sT­VÇкǢ]âär¹^$Šâ3hC àÔëõRéÐqœ|>ßBƒÄ;bf¼¢vdšf"‘è *•Êê{¨\.÷ƒe$ÂÏ8Øôth”XDº®)Š¢ªêg6‰Djµ7–e5M …\×M§¯-Ëây¾•0 c]Rë  Æã©T h6ÃáF#™üùýþ(£Ñ?„š:Z[ßË ~M£©’:–:¾Çʵþ}ÛúîM±ðKÁÑÔ1üSZûS¿ÿ,0qD,uÔ5XX4üøüëçkÁ—/GSÇðO(íC‘”vÇLHê xêಈ­hûøâéÓo_¾ §fꈈ )uDDh¡Ôtúhê rê×3d”眷x&B’¨ì@IÚ ‚R³€èU¤áIGŽ“Çhê ]ê hêøó/O¥[%×äÿת*÷—\ɸS¸Ý¡‚‘:"`EöÔ+<@4$u€RJê¦ ´²#½ì€¨©Ã$0Z³Ð$u¬Ïô?OEE±ß¨ªêy#—ž²’:B0ËŽpña®X°”híqX«–:@‰‘: [ꀷ;FSÍS@ÁRG‰J^ês#£6.®69D«Wê¡rê'rRÇhÍBvꨬ´µåãÓ:>’î,=òrsMr?¼L-–CêÑBZ¥ f)¢G I!`^Rê€T-8Z¥ØSžV)–Ô± Q³Œ¶J©:0z´O_=‚‚þ™˜äæ~PœJ¥‘tPÒ+Êc¥„˜…ûûÍØBû¿Ê¦Ž:D@ <<¼ @O¯ ˜:êå9§Í»-vLbÖn†xhê ä9Úâ/@0utD¤w((--ÍÌ´b /hÕ+Óéã0u̘? €F×wŒÎàãžÁ ÑÔ1š:p§€]98ºr÷ÊA€M£©wê ÑÔ1š:p§€M£©wê ÑÔ1š:p§€M£©wê ÑÔ1š:p§€Âš:\ ìJO_¸RîW*©a© €PR‡+LvÅNyHHbWå •#0ƒˆ‘"9u¸b˜Ï×ÑÔ+ujê N®h©Wê (›báJž!£©ƒ’Ô1”:Kêç}¬yÛ)w»bU⊢ŽpÄNKà@¶IÈfº«+ÎhG5‡s‘\‹§Di©c8uŽš{à iœ5 ,Ò©Oê Æ”„€”~]æã+€\ ¸æãÉx|=‚S@á(;\]qf5âRR:Ãj"Rp7]à$¬8é„JÀ ¢Rî"¥½5š:j€Â•:ðÔæÄ–“ñ¥ŽÉ“IHÈeº4îhÇ0¯C&¦ÌV)@áId•(qB ñJ|ê@J æO&6uJ¦£©#ui­Rh›Z¶ã˵®®®øº0pƒpöhQ›”“]±Ô,xzƘ­RÜÍìÑV)ÎÔ@£c¥#w<Œpê Ì>‹+þ1,ü¹‹° „*WJŒ˜L¹+02š:ÐR@–#N4š:FSîÔ@£©c4uàN4š:FSîÔ@àÔ!2 F(€ï…cdDÝ §¹o0u8uŒ> °€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€BIà)) —z×lò8•ã”qÅÁ9€I®DHàBxÃqÅ"çŠÃ¡`qW˜nW8ˆÀ©ƒØ‹p%:RI4‚§A„Vvr,ñ¸b%àÒáŠÓ ¨:x8%HôN‡¸âJp8Å]Ѳ‘+ ±‹;w¸R\`7‚wê B©Ã•²ƒÄäíJ¬bËW" @þÄ•\]±€d0r!LJê FÙA­² €FS©Ý¨ºýÔ€Ï*:(A´;°ÿ$ï#S0_—rülÂy·Y¢þâ”%Kðu7QL®œbÎÐÚÜ ¹mÄÔ‚Œ” påŽâI¥‹s7´uüM;vФrb°Då¬âJ)®$hoºÖc;>-c€aN–òv`•lŸ4±}~ <²é·¾ö( æê‚•¨ùÌ#T†ÉêqŽÕ)¤‰ :œ“TŸ§øÈûv=ï anZm&*Ô‘&“1¾T÷+×ïÝñÀwå‚ ôtªÛ·µ¶Dž}õ4tνÃþ¾”“õjª§b/P'¢z3-î‘d± À«hšée¤­‡"5¥%ûY^âò’1F&fpü&Ë€°²;aðtîU¾í½Š‡@¬>’ðÛã󲨠};¬K×Á=\ÈN“7·VÈ·†¤Çö1)ëWhÚKÐ}„­4®!M…T$‘î}\¨Gâ–¡ãf=´ìšI–™þlÇ)€°¦WDj§FêÀZ³àO¸³‹+j¦G’•˜±…³¼Ê,©èÔQ‰%rQÄ!)v©[‚!œ:2Ô€Î28†aàÝÊ;t•›½Ÿ(%+—‰I¡DGÉ)KW¼ábIZ8D31C#Hb¿\Ú'¶Dˆ,ßE§ƒÿÞc€î;œEGýÓÕüK£éÐc°K§ƒ™—…ƵzÇs¢ã€k»´Ý';°J·¯E^§¦M¨Bš:H ñûìÃ<ˆâyWDG0 RÇ¡Ý ñp—4š:Ftꨖ8İwá@”¦lþèÐÄIJÇ$vÇkâL4:ƒ?¢S‡˜Rõ!†8S@¦ŽÁf Tê¸-vìÃ̸Ü@£©cD§ŽD±Ù³ð¤€M£©wê ÑÔ1š:p§€M£©wê ’Rµu)©ƒ–Gi¢‡˜+±±À"¬†D 'üHJ2h”˜‡JËà×G\ê -;ðæJDz¥fZ®t(e\É);p$È’2øõ•:hЦ¢W´ަt9`)!ƒ%1ž:}mÒ„¯@UèŠåÄž)ÏJÀZ°¢°m}&S¬”@a™:ˆf©{q‚±ÈË–IÔ3/±BjêÀ^)FàZäHFêpÅe'ªéôK(摟:-u¸b?ŠG&G^„ŠçÄQôE£Èy k˜G`T=(¥ÁvÚ©ª®Ø˜I£åŠK=zêpÅÙ\rE¯Y°¬ÞÅš:p¶;dZØR¼]+ƒ+uÙî Rú,h+JÑ¡¢ztŸ‘+úaØð.¢ý޲„åƒÔ §æÏß11Þa¨ÎŒÔgŸïŠvÚá§èþC8"…F^ÖŠmI-ªç]Q›°®èý˜u”Õ»°†#$ÂQÚ‘ð>‹ ¢Ïk»B:,O+Ý0u20"@|Ÿ €°Ô,4Î nltž…< ƒwxƒÔñ€MÃlN†”ÄA(uæxÖ‰1ÚOAŒèŨԜ£•!!qJ4:ƒ?ÜR¼A…Ô@£©cØ¥*®ï ÑÔ1š:p§€M£©wê ÑÔ1š:p§€M£©wê ú§W«ˆˆíÛ.†1¬Èr)#:à·9æøå±ihê˜ÉÐ;[,qÎܹsMç@— ³@á<¯}]¨+²‚Ä᤮®ÈS»X®¤'x)æ•ØADß>Í™'$ÀíFC=P»£Ôý7d†Ö|'ê%ð¸=_7èŠ>‹¾²—æææ¸É`­Ìá, ÁØ™¨ÆÀ™ûö÷’¨>fj:Ût6˜ššBi0 ¦¡B®³ÂºŒ!TÂ!§à¢pŒÀù„ïDÊÔuŸX F /ÐĹÓÕÛ™—Èk$0ŒA[¦ Ä'"S‡Ô;kV/ƒ@/ƒE¡R`Y×YàŠ \áX‰ gºÂD¡à³gêˆÀ³–×ÃØõ8Žm kDÖOQ§é ©#’: }XÍbAp…4æšY¤Í˺Xäš=²ÍINh¢`jþ>óýñ½ @&P©^ à ® àŠ €ì~$ „ŒBÓNàÜ0€Ây"%–›èa §Ô…œø#Åqº+VÖ,Ð-h§$zꨌÀ8£ßóŬ+\‘Óé©# q2±§Žˆùæû4Íg˜@¥Ì!4 Ït‰®pÚUÆJ¸¢¨Q•HÚ œ9@øÎ+%;uà\§‰5¿R–:À+±¤¤k¾#"Я“ÀrW9ÊmäØîˆX ÁKL(Ì…@œL c`ÔüùKg˜@¥–BhžQ9*át%ªL%”¨DQ‡¦hóJïy¥ØŽuEO®®ØR‡«+®Õ˜èÇ‘b¿ëÛ>WôÔ!mw@RÇoŒÔ½@ÆB¹NõVùÊ,©§²‘ÀPS.ÅH1|Ll©céÒ¥pÞRTÑãÒÔ4Œ”z+#"ÐS%†wѲ!@¸Î+E[Œ‰¾b<¹Ÿ}{œ+öÕ˜˜Ç‘bôYP5a.Mx ž-6'¶?Â’8øø ×Wb/ À ¥ ðôªD ì%K–@qƒI0 &#" æ¸1P6 b.” U1;*¾Ž‘‹´ÊÊJd"»ÎDõ'$tˆOdmâÈ3¼‰Ô»[›I94+cK7›ˆÔÔA¿ÄAè oúãÈLDZê¡câ t†7A@Õ‹åA×Ô;v ½@‘\³ š3¼Gí@ÁRÇüÁ—:ŒãڀĩƒÀÀ( = Aœ:̎ڀĩƒÀÚƒQ@{@°Ô1cð¥ë–Fí@a¤‚ƒ28¶_QePD†˜±3öAèj%¨@ª|iiiú¦ 1 ,ê R„‚­¯”H-DR¬:éx4+@¡§2F9ÐOȤhTD†pꘙ˜ži‰ˆ¨ÏÓ"@&gF`Š¡„U‹f *'Z1:É7ˆt@h©C†¸R'dRTŒÈµšþ@x.â6˜Çˆ,e…D¢ F` â”À ¬HSަˆ„%ôV˜:éxt/@Qž:°œIŸÔÁ¢Å0SÖÓKq ¯·¢ÎKe&Q=V'2GPítVb@V® `†}DØy/JÞµ©MÓî°Ë%4•¶ÐSª:FwŸIóK¼†qÝ!s %¬‰Ò}Æ=6Û#Œ{Ü|¨ãÜêX?£pÀ œ¡0‚£Ñô”êƒÈ@á¬>¡†ÔÌŒ.L¯¨MËѵv´Cÿ¸n„™:°œZ…r<¦ Þ3'¡Y…„ÑÔD:òLåt,’RÇl0MVr–˜âP1=8ÖÓÓ‹@DÈé!‰è!ë@Öˆª.“ÓCbF Ø®‡f ª™z®KBYz¨’hv£[FE@R‡ŒŒ Æáwˆctepœ‰F£%5´HÐÎ<#2uìƒ,ñˆ¨ó¦aÈBq„!‚¢ áLT98 I „`.-†H:rh–£*BS…i4ªaØ$ŽBq;5@aI“d #1J…I'dÒ1uìÑ`Þ!­Ï‚ÔAê!—ƒdÐZ§xRtòeÍ3 ôÌÁQ@1 ¤³ŽAçƒÎD€òóJG… €F@¦ŽQ€Ðhê¸@¦ŽQ€Ðhê¸@¦ŽQ€Ðhê¸@¡ßG Äh%VÝ(² €0î…C¾‹‹pò Àa kê 2ÞGSÇp„;u \öùŽ?¸b˜¢Ñ3¼@á©Y Ñtñ#êm®ˆ{!G“Çð„™:à­RØ=öh—AŒ‚aÙ”JFSÇÈ„§UŠш†ÇhêI €ˆI®¤V/£`˜€""uŒÖ,#‘íôš%~Ó=JŸe4u /@¸GÒ#ê°äáêêŠÒ‘EH#Ô¯'@£³p£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔAo0it·ÐhêM€~Ì#@¦ŽÑÔèGÄÐhêM€~¼4@¦:ƒùƒ9u M@£©c4u úµ4š:FS _‰@£©c4u úuZ4š:è f æÔ~@¦ŽÑÔû’W€M£©wê Ì]Ö02I “X€¬ˆ³PqË"l7`À•he®¸ôº’o2¸d@€xmxD±¤€B?¡k Žy¡Fðâ3¯ ®$DМþpu¥N.‡¦…_Q¢ØR@ @êˆp%3wºR/q¸’[,PTʸ’_v`Ïÿ2„J Ë€".uÀbu`Sö{§hI ƒ3Â)L踂B¶ëtöŸÄO(ôx‰’úêŠ,èhжÎÒÈ( "(Л“3(?ºpv©ÃSlˆÆ´”ΕÐÿ…È`qO£‹×4þh˜F$Š3.b/Ÿ«ÁnaŽQcÿ3ïaìnV訫T‰›ž'^—å2Ñq ã ŽAÐ"®ãî?I×Ud¯:­DûÙÏ+µO$OZS¨³ ¡Ã˜(µ‘’§ÁB¥Àæ>.ÄMERˆÚ™Ç»ô#ó–xðÞ¢ˆ¯Ðmt`Qèa‰î&) ΀«G'YÞ¶)òk6ÎŽ!£epÂÀEX§;°ÿ$~L ¥^>„&¦Ge™‰%A™\cGRPyˆ?rz:LhIšÒ®eðü+z"êÈ÷8›÷gaÿÉNÿ K‡•Š\D_WbAÇ@¤§äò^s`É(5 †ùÈU 5SªSð§„Z©£RsEªþ°¥„‘®Hú\QŠ)RS¼]-uÀJ"RRû„èÔ@Ħx™%u¸FDàO¨a’¨œ:\ñIàu+±©§¨¦S-u`˜©Q2¸JâR@:Ð O´¸pÅZ—G` ,Ô¦)–* [†»ÝhLbs Ö¸ƒ0]ÑÔº¢ù-yº¢ÙÃX̆¢= ±kêÀÛîÀlp —'ð–-¶QˆjŠ-øS@ÂÎÝ †‹°Žw`ÿI^Á'gzE„BQ _Šðê•Ê'Njê/¹f »ËœdÓ¼˜ˆªø¸DRœà’¶ TêÎ,1™¥.ÙmEÄÛ+À^HL9™8)mXÑ#Ë‚YÃc´D—m»@p>CÁ±Œüò_ŸÂ;ÏâJÑxò( õ<‹ Cͳ¾Ô1š8û,œ uFê ’çhG2Ls´2TM© €Fgð‡ö ¾ þ9Z S@¦ŽÑõ¸S@¦ŽÑÔ;uÐhêM¸S@¦ŽÑÔ;uÐhêM¸S@a¤\K|ˆºÜ›ZÊW‚b56•‚ñWÒ¼ö9æèò8U›?y‚³÷ÚÁÞO%®"Cœš>© €ÐS‡+Ž bbØ[„Q¾”zëɳ)7')uàTm,;ž¥¸¦Bˆë½ÊÈ—‚ÐS@a™…£¼ìÀÌØ®Ô/;(¾u%΋ÍqXÅp§Ž™ ³f‹%Ι‹ LÁ¤+’ˆ+E‚0p%B¦ÄôÔ@4N”ÿÃ6uœ8&vûÞd` &]‘D\Ñø(„+0%î¡ï… ÔÔºžÓ}­$Úl$ê"NÔe—®˜©y*Ò¼(¶Õ¡¨2HKu"°¬ñtŶ(iš·“Ñ @_1ꊼ<ß ê  \DÊ0GRW\É@„€áPµ’˜i¢©i"˜‚(S0™èšˆ6Ð` ! ®98…%B¥ òý`Q;¦º21‘/‘Ä,Í´²AßG €n+¸a„•ònž§®Ð!ò´º‚™ã¦©x0Eÿ«Èh‚€ãìÃ_nISrF›x,ê êI†lqN²€NwVbÿgåCä‡5»æ|tqY•ý½xé£7¬9—aÝ RÕ1¤¦'Ìïçþy|ËsŽÞD“q°HG})-Z÷È´oTy5nØÖ¸¯BÌððqî6Â0E¢†šE(©Y!«œå 6‰‚¹0Á>‘¬³GIì§”y£CÛj+_B®Ž@Xä êèp¾¥ô0óBœ‰Æ]‘þè€xÚ’ Ø]ý¢#Y:î–§Jßdd—µÚº©')v¾}öd€: "–f&4TÄ/!¼Â¹š<­HCŽ"õÿï8¾ÔQY–/aɤ^ÊTbÑD(u@µ“›:´WVâLðäŒâd4 P ¨Dj xB/à%&”@ŠX²¦ +=Æx†Ý‡¦Ïš5k:Íš£*g!@%œ®D•©„•(ê*Q™p•©Jt lgÍâR¿gÍ*R"'ÐÏþ@Æä°%Þ}Iÿáij ÿñèOÔy®Û€¬-P(|IkJ:‚¬BïÞ@°ÒîÖ©Õl79Áío΄ ƒOcÁæaȉð~áés«LÙaœÊÔ#Ÿ×sorˆÔª$?AØ  ¿‚p>x©e€.š Î…ÞRû2 ÿ†}Ðqm7‚0pÝÃ!n ò¾Üĸ—?"PúŠÈÝ(C‰@-ɱ;–M#cJ×är—‹Šþ99†ý÷½0CIƒ ìuÈ/ùbÇi5Dì½9 .Ñ+#sí˜+ #R ^{S„À¨Fl":§â£Ï(¶Öˆçh†¯+˜)ìÍ'ÇÄÞÕÑ;eÊ¿ô¿º`†ŒnAzc2Ý‚ Ï3Q âÿb!4Ðú¸¹G ß3smX51ü]![ŒÑæˆf®OBÈgʉNËaˆdF SŒUE uP$ˆ ¸üÀÿâ€Z2:(„aà3ûÝ]Oáam«â· DôLð3™ÅÆ"߃q,°(½C#g@:ûñi\lÒˆ]–¥KÙ^ íÿJÉÓP/.5xâw4˜!bþ˜Žw£8ZéCߤ:À—B1sõÉÈü*äöç´”°=\“Þ[6›b@EÍÑñ!ÐÌÝ Æ_ê"ÐUн ‡ŸâÇs²}¥ÿ=Kf©í€„Ý]ºÿ$æP%àB-´?£Yfüøïˆ?Ã,Ϊ8ÙhOQÞq„jï_NF{JH±Å®yó¢y¶µ€›’AwL¸á©2v0´u¥xûw,İ:bõê‘8…p»À üêOŒ¬@ †Ã‡ÄÔ!€]@¿z‘HÄ0#bÆŒ˜8âãã±a -=,@1Ì@ÝÂ0 FÐhê¸@¦ŽQ€™ß¶jëÛIEND®B`‚PKH=27 content.xmlí}Û’ÛF²àû~EEï„d‹hTá®I#µ¤±ÏJc…$ïÌîÆÆš»a‘ªÕ~Øðoœ‡yÙOó—lf q%$AvY3ÝluËÊÊÊ{þåÅ·ùŒ|uüÀõÏ.¨$_g1ö&îâæÙÅ/ŸßŽÌ‹ÏÿË_¼éÔ;O'Þx5wáhì-BøM õ"x=}v±òO=;pƒ§ {îOÃñSoé,’VOÓo?åcEßáý¬qsþrºuè| ›6Æw3míëæ#ó—Ó­'¾}×´1¾ @M7ŸzM f£©PŸ/íÐÍÍâÛÌ]|yvq†Ë§——wwwÒ"yþÍ%µ,ë’?]Ox¼~o¹ògü­ÉøÒ™98XpI%z™¼;wB»éüðÝô”«ùµã7Ú…]]úN¯Àr1›u”n“Á¯¯7±ëëM˜Ç·¶ßÏøËYTQ&ÍQE™¤ÛÎíð¶bÍË÷ðÿxÿnƒWþ¼éXønTcß]6^fôvº½çyë©bƒè°óé2YV/£¿Soßm}ýÎwCÇO½>ÞúúØž×÷æe@ƒ÷è%¼1r¾"ʯ"¨hÀ.£Çë—ƒIe×ÿ|ÿîÓøÖ™Û›—Ýú—Gî"íÅ2ÁÜ5Þx·ií…ÛðÝÔщÉtænxž\ÑÆ—ë/ìUèaëñˆŸäàù_¢Í’è3þìb²¤ñSf~_E´q´´oœ‹¤eúËÑÒ‡ û¡ë$sȯíñ—ß[-&£¯nàrbú+cÕkÞõ¯Î8 ¶¾>qƒå̾’ë…Hƶ¼Âg—»©= ª^"çŒBwžŒ »Lh¼XðJfsëØ“š• bñ7~Yn|{yëŽ×ëŽÿN/9z_„°ÕÏ.÷·VCà ™tlûÈñ?FQ#<¼ÛŸl›nŒç{_ ÁÂ[°øWSw6ãcL\è6õ%œé™ý·1ü7¦Ÿ$oÇÃÿ-þóÿ0ùÿñ{ÈêÀDíѭ绿¿fÏFö̽£üë*Ýé}þů8Ññæµ¹;™Ì’Yâ‡a½;À÷æ6\oøÔ€La…ÞòÙ…,Qe<Ï|í…!Rã’G3gâ¦åøÑ ©'wÒ‘·Œü#žYpkOð‰OtæÛ§À Gß°'Yá]•<¾¯xœlÀ5ÃmpHM§ãqC2ëq7îÌè¦ë,Ê1À”ñ_ P€;¸½H5Âož]¼†Ÿ¸HɾÞ$ÏîÜ 2’€éLG¤%Ë”ùÙ.A€p~õ\¾ŸœKa\SýŒÇ–Õ%¼&-¼ÑÞI)Éln)é 45Ñ€7s'û¦½ÝQT~—Ô¹œöXiƒ4UÝ9Sþ_?HqʇÇhîMÒÐŽÍVswjà¿®__„¾„©¯nìù܉_^ã;“ôsßq©¿¯g«¸G˜îxæ4|¼Éã9Iýÿqüº;G¹Ñ[Úc7¼O†‰aîú>n&ßãˆhž yŒ©¡â2íD¶¬³Ç–¦ü÷^ý¢ rGã”3ã6&Uj2Oêl9¶E =uNdn8×]=ŠZXL{˜F”®ÈD¡ nŒ‹×ùR˜Cè‹éQÆ•¢HS*#v¶~g­VÕ&,äÜö¿8þÈYœ/<ݽYLPÑ ol:gt­—L=ÃzRÞ]YTqåõ…ŠƒRý>þô {UjóÛ#³³kþG[óQB·Õa«¡­Óm©WAÛ^5ü¢AǶ€›·^5Jƒ»&5vŽñ.¿…¸a¯äJÜB5Ì¡í!‚‘у|+KÄßÙÆE/”±E‚íz%ò±Ø®}³C(|ÏÉ<ð°éÀ!É;bKJ‘×ÍáÁéS#ø°‰Ë!t½§Â' >fôë:ê:ÑS«=­Ü„BƒQ‡FÇVˆW^ƒJÑåì“äL9 Ÿçƒ[N„©ðàל2¸¬­Â¨)}¨­g48¶â¼+ç­ ÎûlHÒR„è{ò¿Ù~s ÿ›óÀàÁå&i—B‚õƒ'v£KD8¶ ¿+¡Ó;:AΆBÎNÝD`lÃEÁž.ÛDpˆ”&)áÛ_‚>éK™Q¶íR.yÜùŽ!¥+!4!<B¨Öbq¼ÔwBn9ºÜ¢´Q§¼1*PÖ4»‘OkùÔUA>Oˆ|Âîq,<¥ÅW¢ž*¢Â2s4DÝŽ*õ¤uf›½!êV/S¨'…¨‡°Îœ ÷@ÅãⱭ<û×fN§º¾îèa æ=ãÊ©[a¨ðŽ?Âu3L³gî Q…3Ùù ê’9YÇŠ¨ËøO\¾Ý‹MÂÚr´ä¡{k’;¨ÚúŸ>²ÂúßïV;™PgÎd«è/8“SâL´c‡\Ä€¯ÀÍ øŠ rÝñêØIì!÷°p¥ÖÙãþpÚihÒEJ¢P¥ó×tÇÕЮtÆ•ckºÈ©¯ºãÕ”Ö¼râîW¸Ë„Ò¨* +;Ð)&´ÿròÇvªï\Þa_a—BAtp‘~ì,A‘qkÜ¥@Æ“BÆ£«Î»"ãÖØ7Œ'…ŒÇVwFÆ­‘DO ­olk´@Æ“BÆckä;#c÷u‡‚Œ‡Ðù·ð¬•szÚÚ¥_M—¾À^Ú8þ–í}íLíÕ,…n°;ñÊk‘*,÷0&V›íŸ»‹u &YT7 ¿O([nwÏŠ,ý‚èØY‚ÕõiàK½Þ´ ²¨’.[Y ¢]KdYx¡ÔbJé…Ÿƒ?¥’Šk1ù‚( ÈbL—%Ãzh˜þ¡x…ھͷ|ëoÒ(€0²ýS¼¸pÑ—ÉÂð[ÜÁ§Î¾FD[ͯ–žÞ|aä.`Qq“æÓ/õfÓÝùnˆÛ0÷&ÐÙÌ…×-Æ.ÒˆÞA·ù6Á:YË~¿Æº}CºHTö±Z>Áø€GÕ~WUT›¯ªlª[Ñ*zÈ›e{šzHˆÝßàe¦.ÃÓ/ˆ6{Ù_7÷Oò¼Ï=)øÝì¸(*1£/ª4Š;k¾Š‚—ÇÁëÚ6¾û|.\ Ø×ÅÎ+XJК£’½¸YÙ7ðÕÔ½ˆÚ­¡¼ýi=dÒnd®½HZç޽ùræ|k{f>®Œº¥¥ÖAYax§×ñ·W•ëˆZW®ƒ?n¾ŽÂõS·Ž­°o>ná"h?¥¿x l‡ŸÒ~Òß:á3ÝŽÏ´>G5qýÛiiI£»øZ¸öf“æ ŽZ%ËÛfáQÒzýoß`…ûå ã£<»pAàÙ¨  —Óâ§U«A5_?;h³ÂmÖæ°è‹¾ý°è­KÁa®ño³Ž^‰?-¸ˆõO½NcéÎ,LÅ1o†Åíèb·ÛÑÅŠÖ»ÒEÚ‰3:ð´f¸rJ™^Oa·û·îlv»ŸËnŸ[Ñ…m‰© ©_á–jGýÊ›w ~­¹Ûd}@뛕~@ë›nÆeµZùj´òæ€ÖšŸÞX‰²ú•¤ýŸì¥üùÊ›»còÉ^äý§è«Ì¼£·G7ÎÂñÝñ³‹`컹¥-Ýp|ûìâ«í»6ñÍmÙ‰ 6·3Áf;&¸57ßËym|0»*¬5ƒß˱j|~º/lgÖ¼Óåt˜}kÍD׬­Ùyë…K,Î^¹ÄòÞ÷È%²ö}(z4ÃÎZ3ìûdG» ¡ýnE3v¬Ï­ØY2Ðõñ8vP§¢—­h-o ”c­e€RÞu廎OþîÜ5à\Ѷî/2¯ÄœëÔýæLÍþìÌüçï¥á°Ýy΃µÝy­h½óiÜYšÈßQÃÛ–ƒàµr@›Ä š•ÖRO™^‚<>Û.Ìß¹AÐJ–ܤìf|Ø't†t´veÆã˜¶ST(ª½AQ‘LúP¡¨õEM’͇ E]@±(Š=@ÑP슖€bPÄ ÆžÄå Å– g!¶ ð0 ±Eˆ-C¢[„Ø2( ±Eˆ-C¢[„Ø20±E=‚ز'ƒqUHZ†{–…Ô"¤–¡@QH-Bj …Ô"¤–¡@QH-Bj˜Ô¢õ*µl<æ ŸÙ×ð$Îþ™u!ò‘g(P"y†E!ò‘g(P"y†E!òô(òègè_Vš-Ä–f!¶±e(Pb‹[†E!¶±e(Pb‹[&¶Gñ/ë;Ý„°³ ÿ„À"–“ƒ¢X„À2( E,C¢X„À20Å<+E$;:þ E,'E!°e(P‹X†E!°e`‹uP¥¯„øÂ¢2|ŠPNŠB@ÊP (!  ŠB@ÊÀfW e4°À!µœ…Ô"¤–¡@QH-Bj …Ô"¤–¡@QH-BjšÔrŒ:ž{ÎŒ,Ä–£c¡[„ØrrPb‹[†E!¶±e(Pb‹[/¶\zÓ©;vžÚ«¦ºãèAðü/ñƒkor¿þcé;³á=oñü/ß¾{º´oÂ?E²Î'oå²tÇáÊçPòÉįæÐŽüñû¿>ßz«›Û0 öµ· ‰»ûޏ‹П{±ðîíÅØWÉõ=ùÓ,üó¯ɶg¡÷×±½ÑÂ1…-/y²¤ñ·s;„S‹Ÿ½v¦öj­Ò+È,'z{fßìâF/ßÑÏhnŠ+™óõÌSКÂÒ‚gS{ð}‡Ë%lïÄ Ü›Åãk’Ç—1Ȧ>tŸIzK?YǸô£,~ót¢éî|½yç”fTÒ,@[þݭ㬑ߤ†ž|ù e!KÖ’¿uuIQy£Ì¤Æ3;€µ…nˆ8˜y´ ¾¡²%.Ù™À[þʹˆÈç}í}‹Ïí2>]é…¬bØõEñùgx~ LŠÎ#9 Kø[Èåfçšî"ë°‹Ô 3¿‹ªdêVjc)"ÙD*K†¥Uíb°ºÞËF*5ÉÖÏ×ä)uM£wpäó”|¾u‡ÍAgQøpO®à óÝëUèLˆ·˜ÝXÞ¯Îî¯|?{˜ôpŒüN»¥„·<@âa/&dì-&.Â> \^öð—üíï¿¿á«ü°ºž¹ãá­$Þò•8Œ3Ü”?ç'Ä à°O¼%®ìIfV‹‰ãÂðÖíŠ7åÀë;y~:Èz½ŽàßTÚ,|x«yÄWñúÝc©÷¹]6%â²ðB Û%5»Hq£ðv5¿^Øî¬øêÍú.¬¦•†DU–§•–¤15E+5ÉÒ”4±”,þçf ˜Ž@Ëé'¾ÓüWê)¼&1¥pQS*©Ê–‹š2IÖ+i<‡wžÇ™O{ëÍ&82Ú~™ÛÁËâ&o *ؾ½;bO&Ð4 Àru‚oâ;Ïÿ†WcÈ3ôΫA h> ní¥S†ž].yິ<0‰R#ƒ·šœÁ[]br[޳Zsœ•"©Qò¤f}ÚùœÅ-rRZ¼¹ú÷|:_]çî•“”‰LÕåøg¼ð›ÙÊ-=wÈœ˜2¾¦À Ñ™Dßñ?¨©ªÉQOñ7ügü }ƒÒ·‘õƒe0ìE¯%?“÷î—°xg6s—Ñþ^6¸ééV»ñçT7 ç^Ò©–Úv&iâÛ.Kš>,lۙߕ«®;oJÐÇ}ާVÕ4à©%™–‘‚¼)©|»P]v9úÀ¨Ú‹ܳlWK§ùž`ãwqóL7dó[&ÿ“ü}+ײ ’Z„elZƒ2}—Ew—EY7Ò¥]< ˆîÝÊ'=›(çÜÐAzï{s‚ZoÌ5+±b 7ðð=8HΈoÓ³‹5å‹!Ð<òbJUü¡µ¤~s×÷=ôuWc{“ƒ VzÀ¨àÙŒovÔÊ›¸S˜_.« 1™™f9Þþƒä±õÅ”1ü¡àŒMüa^¯—À18Ù‹ÿXE,wЧ˜&“G¶šÙÏ.¾“Ɉƒd}?—¶£…v´Q;–o÷b*“ïñÇövJ±Åv´¦ZlÇÈ/¦JM;-ß.ø?|ôbª’ÇÛêŵF1ò m `ì.ñ Âçñ壥{ §¤ffqN`{+«¬Õu­h}øB¿{Á#ìàûdÊ5s¦tŠú ÜE»~JЋʸŽz„.Ã0Ú¬iÉÜ)L['Oà0ÁÞQV‡4´€nëøîS¥¶‡Þ¥wÂlÁ¦w¢E?%hHõfà,ÁEj4jʶâ£Õxöl+>¶è§Y3|d%øÈ ø·Ãd³Ñg¸®ûâ¤ü;ºá_ wqÆFëÀØ Þ  ”¡ú<Ã$JªÉ²œ 3ŒíœM? œÍ{TÄ µ¸ÕÇ™ ê°¥V§Áˆ\‘E@V€þa@Âe_òéý礱âI‡‰¿üéyûñç÷OûŸ¢;™˜q„…k]rèv&ä—EàÍܱ‹0zµš}!oæÆžça\<¨~ƒpZï» 8™ÃŸö<î[€”´ w8T ´(-0ÃZ«àÖ¢*2¢Èz“G#&)ŠNp´ŠaiTLø[3þåhlOP¬À#û¸'-ÍP+†F½A6éÅš=ŒöÜKèÜÇå@ ß»+rÍ”*šLTº¾6 »·ƒ3Æñh”dü&a©ñ–4c¸¯q êB;Óã§rê>•è5fÈÑÇøK²xò:.·È×ñÓ…‹‰¯}T;RáVŠÚíĈ+ãÙà6,ðG8àÈŽ·¹ 3ÏoœÑ·ÑÜ]¸óÕ«ƒv¦bÕTèpš0UÃQࢂéXpÍȆɯf’Üë¿Åùó!Ò á#ã‹›eà‹ñ¹~+5õn|ˆÕß¡`%Zˬť ¶¤£foà ~Us}óÀËÊZ SÙRcÊU(— ѱ!9;@£_¨‰ãRxœÒ+®9 üýŽʪôŒø©œ¼¥Cë&~mæ~%MµõŒvÑüµ×ùµä2¾c»ñµ#Ø ÔGÖ®¨„­Pɨ^;Xªä»d-|8ETò´ÔçA³º¡J4(f“±Šú<®í x=_2ô¶zÔá÷I.zÏ”ì“E3,YÒÌŽ¤÷éÿøÁãtwèôŒ™p2ÞÁÉøêÖžÍTYt‚¥‡žù×67^®Â[4FFÂSö7.ðw_œûRžŽV{BÖ3u@kÔ‚*|™fé2–ðX\RÛ³t²rÿ~ùúíkÃ2@;$K'œy›9ó6<[ûòë¥]¶Mûrá>•%Å`ãVòÿ„Oè„0N€w²Wj³MêâYcH¦R¸Ae¸!ÓòOÞj<Þ•å^Ù~càìžs×’€`äáÔõƒ0rô½æ^18ê[¯"ñTðHo9T;ƒl¹{¾Ñ”8m0ÅkÆHaËß;lóFæãô6€ŠÄ©JWÒ4>ƒÝÜHjPí,Ãhµ6©‘'U/ù`i%HÒª P.žcøÔóþz¨ùÓMøçÓ>žµ;ÕÅ7˜ZPûmBÌ×ôšii&1Ñq ´oBB²hŸq¼èë¯mÿ¯#ð~g¼O'^ÈdgàXod¸”3Âú.î¥Abˆõi ’3“€¼`I5UG·ˆ (¾ûîÜ Ý¯[€ ÍZ„˜…ö¢Q˜Ä0}-+hô¡Š©Á#É`ä˜ZDU²ä‚n'ÏP’®dØ’(œ¸ MañådÒ‚)išc…ëÈçñ¨ë¿Ålô‹çw·nè çÙiÓÁþÙóìa¤\¨šfš=Ïqð,õN½“ü¯IÌ*-Kì5'•tµ&µ R—LP:| j€Þ…)Œ§¡ÙûUÑ2VPØL]?϶ã`ÕJšºž…fÄÅw½ÆcgÖaýa/šë6šqÑt»hXµÓVë‹h¸ZsÏįt¹fXŽR~6ãùRÂÏR ~ª±®7ÈzðÊöyö°·žGœopä༭#Ïzv>£îöÁ‚;ÏŸ—Wv8¾]ÚYxdæÁ¸>Y8ÎÄ™œwÀ[' lx™¯Ìr kX¡×íœ $ó´iÍž]°t­(Üç\° Ìð·Zw¬´F¸_ Õýª v¥óqV WÞL§ë¶÷¶À«¡âUí1\&´DfÊ^& Ä[š‹[’ë’4¹O®Îü>éxÍËjí5 –v¸LŒ&7æÕyoL…ÈfIŒ’!ãÕн²AØÆç[ÇwxîŽÀ‰‘-}ïz†éÉÜfÁ%W£$¸BgŽis£8Œb%å—OÈ«Æ `N\rh5B»C¿Ù'‘6·ÚÄj2EÓ2Rõuø¾Èš·YÓDÖ4‘5mK"kšÈšÖ_Ö´ägIÛýóÞ.Ï!Þû©¤gT3AΦd*Y×]3N ¬§Ü£ˆàž+|uýU¸È øB­fí±âKÌzˆ¨U‚ 'Û#BQšä•¯Ç„½E¢ôä7È[’’ÑÔÅŠ‰@ŸG(à>%j|„¥mZÉýhfl^rF¾xþ¨ñÛ\QN¡ù¸• £Uð…%‚/ʃ/ŒMœT¹{âæ†-ëÍ»ë1Jç v3 b†3@såJ,‰ÊÙ°#‹õ€õ›„ÎD„ˆð£xŠ‚PføÙDœM’ªñ&ïÛx>Àìd©ÔA ,0¦*\ö9h¦L—± ¹.ûÑÀ“>&ï#_5âÄw~Ý5§}“Ájk›Õuà;áÊ_Àü€“ž®fm“É7™#{L~öQ Ùd¶wξ?m›JnWüñû¿ZAå`}ÏØã‹˜†¶‹0:ÀlÕ¶È…G,ÔD…€a'Crg‡m«É¢T;qfîWÇw&ùM9»Ëµ[ѱáº`ÕW3,‘µ;zß®B©á„.?€³ºp`·"i;¼µÃäXHäG·…)_¤ökïþkóaOÝÙ,ªj&w熷qåŽ4A•Ïz3á3Ã$ª¬UäY|aÁü-ý ¾°àWBAXð;YðÑ¿¬[3+‹+Ì'ÔΔνß(¬ššA°„ªi½} ¿uC»’ß¾–_ªWÆ›£[ðÕ þI‚µ6¯‹6#›Ëmã ‘*ïQšÁ0[ÊyYÀºxþil/ÀýO‘kŒØÿÅØ›#ó>ßè8¸ä èØöý{|fc]ìy…ÚAºKsÁ˜^\6˜PƒòÄæ€ Nw î6NW¶ Ø•ZÞªï µ™È_ªaì†jÁ¨œë¶ ™hÌH>™Èê[šLtþd ¦¤ã†‹00±:U ­ ‰YÉL ©Â»øÉÀ…Èø%e|M8Õ §p6¸p¡P-ú œ?á©Ôá ' š8!.vh Ÿ/¦d—M7¢× ‹—E¡¦Å»Çž-!ÃáAhæBÏ/CGªf&uÆÖè#.EÌ%u¿U SÕ“-´¢´ò‘ ³ùš2¿—ñmªê&O!¯ñLøtý™w{kðùânkFê3N(þ¬r`™„*ãïY1Y²*ÊÔM¢>÷x‚›üÿ&‚”ÉnßK£¸.Þ_-¢tg!8Ôä£jjÉGEã8ÁjÀ†ŽC+ÑGŒ°Á•êJòIE˜ñO ¾ÎAáCËØÃÖ >f±hÉQS¾­¦†s…—ð¤06NןÆ`DOC囌ïãPp pM ³ôãûœ½Š7AaàüDLC7ðØÑäý¢b‰™8xͦøA†‡&n³ÁÒ+Ü7¾{2…m9|Ô8l7ãl0‚ã0Ü5´‚Ò0ÿHü«¨M '¯àümRƒ¯¾7£=ÅnMËZcêz‚‚WˆN*G'ŽZŒïB„¼¸EÄNÖ´A9\TD˜,¾Á Gd=úlptÖ“v&Ç`ŽdWÄ”9ag‹«øŽqÒb"lâumÐê vÅJKá4r §Fj~dºŠ¡wÃ1Óã"ÇãüB8ÓË…z©'"õ˜¢YÌŠì—HÞç<%åa/)‘JÅ(¼2lÁŽbp}NK¬1_íÒ‚@ónJ ,)Ä€u‚Ú¨a±Ê’Œ…„ê •UYjP0©T}p©´¯²dÖ·*©­dïYm»YÌlÒ®€IõÂʪpµÕ †\ÒšWE±ñ£¾Y;Öõ©F\m¸ƒpÏk6é¼}my­2 Ÿ6©Uð¹zå‡ †«8ëbƒ.‹èf’¡¥-÷¤û¸nCMZ©&‡´ÏÅ¿ÿgß9>´µí¡›DbšÕVÕÝ:0Üd£ÿ‡?®rKa)lf¢â\ÉŠ/ö¢(´h[ ò¡‘Ñá3H "ËqéC%®|¨–ðºëééæfžøF4hÈ?pÎÄä‹r4NS^1d\ÿPN@‚¿ts³R-鹬ßÖÌPPµ%+Àuþú%¥;Ø ”X®¬Í\G·Kk3ÿP?` í–›´++|àl[?QU›‘>¼'¿;bÙæÊÜNÕ–ÚÖn¦‰WZµ—iÞo-çdzú1!ªˆ é§àK9?¶WªÕþÝsFÿî]Ÿ~XHjÕ{)ù’Ùó;©©fñ9•H3“‚š÷~*5_jyÂNŽtJI^¶„t’ew}¾t€kÇR£JW£}ÕíÑ£¥óF„*Îlæ.£³»Ð%¬'cIØXnLÝÊf:Ë Ü‚Fo^½ç»-ÕÑ, Ì@Èi.éL „hfS¢Ä0{SD âÎ5±ÊÙAVÅJJÐäöé}ÈÇ"«hvMv|øm.Ÿ^^Ž}é~)…Þe0——¨pnÃy[‡êiê>9¦Ê#ß‚ìm2zÞ^´bT“‹ikŒjž¬ÏMZWhñr“,:ñw'¡×Úå½i}RD h‰´˜Ë_—¯É¶v¾è²C€ ŸÞþ@ÊxÚ±·X8ãêjƒ§²u•ª•œˆ¸j%ÉQ·‰à‚N³øM$,×¶Xj]ï¼ 2 šŽïÍÔS«“Då50°bº˜Ój幪ܬ9WHô±2$*gNŠô¥!)¬æLíÕ.S7±Ê6•£Ñ mSLiWOS»xŽö«tÚK®ÿšÝcÙx¶š8Ar \>Gº6)%6-›])•ÜAÍ:gÁÔXÔñíʧ2K#L·táÈ'ù„#ŸpäŽ|‘O8ò G>áÈ'ù*©Ã1ù&*ë’¦§ ©:^'%, ¬™jX-Õ®Aƒù²BT•ë ƒ»‹3 §óÙC¢^k"¦„À$ä“(HM:H¶–lhÌ|LøK3þP“tZ–SIb<ÜSÒ©´@14îŠÄûÅš}‹7"ôÝ%tîãZ …ïÝTG®u›“ìz ž¢"’X‹¼1~“$· ÜA5nÆba,q¬ÕãÎôø©œz‡¢´½Æ 9ú`ÉC¶Ï\{ý·æ1 ÜLä­Z;R¥—ë)1”(Çev´„½á¾ÚêÚÎ<Œ|L¿m|Pq¿+^IÜPÓX|WÖ}f£Cýo¡ÒS¢MÝøUÊÚVcºHF—x&è%À¤Œf©§k'Õ.fGu'Õ/ˆR)Eó¿ÿ+vû€O}›®q¨÷«Y膫 Oß¼6˜·Î^Öd¨Øß"ç³rñüÎ÷0 =Êâ|Ú&Ú$.6$ËÊ–„¤JGW ¦=¼ÄÅÝË©r‰D¶°sÁ–F5É4ºç–{ïùAo¶€ø«Å½ÊúõÚßDZ¸˜Eîšn¤€ÀDFÔÒ­rÌyáD^8‘nK?"/œÈ W ‘®¿x«oTZv,#è–dÝMô‘]ÜŒô‹çŸ–®~~¿¾u rtǽ)+8ŸÝS2­þwkCœýÞt+U"Räã žÕqœn· ÔŸ–ö|îøÜé.ÎH»[w|Û³\רsàŽQx!ÙÒNΞÔA Eî€é™ F"ó¯eMMb厺•›UW1žÏуp@عGJÒ‹7èŠß9jÇ3Óedšë— Tµµqå¬QtlÌÊÖúΚL¼/{èÇ«ŸÉçŸ[‚³y Ÿa®úõËÏ/÷0_ES÷0_c”ÝU9ûjuO°èÆÒ÷&«qø„W²Øƒø« L(ùåã»æ(às‰À¿ƒÄŸ¯Õ>)ÕPJT¢ùÙtþb#¯FwȈº_b'Eá6×Jd'Í_/‘¡sóý;ž6(Ê„" $\Ìå릧]T?-•>Måä{¬ ÜÄYieí•?”Ô¥Ý)5|Ö¥>*Ñú@#£¥Æ‡7¨­~Giâ‰U"UË9?¬†:žüj]ËÒ„P? B§±{í…À7ÕØ‘ÓGv»!y/Âp§|’© :À³›l›ɈIŠ¢S¦0Y1,ê'Ê$Û£ µÔ¡z‘pï •Ò ]·ð"^$Ä‹¤“çE²¢IØR²éƒŒœ6M­ ¾¯cKà±Çû‘ʇbÞÿÎPY2å–åÅm =ó­Qh—­Y§§Kï%±LšŸl-뎹~ EÇ@5̦…óÝ9»¯[4PT±ÁH$Ya§db|–Ê»‹"Ũiðø(Ö˜bè$Šå£:tQ íÓÏ„¨‰Lˆ;dBüÑ»#Ÿ>¼%·Îl Çôò·¸âÕwq^%ˆ°§ˆÎü>²ì驽SåÒß©.ÉšÞݶñÓ ö”€k—T‘^O¤ k®Lìª?§ûʦtóÈMª2Wå2ËlÒ"vÔ?"¼`Ÿ€µIÆð”´©`Œ Ë¿{múÂM%dâö®sÕ¢¢¿c $¼õ½ÕÍ-×óö?Ì{\Á›oã[”|òèý?ï­Âð@lsòaeJÚ¥<ª–¢ó=æF‹OÁøÖiwÆÞON«ªÃ¯ÿþ‰|þççæV$­QNà êcϯ¨í~*"MU–!e§,ÌßxôTa¿(Qºjd² ©@qÓI†âª9fˆ©»2 “ØÃÍñˆ²!ŸX,âÀªd¸]MÉBU7ÕÓƒêQÊBjê‘ ¯w÷âÿ)ˆ Ä'% ãŠhr' P´¡ÎåÂGÍøÄ^…·žïþæLëÄ Uœy1è,U ¡D±4]©¢å"K•ÈR%²T‰,U"K•,²T‰,U"KU¥³ŠÈR%²T¿Üd×…ÄüùLRiÆê¡HЬžeމ.&SbZ‰ .謪"öÝÚäM‚»¾³0ø£„dæADž;$jzúô‡dÄ!šØÒô½ô}…ö·b+7pqÙ9™râšbñ>ËÑWÄe‹¸l—ÝŽIqÙ".[Äe÷Ì+î?.;Ï,’)S—½ÿ½©ËÎî‘Ù‡ Àͤ ÝlOÊ*Trr,É¢ÆöÝÙ!7ŠYÝOü-Œ&IñyzÕ4¹¢êŠˆÿñ"þ¯FŽñGÿSºh•tIÕ 7»ð¥’qgÇ'I>vÐÏQƃ²Wp£(ÞþÇÃ"»+ö;C£)š¸ð™ Ò5áªc8•;nŽLKBp =ËÒ¦JÖÇûŠÚífVØÁÙÿÖ â«Ìç™NºnŒrîÓÅc•b†ú’Ü¥Y—Õ$L-e4 ¬£Ó÷YŮڷoÄw~É çjâ*åÐ<\ù‹ë’ã“ÉÊ¿úÏ„ºq6çäPîâ٘Ǩ¹C9VŒª´rÔJ{gI{óÆ rïꘒeæpÛ`E5NwÔ§;e¬Šfiý;°–ê¢ÐíRÍÐ KÍ$;S%]nQ}V±P‘¯Þ(ÜŸõ¥ÆLãa*W¦:(V¥ 9×$Õ,Ñê1¶=Ã?&l‚¹ª©J&Å„.1ja† %¬f† Q§Dd˜h cŠ Û)ˆ*i–^¤ÅÍÖ×7µ6ÊœHvaŠROrg/õ*žq #Œ±C²ü&£‹Æƒó¸÷~Ïý+q ’RÞñäxŒÃGãåëg(Ó3ì•«Fì¬Å%mÖjî±·X€€Dè¼÷Ké’«,h­«â]€wT©f1xÓbÙÜX*·˜ËtôæÚ‰qJ´¢Ì„ô>KŸT»ì*3{Š¡.î™"i³°•ÞM’YZLJâÏϽ³š›’^p•-`9ÀR§Xªji”?ÿó3ªŽ¾> –À¾ºKõ©„Šé•uI¾dªÐêl?ºYàP e±`ïd=µw@±Ì­NÖCßá2Ÿº7+?’OÜÅx¶š8¨„Ä õ§'»s§ŸJ©¡vL õþóK2s¾:3òË«7IÎÄî;ÏÿrøÔP•¹vÒ2bNô:y‚Ôvcue|WÕM¤Ïž$êØ–=¡öÆ7»0c™šq›Ð~3sOÅùC6”.Ò¦žßß±n‚ª®|á¸FÔ´Û6:-·­C”MPRõ!o6ªÊÛ×N(Œ8ð*Ýj'Ô•ÑæšEåQ9AxN¶5ªÏɪFÂsò{Nî;Ÿk&B"ÎçZ'ò7ÌçúMâÿD6צB´ÈæºÎæº]´ÞW6×N†³ŒT”²[™ã–¯d’t¯1Tfn¡òÙžÍ #7tæ[`lÖ 6\a.–¤®Õ:á*¯RÙÖ*6$?ãÍ}.·Öø»Ynôt `¿h¹ò±ç£<%@D|ôéÃÛÇìíî ï{Ý#’ldwA®aþ_ö¼è}òAÒíxÉGÓ?~ÿJdðë¸ >šŽ›ìqvˆÍÓ]Ì+’n]õ (Þ·«<«IkTž÷‡8_ì&úUž‰Md£ñL¬‡Ï›ñE’%…eÔŸ‰¡‡÷~*‰MUYÒíô¡zðtKyÝ<µ$– çʇiŸv~ÿn'º”a8I¥]ëZ‰È­>6m›9T?[sö±[ûß H,ëÄ’uá-G oIë34Éb™¼|V¬Ñ{*á-j.†·”8§GoQ¯-=D™dbÑT‚ž(f3ÑÍìwÌ—ÑljÀø"_ø´¥è 2t&­°óªž–‹LIVS·éAôIÚ.ê$­ªBÐдe»®î§i• yôúïŸ^½«àQN|©ÿmáÝ-ȵ=!on»‹*+Âi¯ò£ý›ç³'äÃ=ü~B^_] [ë©uTzBûHÍ‹ªN2öf³(bèìWÍiRß8Ìú\¤¾Õçæ,ôÏÇÄSAàÉ$ÓV$CëZïÁFâ"9(ͤ8Ô$fõ€ò ’ƒL—ÏdÉP•ŒvΤç§ËïD¡2Žª(”&4[úM« zo’éåxŒùü0…¾7KØ×—WïÏ'Wð5¯ÿëÎB÷O›hU9UºËˆjb¦Œ0häTâÅk#§.Ææ ¶yc›³r¢ÕfÍDA±z¢Ù$[]'ºs•ÑlÌIéL1ŒÖßT«Åêƒz¢4d[¦š­&ÚpªÇWÛ[¼îÏ rêÖ•HTMüëóH©i$Ê0¢‰ÉÒ­4%9 ˆD¬,m•³a,Whº–C«E"ãâù‹þ‹‚ž>™ÔÈâPš+ /L¸‰.8¤vÉ·ˆ¯¬)y.?o—Êgzèä¿0Hè©ç_»“‰³(ÚZЖQŽ›¿deÒ?åtÄWëà•ÈÊBsa)¼NIùkIýE^Qˆ×ñ8XäJ{k _z}»²²xu'CJ\ˆ¡5…aí8nW©-ÖR0©Ds®¯JT^ä¥A9£òª. "D ±,Ɉu Á,°‹ªmJ§|ÿhSéñXZ%ÿÔHž>nT7¦€t£Ge½®Ç•ͨ嘴Ýa™f»! ¿Ë2[ŽY8-¥ËÔû\fá°•/Sïs™…ƒ¹Ã2["PáHï²ÌÊ1ë,³Ûâ²¶ZUS–Y¬ô¼'£j7ÅoŠ J‡òd2e$™\ךß|â…]4+ðÂwýU@‚±½XÀõM]Íìù×€ö¼]ºVy•Ù®D/¿Þ.&Y´£æ·ë·{¡1ˆïþiüÏ]œû¦uYI^0UMGkÉË$ÑÖêšäÚ¼x^‘@ì ߺÉcTµ/XA6ÆÈb¹¾ã¾¼ûÒ9áe¨¹7R#wUÀi‚”uŽP45£ÕŠT¥]wF?ñ©TkuIš•Ó¯³fôë…Ú ­lÕÙ²êæÊ€’šÛç œŒšÍð•̾“®‹¥=QÉæ9.+ÃqeM2…Ê8秃k’„ n_´.žæ(¸”\Þ¹}É×àLªÆw`„•¢?•’÷§:¿ÔqÕö[ÏwóaiÝö^p¢ÚÐ,ÎêÏj'©µÂ[‰Zö¬ªY¨.auíI®âÍ·Ðñö 3…¡ÇyrÚÎ^H!U«þVÖÓ·rñÄ´¾“µ.½Š¤Y%~sõ—ÓÁô÷ë$œý„õ¦Î_¼ r² )S•Œéå©I4Mת°&ÁŒ+ba4ÌcyhôË|ŠRWчé‰GñàïwüSÝP =•“·tž€-þhÊ<[öWÒT[Ï覭ÚPŸ‚Šÿ»ºDjÁAµ#´ìТÞxV¤’]ìWø:«[Áv…S¬ÏŠV°\}WŸY®$›Ùd¬¢é ±ø{Š.Œ—Œ)¬&c\Y6«Iʸ¢1(­ [+ ·ÿ&SV(ˆC-í3ÜNüC“± èóÝfdMÕk’òM&ßñœuòõo…èLÐKœeâÊ Q·%Uјd–aâh†E™•µ"×[bH ¦ ÞCQ4Aúé¤_þNúi=æ-*É 03+³+F&ôhS[tgñмxþsxëø-ÓF7èöƒïÝøö¼wa³Ahj™VFyPzm)‘¶!ú)ËVææšÎ¼»ñ­í‡#@žÐxãÕÜY„Õ’-ïí¡šœô¬Å LI}Ê˼TUe‹0™æ?ë >ÇLÆÉbµ.ªÃUH ÓRà³j`É.S±ˆj* t­1¸·T G¡pä¨fQxÁ0yJf’dCXÏø-Ο‘ _Ü,_ŒçÈõ6©©ŸqÝCÔmÙ¡n 1¾sÃ[rm‡¡çÜ›’; BwlÏHèy³ƒÖoñ¦Swìð»! øó©½d…fãÑÎ:ÀljÏç"~¸\ÎîG'po#àaäñeSÁ KªajHVQ¥›©4ý-w]””’:ŸnûHÑmd ie‹mj’®×Øn…ÁDäê>D®îæät_9»»¨821Kéc[èXRëüèXkð²\@éLªÜ(>iYXvNV mðßÿ3 þj¼z¯z!ñ™k_Ïî‰;ÁüñÓ{0 Ÿô]˜¦xÄI,[Í“6[ÐpsVÚdi>ˆqñüÑ+Ø»ÀµÑêV”„êÆê @ÍœÞKú@ïî‚€p?CLámjî”$•ÇÝ€ü²¼™;výÌàÕjö…¼A$ê¹oý÷’?&À¦qÌ„»Ðñ§ÀëâbÓT2Ù–=9T1‹ÃQDf“œk‚ÈN„À`Øói U·ðó;óÂBÞ|sç'îGX{¹vº]3.…É™’n¤«X'A¦Éok­KoFUQË q9kXvL#aIÓy«¾ås‰¤ét"ï^áH8¿Çç0s¿:~TœþFù§9Ä@$žzÞ™S¡ê ·‰U@-8wÊ’®nÍ#Ì$Ù’ fYT¶tE§s°*(4 óGYw@æ`©—-5V%Wæ 6aa6aa>›p®‰I†V¢*ËX„³µ“ ižû#ê=äçyÕUJ­*º.ò¿‹üï"ÿ»Ò­¶„Å ž"Iµ¦„.µŒŒ0•{ê{¨‚ðoäÿ^JËXðÇ-wMJ®úñÍ»wä¹¼v—×vp»‡1$©"AòÀz ¾ÎüÚ ±&fÝÞÃôúûÕ»_^¿ùxÀ¿FÅ5•ö²Á…qØ~ÆÙûvÜÙÁZY¾¥èc§E<•÷Ðé÷äÍÇ?$/^ÿe~ûß{á!ͯ½ŠJÔ]ú¾ìEGÐÀ…,-V»mÈ5ñDK ý~ dZÕ‚m™F"I°–ý6bc6ß#Ǥ𿯸hšÍÖ¶éé`©Øp°–œ ² ß£î¿ £QÉßÔ »e¢G­lWÊÖ\ª­VhT# VÞˆÖÈ€y±¡X"³rq¨½Ìš€¿.Ó[™´Ê‡4šsˆ×^ìU —¸-YU–MÜOHu‚€+vfXº(󇦶äñvðQR…R‹]ï’bIjѺš· ®gcdi¢Û¿ön¼(uû™«ã»íaÐÚÒaGŒþwÓŒèuíœ÷u2ŽQIµê!é”Ï‘½ãþ¼šOÅÎlsxÐKLY…£Ã¬ôÖX’¡ôàñ€GÇóíñLœ®g'q„^{÷$¹Š:nÑOpùˆÝéº;À(Zæüôrõl©)v*›S•2D¯VÅÖ'Kùpaʸøs)ÇhÊŽ—xaj]&ýʉî\zî;ÍÈLT“˜™ÍmW¢‘Kú¯ÉuÉM*§º{S27Êmœ*H=zvª¦def ×75véîÕg IÙÀð>J!clÊÄP¥)^=Ê!cQ}×Éî^0QÎd·¡²¤ç Ð :g°£MUu×Éî^£6X¡éÉZ’Êò8`fëœX=Ԩлk«‡N–ÎxÑgfd“;)uôy‘Ý"ûò€¢ÏbITQÖÁ¥¬§6½IÐv#þ±7w7{pÍçî|±mã´¯ý=ᄀÔùÄÉ€"™4{ ãXJÍ™o’9ùG/‰Hk½mwtµ DÍïË$ŽÝ‚ö±9"·õ6u€V¬Š©3nU2Yæ¶ì¬¨Ûò—WoN·.ØéçP0E…r(|>tz„F$`ßaøZ®¸äZ?(Âð÷Æ/‹0üfaøŸ÷aO»9€Y™fÉz.0<2'w Ü;·a¸|zy9ö¥û¥z—Á<\^¢½ÿü”ݱ·X8c<²ç½uÝŠŸÊ¬ dÆñ|q¯e!`Ô4UÝTTK64ffBÀ˜,Y˜¸š Ù~bÀzÐñ&Ó¶„‰p.ð0Âúv%ÃÈ"š%üz¦x2ˆIfoÅ“{Ý…±Jô9Xfr­KB¦´½ÙÒ=;È,ÚÅó—äßÿå{×^¿“Ä%dnA °MÆÞlݤ˜ Êá \{2¦8pÚåßÜ@'ºLF|Óž]Œ¨)_ AòÙÄô¶”âÚ-_Ÿg)©Üâ{«Åd„9wøÖ篤‘JeFF†±6æø$ºp/`1ã5±Ñ-›ZÑuG%ïâ=jR)¶ä®iÒ®Ä)[ŽÈyËûƒ;sït}0Ò Duá∋k«uÕ´K£ˆ›@¦à˜m9cp‰O>/“"»­]µyAÞÖŽÚù¡®UÑM›/ô{¬ Œlê·uÚŽúÁÚíú)óù—ÉnE¥ydÃnÅ¡Ý)/’üÓº\7ﺭ{à»Ok‹¸ãŽÓ;a6‡`ymöx'ZôS‚†ToÎ\¤F£¦l+>Zg϶âc‹~Jð‘5ÃGV‚¬€ ˜×½pŒ¬‹—sE™ªBY!ƒ±¬ê<²Þtàs˜~ñüóÏÒÕÏïO:!Û>³>Vð ”ê[•{º$×¥kÐýhçŽOÜůÉuøcð´­Bm•m@„—³æÂôË7Î$áfÏ1:Æ…—Hzºd™µ¯%™™Àð6Õ&Ÿ È& ã-…6ìY(-œ¼Aí_ßa €‹ï_þô޼ýøóû§ÍóMm2x2ºþ4 ÿ<õ¼¿†ž4öæº ÿÜa°~Bk™&ïËúñêÃgòùç–àD]Ûþ_§¾7/…ÑÀWýúåç 'šNóU4uóÍF?ﬓçÑ*«{â­|Ô$LVãð î¤oO2ç« ìùåã»ùy÷åq.‚¾EзúAßú¾õÝr¤–8'zø¸ÛÒÚŠ¢S¦0Y1,êYKŸ*(ʪH2&¦¥O$–¾fÊ’í§ø–¾¤jO«2Yò‘ ¼ûsIÕÞ%G’U£`@Mö˜’ª§¥ê|ÆÝü?¾½¥óD鼦XÞ-³E*«H¡òpâ—)gB‹™-D i‘BZ¤®ÎD étC‘Bú`e…KÂ’³a…¤=°/hÊ{ç^û¶ï¶t@\̹r1§¼f‰àµíÁkÙe;aè.n‚ì so8#´ \£_Ẋîe\‘7ýòæÛkor¿ù+9‹£¸¶àóÿPK\áÒØn?&rPKH=27 styles.xmlí]Í’«8–ÞÏS8<ѵƒøÏª¼ÝÑÓQÕQ1u{ÝÛÔÅàœ?µê7˜Å,f߯1»y”y’ÑâÇ6¤ÉLÝŠ{£,Á9Ÿ¤OÒÑ‘øá÷/Çhõ¤Y˜ÄkUVÖ« ö?Œ÷ë¿}ý³d¯ÿå_~Hv»Ð üÄ;ƒ8—²ü5 ²,g$óq}Nã‡ÄÍÂì!vAö{É)ˆi¡‡ºô~IÁã-Ž…ë¥óà%ç-ŒdeÝ-ÿ›±p½´ŸºÏ¼…‘,Ä´^|—ð~É"i—H^r<¹yx¡ÅKÆßׇ¹iˆö׫WeáoÈk§Ÿrœ¹ñþìîaÒ.Ä ^rŽóêòçg½ÒÍB7¦ŠþxöBß]ýâÆÙêoqèA¼•¥OÈ^³<8¶u¦ù•æ5 ¤< &m¡°‚æýöòB³ {hNœÄK;´ñp:õÕ=@0û (E;M(%º(E˜f”¹ CÊ$¦F¢”ìvYK/M#›™¯ÌLj’­ ÿ`åâPrŠšl«ŸEc2 ¸(ù¬(šÅ P´Š h '@Ñ(N€"rœ »`¬e«’M×"´×¿_W~û0¦K¯bÝU$ÒeW3•,íši媮HÆ^¢C@Ê“(˜JYQ¸ñ²:Í‹:bDÂõk~¥²Lˆ}Ot©Üáí:¸1Te»«åºL ¯M²œPmªKª5ÏîlµÒ.AK6—  —Ø&Ÿ$->AC|樖lñÙà*œÏ d›Ï `È|jKv ÉM«\áÂdtðš`rÎQ«,›w- ·Öü&çýôé¦ë¼¨j|¿[•½êÎQ’F5N(T–ö[ê£iYr†:%®äº­ôqÏsÐç½·j…Eå>mY@ŒëX’‡µfQÍÚeS‡®òàx:¸¤í´|Êi…Á®å¡ðÌ&Û_/s87 1²L-íônZž”.\»·ûpeÕëÆ-C{{¼Õ>$ÓÁK6Ezý»W Izíœp´ðf!nгøn¯°4rlÏh:ñ¤kç¨û¼Aã&½ò&-·‰ÿzOMû'øÅÛ„ì6Úª_ÏlAç.ÐÛY×5‘¯O®‘¶áîu¼™d¢}7#§ßnùïÿ¿`Td·„sŽhmäna™‚U%vn= À³Úüú/¯ÇmR²×8i˺ñ›4“CøŽboÀ\ƒ*ƒ‰{så:„ì‰{ãä„^å~<„Ø›"× ¤}H|ØÛWáóAyš½•q Búåiö6Åu}LžîØ‚¸"ã}õ}¶šž~ çú%Ìk.­…®Ð?\`~‡E‹ ̧“–ì¼ó–÷0o¹q'ëÿ%®ñ×x,ä+Ú¢¸ÆãÅÿýqÌúæ5â»oÄ 6èˆìá —â⢗î 7—ps 7×'usi@¸¹°â#¹¹:,Z¬›këzßö°çÄ­ÓáÓ8º:ãñwøÏ¥ì¤áoÐªÊ F;._óvÝ+Ãð¯Å‘ÜÈݧ¸øþ³Å[‹â~`áX\ŠcQÜ,î^†gQ (î^ŠoQ (î÷/ Æ8iouЊû›‚Â?ûñý³ïÎ {¯K€ç½wæÛp'ð8ÆIÜè{ã{…[K¸µ„[K¸µÞ=ŠÂ­%ÜZKAQ¸µ„[k)( ·–pk}·–¬¶pm ×–pmsm}¤ÐCU„õÃ…vX´ØÐâ[µ®z/¾ÀžÙ ã>/Çuì;˜ÑÜêH¼þàm'È–£}V'÷3vßL§ŸäÉí ç?Õ+0žÿЯÀxþ3Áãù "Œç»Ð•Lußð@l¿Sª¼óv±>)U6l>OŽ.«€OÒ”M“OÒ‘ÂéGReKçÕaÅrŠš²Íi”êȧU@•N³€.ëœfSv¨YÂó$½^ãy‡^âyjÝ¢Üð<Ѿ߾ú·åÀ5>Y1µ1ã£n~öñQ‘u‹oA“ÎÍC6 >I[VÎ 4OäÕd•Ó&Õ-Þ![œVä-ãÕdÓ,`ȶe¾ÙøøîA`/ èØž9è˜ýü»T­MÃø`㣮nŒa|µë#Ÿ†ñÑäÝà\é:Ÿ$šºóI:²ø$U4šsŠê²Éi“jÉ*§QpEdrZ€ 8Í‚+"‹š%h\œYëÓи6ŽÆ)ÓpG[YbâÞò›vOÜÉÉ3q·T>I4ædQ4æE“aNQ4æµeÓ*€¬œ¢š¬;‚Æ»i\Y+3Ó8ûùK qc×ÇÑ8åAãb6¾Ù¸àfÁÍ ãfsn67 nÜ,¸YpótÜlMÃͦàfÁÍ‚›7 nžŽ›íi¸ÙÜ,¸Yp³àfÁÍÓq³3 7Û‚›7 nÜ,¸™››ëL+Ü} Eî+äÓ]ÿáGå+@^‰ºôÃ)r½àDàU#ƒ|h““uzÚ?¼àkrÏ úýŠØÄÒ5ú»8Ðeʪ¢Ó4Ê¥’"­8@~› ª";øº—{êàȶiÞW‡ËªÐdSw®Š{èpYwÐá²* Y''ÐïX÷Ðá²*®ÒaÓÏj#YOýªŒ&½<Ìñ‘~ÊšìTŽZ¥É=%7Nì¼í×ÁmÍæÒAÕ ²s ¾ªïØb•ñƸn’Ý.ôŠQÎùŠŸî.= ¸'Ñ :QdcþóOÊš!Ã^å[q×~_ìæŠQO§˜WŒÑé1\Áu]RPàš0IóÔ ó:jŒØi¿ºû©™—æ—¸tÚAÂÌ<÷ôÐ^lû§ÖMNè:&´DåKXꉭ뜪Ï(Óòm’úåçù>)ÉíðO­€£4nt_?Ì`×~…H»PaºÊfŠì’$Á¯"köòð/SÐws¸Î ‘9øqÜÆïÓVuÿ{Ùü>Ài»œœ_wÏ…Äüê·-@ý‡;¿eíü¹[-ýœ÷œõÕŽ]]®U“Tc; ìMÈgÎ:lÇQ,Ô¤)*ðkkE¯üèTÇѾ ïÏpÝ€LY“í™sœ§ðiùã´DqsXÖÕµøàVÍ\ñÁ­÷~î§DQ|pK|pk)(Šn‰n-EñÁ-ñÁ­¥ (>¸5ò~ãÎMÍ"ãèfp_¦biä¾¢$ôÄê7qž’ÙC ±ó+Ç8 užwŠzˆ4‰z$Ž›QPV`©Í¥ý"2B"F7w—ºö‰¥F V¹)p™v©ÿµÜ)@Ûm…θH~€ ìØ £U¥ Šfd†â—ûܺlXeÞ1WF° ¹éqU½šî¬©%Šój„î—¹BêÔ ¼‘N(AuUg«¤Ý ¦>¥ô;ádÑ}ž¶JÆÝpêQÊ,•Ú¥°¶û%Þ .·Ê›{?Ó.ÝmT¡Uµm1Ó©é®ÔÔÆÿß /r³ìqM6Ñ)[`µ¶ÉK14žŠ¬©çE˜ yB9Jœ( VÏÚT˜\˜T·¶ÆR¹õ?'p‰Sù‰ wjJ@/öMYH‘€‹[šyÂì½AsêªF#ɬŠù.Ê¿'ÿûÝ>ÿžâVà„rÚ­Ð9L1aCeü雡¨ÌŠºnT^£º$z(¢ù+ ¨²á\V½ º¬´âüKuh: «Î º‚ ‹¸ ‹ÚÜt7ØA›«ïöÝh¶ªÊº¦öØmȆÒÙVË8Éù-?õŒú 8í0M8v÷¡wͰ¦4Úaá"0nç·£fÛ£*y^±9޽»} ±-›–Í ñèáËïÅðò–àÚÓ·_80)7º×9ÄWIcðo˜ÃjÌz—ÅìõÁôãŒrYKJÇÄ ²Mïtàbõ0¨)†`Œ¦èãÔslN+Ò³—LÍ -n6íº-ç#µ™GåXºðÑd?ñÎÇ2n2ûòÿPKüPáÌ 1PKH=27meta.xml”Moœ0†ïýåê5Ò,©‡¨9TY©[õX{–8Ù¦›þûbó!Xõ€Ä…™ç}g<È?Ú&øÚ%‹¢0ɲ.Âç't ËO¹º\Êë[µ`«`JCÇTöZRUa¨¬Z0Ô2ª:³„®iê ‘FÈßEøfmG1¾^¯‡krPºÆ$Ë2ì³3ÊÙÂu½n<ņ\ƒÉà™uîmʱë–: fÈVÖeŸÇZ³öRJ-M;Ù8ßzE)ßgÚ´¢Ù[ѱˆ©¶j¾6›™VR´{m»êzº ÍJ”óý»A•¹W te•._Ï—Õ©ñÝO!“8Ø&~uZ½³øó1j ¹ûÒ‹†£ŒÄYŽosΨ¶ò¤® OJHœVÎñBŒÝ)¬¨†qhðRI˜loS£À¿ NˆWJw(ÊP£ˆÆ1ï'õ–smK¬.9»=87ŸIJ“ˆÞ§-¼m§‡#¡-}<“ˆ¦Ã“NµWón*Y÷U åE §g︄FWàÃQeØ_Ö€)Ó‡Éè&¾…y¯ý ËÓ™¯ä[’~¿‘-Ä(ì hÄá"$ðÀGÜzá³¼¨€„xïÃ’}Xº`ËʸE1V°V¯nõ†¯¥—¶ã$s ¼Ùjü¿\ùPKÀŽõû!PKH=27Thumbnails/thumbnail.pngÝVmT’ ~15rc³­eùA³íŒ}l«'uÀ¤¯•>VÌF!eÔZwE'Ó#o(M§¬Ži³É£ä6ب0ŠEoXŽZDXãËËÎ)?G”ÏuÎÙÝŸsÎþÛ³î¹ÏŸçÞûœsŸ{¯#àQ!›B@>tð8 VR ¼g,P!¬¶>¸/ól³Å û«³>è¥ø²Û¯üÔ°<ö®x?~Õàn-ëÙãÍkMûdË“V¿gõåÅá¶à\À9|¾@~l¾ùÐïppÕ>ß©¬ö?ºg$i'd|–Fm ¢Gj3fé)Š»$ǨBV“.Ѫðcÿx_pm6Lvfô†¬)©¹2hˆž\E«N‘4%ŸŠ—Ô1fošØüKKôuUÀÜœN3} [­È!†¥H¦3øðÒ_• d²qÍ—”L:–F£Ì]Ü›õºäc÷™õ§ê,&¤¤ŒdÚë^§)ªð^üZh¹L–-ˆ]úó Ÿ˜zÜKþ®ô6$“|K&„¹Ù{•O4qvM¬ðÂQ‰'¶ÈhyãÄ bÂ,?ºDª ŦSmõU”DKÕ-ß®Â#àOoüBkÙš†×š³Ø"{Ý­öœÕ.ÎÀk¹Y÷·QÛ  ›Ä5ë^¹JÚ¹?•Md²î¡¨Ìm–l/U?ßîi?ÊÉfi¾Ñ7Êßå1©wŒÜ„» Š8ÁÔüQ5ÃgÐ ?qñeÍS7â©8©†®šÎ `O׎½’8Eôœqa–¿ôõRVÚIÓS̲œf®×»b€ª.#ª³†R·s/ Ë#bûs¡/®Ò’޹ÀÒ€°ËßÏV$ŽÓi¿ÿp£#[ž¼ âÖ8ëK£à™ÙÌlïm Iö퉀7y%; â®ig6$XÑe©ýHà+ —ÈÕ:ÌM“h±¤ñÊ×-ËÇ:=ôíÎÞ' Í!E•ÔÆn-ü‹ãÒUb‚*¢*{Fz”Nøû&É´ÉXî„OXÚ)¯ñ´¶R}\ˆ@aõàJ#‘HJç#’º t>:ŠJT%U°ò©ê¬—‘39AFø­Ý±rkC ó§î¬Œ¯&ÄàÆu§íR|kÒÓë~UZ©›ûaõ9Šãhó<–ŒÛΊ¶õ×Þ%·©È™(€³™Py‹n^tzúÕé» æIÕn¶Û]j²ï|§Ð¶è{Ô¤îSM-Ïéü=:Šˆ„ª~é”&úG’«Ã7vXà öòðÃøá(C-lõÿ™¼²Xéh‹ðù×é9VÁÎ ÚžEͨ¦ò¦"àëoàï@à:`í½»Àãÿ$;Zùº‡8ñÙM/é™#×àn×Àmi7ÅÆîçõ~¸Ø@ö¤bç£Ç½¬@’=× -ÀLЖi™c˫ȕG'êÑỷ€Ó}Aôzb‹ñ$.×/ïA æ{¸5ç’ã­æóa£žÑ úŒ‰ùrˆà‡mzæõgÓ ¿žœë'H¿¿D+¢ü»± àÀüè‘Fé{ç)3¨xMêú[÷+p_ õÙû.²úI£ƒ¦ˆ¯A5%²¤¼­XüÛ‹¼=¾TîE7å O_y*ï ›?K:¾vvðéŸÖ#¡b†®Kìì‰/©,¼<£jóíÍßôBñ ½0a_YÔÊß_èO¦äUó¸t_8´j¾q<òí`/6!9 o…©«„¡ƒµ— ¸\ÿdxDï]ÖÕ€¬-‚"Y¦ÍZËÊl`¦Vˆ0 °òPÉZóVÇ pEN¦c„ƒE«7B‡Ûƒß–)Y± ’®èñì=CF(Þà ¦§\ItùuÅ–³JÞÏ®;ö¢0q*ÚŸÏnqo3ú”·yUع᪋:ÂFOTÜ*—„ŠoGñÙ"W,iÈ–àÉÀŸT¿È(Ä.fõÒ±¯”…À·I ¼ØrñâÙB¯Ü°qê.Ÿg‡ŒZKè;hB6UEêL]l#6FtBÂd'+fÊÒ,ÒÃS.\éahF‹ºb`n¡‡„¹ø¸2xH˜+&œÿÿš$sÍ V“Ô]*s䔡T髚jfñ/xºìùÐ;"7N\9#Ú"§K Z&Ä‘Ð_‡‡(ä„ÈÑF>‰²»d–âŽãñ?Ðã±=z,ʨ%áË„0µb̳‡ô÷? ñF~Bö‘a{Mx¸ßxH{÷2’0ijw­6íÛ?Ò¾«•»ž1DÛÃÓç:æBQK†ÂlÒOi­üú[ ø=&¨°x ?gd®Æ*Ò E.I[Ä“mRÙ´åIóÕ({WÖl¡FÚ†l©Ìi+r¢'¸\ÐNyr6Q­}ÈlÄô&^‡Ð9¶mäïÜ—¿¥×ùlPPĶzª¾$ j§§˜@ŠáQ/FÍP­êÈÁ¾ìo)#¾ýîü¼ëÜ÷÷(hc¦⎚å»/Ô¿«¥êfùQ0áóqà/xPTÑÕcQƒF'äÙEÅ´ˆ÷ t¸x.¢BÝçx·Ù›Dì…Å´ 6è†2¢Š’¾ƒù{YL~’ ÖSDÛ€T¢"ޤjþ„*Œî¯¤'$Öõ#CÄ`aH.D~¹…‰Ly=W¥%О hß=Ì NÕt•áQ‘(y0±VléŒE¾åP¸ZNÏ{wRÿì"‡›t1?´Nž&Z‹hOdò?DîЇëãÅiët—„eQ7Zæ¢Løø¶,Æx:žMùÚ ØÙxI89›|U.Lc¾)âÁaöýö§•¥3þ£¢Ý›3­>êu†zx­.Öº oëÚ|­OÚ³p~žcr¯[–véÌ.&æÝûo½ŽNæ“—^çîqhpoèøzÛ{€åT\ [œÕÉè>ìÐ; À,ÔÇÀ¸£u tM€Lî ,BàÈ÷è/òù<ºïIð*h œ4AÍ©©Cðcït îÀéÁòYÊ¥‡:¦Í”× öîaìÉ+O³,ãµ–8yÛŒwÚ•JhÄóÅ5ŒÁ–ößIáM?:;¹zÒwGÇmS;‰ÍÝÝßòôEêÕ"»{„]º†µñ+Œgê¦nXÆëèñ¡ê¾õê“ûºqo—SmLŒ×¤0ºFØW["ü ôAKض;Ù½OsÖZž*á©wÇÄÔMÐ+ÔG"øeÜk û æ@¯‚î@šÚ·ŽˆsñüöJÞOAÇCSx¶ffĶÙvDŸEz¥½Èx(þÄ;[Ù"EE€g!o従®ÿXÏ.ê¹UŽþw¬’öŸ‚ÍPK`Hv<†k(PKH=27META-INF/manifest.xml½–ÛnÛ €ïû÷18vçƒâT™_ï¢{J°‹„qèš·¶Ö&[«¶‰Ì¸ùAÂßÇá7°¹{yôDµaRÔ ‰ˆ¨ òÀÄPƒŸ÷ݪw͈ۛ멱ÕK%òß óÚ¬Ó¢’Ø0S Öx‘ô}J#Eϧg‘YCã•Î<` ¡œú¦Ô8­§©úÕ î "è¹Ä–‚+©œò©àáµ|Š…ÛéièÁàVJ ÎFÚÝ®‹|ŸiSdñ¯±`Dé¤Êвë|ü–ß6¨kÑ.kòýÆy[ Ã'ê—´ùwm׿ež”ñ„øêuÒÎ1Am– ¬,t…úã…4KŸ-œÎôw©>Oíu‡þÇ\cœšÅ±#µx± êþÑ3n }©.¶]gðe–ZëP¯K»oÞOÛßPKc|½&²z PKH=273&¬¨//mimetypePKH=27UConfigurations2/statusbar/PKH=27'Configurations2/accelerator/current.xmlPKH=27äConfigurations2/floater/PKH=27Configurations2/popupmenu/PKH=27RConfigurations2/progressbar/PKH=27ŒConfigurations2/menubar/PKH=27ÂConfigurations2/toolbar/PKH=27øConfigurations2/images/Bitmaps/PKH=27ÿ©òI9ÈÒ-5Pictures/200003980000CE300000A5287E783C84.wmfPKH=27fÃÈ- -‘;Pictures/20000033000489FF000675C0FD0A4C7E.wmfPKH=27yå?:ÍÍ-?Pictures/100000000000003C0000003ADFD79719.pngPKH=27*žyø,ø,-1BPictures/100000000000021D0000010D41049910.pngPKH=27\áÒØn?&r tocontent.xmlPKH=27üPáÌ 1 ¯styles.xmlPKH=27ÀŽõû!`Âmeta.xmlPKH=27½‡y ¢&‘ÄThumbnails/thumbnail.pngPKH=27`Hv<†k( yËsettings.xmlPKH=27c|½&²z 9ÒMETA-INF/manifest.xmlPKZ.Ôprocmail-lib-2009.1202/doc/article/slides.ppt000066400000000000000000003300001130547513300206010ustar00rootroot00000000000000ÐÏࡱá>þÿ ·Ìþÿÿÿµ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ`!ðb5X¾t˜‹gFŽêûÅ»Nkˆ ·ýÿÿ¿üÿÿIAS¾>0þxÚ­—_HSQÇwwÇ9­éî½›®”pêÜîtÿ7Ó>…ý„þPpJ$ŒLB-²—Ê8PЉJ‚=XAˆORB7ê±^ +$¬‡E"Ñ:¿é,BÒ¹ðãÜÏùí|¾wçÂ8À æ°^FV¢Ï Ð€3x·Á €°joᮿiÆû§‹ŸÏ0±ñ'›inn^œ­“aÞ@2©étœ‹ai…U".¥¿É#u4>qOxg¼O}È «aéÊ®6,¥¡3›&fÆo,5ÛíëëûëYVJ>'vÇ0ÞnEÎæ¬dN$Öb— ãã’µyâ.›gs-2³(æÑŒFQüCÎežšz¸ŠÙž1›¡C“Rê VsƤ,*Iy´!¥TSj›Ü¡ÖËØÏ•4==½†$ ï-ZË|B7«`9…[¬®D0“±Ïg·Ð„FüN;Jø™“òž’¤¼ÅžRSJM›s™5mçšÌ÷œIùtÅ'CN©dd^Ïìsâ›<ÎÞ$& ó2?vR¸QþCxP–”;+y½ÁWN4Véä|%‡™—ù³NV뤸šÂp%2/ófÝ_£“!…H52/s³~pëÄë¦0áBæe6ytÒ©êdÌCa·™—ù:³þòêd»—Â;2/se­N.Õéäu-…v/2/ó}fuøurÔGa®™—¹‰Yït2ë§pчÌËü‚Y#!œ RȼÌmÌ:ÖIA˜Âí 2sÂòݯIóM:HXNú‘y™• &m iÒµ`Âr5€ÌËaÖ†°&= %,£Ad^æ}ÌÚѤ7á„åe™—¹‹YÏD5)IX¾†‘yýòw–PØ%Q Ö¤\cGæclʈpØÖkšµ÷šîØù˜Ìû€¹§$n½ìˆ[·•"ÿß*k.+¨dÖkYA›9—Ò°ó á¦mXüÈjH4´*ÈË™Ws´%û1rˆ•bk1N*Èëu´™ê/ïee޵=‹"¯×á²öÖ7KÏYõÇ\Öh ù_Çrûn\ш§È¤ìvâÙ#{ª\~ß fþQüÈ’ŒnðÞ"ë&ÓBwêÐõ<@å§ _ÿ‰PNG  IHDR<:ÉÎe³bKGDþðˆü) cmPPJCmp0712øêÌ`•ÇZÖÛòÊÁôhCæ5²¿¹eªÅFê°À‚< ”^ÆÍ(âÌÚÛÇ ›Ü]·çT\ÀºžƒÕ°'ÝŽ¿¦·šcæ.2Û—üh#¢ãÌò¬3ÏãÞh5"/€Ýw":ˆ|¾8µ¬¿ÎO$_ü÷ùùUH%‚Âg­Gƒ*]¹ÞeQâ¤ìþÁDã+PK#ƒñL ׬»ÕqxH'j>“6mÛHR6¢Vk9¶ö½FÛì¹ÌzüãUÎ'wË6GRš1RŠÙ NRaCDyÓÌ û'Ÿr©ñ…)ÎP@¾Þ¤3$Ò ÓÆKÛÓ?;>ÉÚ´Ûk‹X2pèxIƽå7ÁÐâ+Þ4Áù³n{c+f[èÙì4;1Øûaóò*ÄÑÝÙ|´ºRjÛ| ‘¼áÈ7-æ6–#âþý× Ù¦•ô¥ÔÈ…¼ìu̪&0ZšÅg±T%…Fo¨jÅÁ;÷¹TœEÜÓoU]ö-Ý®ûŸ‚ýª‡é‰~‚á&tEXtCommentOptimized by Ulead SmartSaver!)ãö·IEND®B`‚`!ð9ßèÓ!WY—“r†Z¦!RÈÒ@ûÿÿqþÿÿ ®RÒIHì8þxÚÍ}w¸Tųmõô‘ŒDAŽdD JœsÎ9ç,ÉIr (A ˆ’Q’¤Q ¢ˆ ‚0]]¯ªe¼÷Ý;žyô¾òìêéY«Öê={w}8*H Ûuˆ ðŸ8‰ƒo…ä(qà«ÇßÄ‹ÇG&à^æ?A޼œð;áIþùóôå¾Õ OgÄq¯Ñ?3ð7"ü_ˆÚ}Ëï—J²ê1PÙ¦†6 ô±ñ`Œ À{i™}Bkí#ÚhÒÇöÏbçáøËf„MÏñ1o¤Žæ5ÕÖ¼®Zò×r¡ðV¨G+Žj• \¨ô´}ùoo;€ÿ»Ó¾owÛ•vŸ]cÚì9»ÅÞä‘¿ì~›¾·/Ñy›Ÿ®Û2t×֡Ƕ5)êAñi %¡á”‚FRJC©9Òq¼J3è šI…i¤T€–P>ZÁã›(+}N饢K”˜îRm26)<°™áŽÍ 7mq¸j+Â[ÎØ&pÒ¶‚ïm;øÎv€c¶3µÝøk<]êZõ8 鄺¨Ž§‹ëe*Ap±J\À_ ªcú;Zü––pÌÆžÁ\¸!˜7³ò׺fB°†¬nF˙ժœY¡Þ6ËT³TU6‹UM3_50ï©fŠêlƪþf˜mú¨™¦“Znš©Í¦¶úÚ”WgLõ‹É­_R©1)…Æä0!Ž'pÜkî™ßxÒ/o@B¼Éñ,¤Ãï!@^Üå΃ð#çQøŒ þs>ýÏóê솥ÿÌŠóÏyU ä¼Ê Ÿð¹ô‰5Ô C'Õ‘£XhÉÅ6‚'PÁÛð‡ß /Ü‚Ìp ’Á~÷)¸KGá}Gi'ì¤a ­†Ù´FÐTèJ#¡õ…2ÔòR#HGU!.•æÕ|~²Ùá>/Û”ð…M ÛùœÞbµ«å¿«ùýi½ÏRuûøÎg¨:äTµ-Ø –`˜ˆ£aN‡ö¸êãZ¨ˆÛ 8î…üx²âiȈ— ;ï°Û÷!>bçCŸ@\ ñA ªŒ˜HåÄTªfR1·jŒ…UW,§F`-5 ›«µØUíÁAê8ŽS7ð=õ—¨Äv­Êd7«v—*k¿VuíQÕÖžT}ìy5Ò^QSí µÀþ¢VÚ»ê#{_m±ªö¡ÚeÿRüùRÿ?¬Æ&ŽmVÙ8°ÐƇiüúH› zñYØÒf€j6 µ¹à[^°%ྠW°|ƒMÝÄz5ýðŒÕœäV³¯Æ¼*²:¿óŠü«uƒWí2¯Þ^Åc¼š_óª~Æ«»Wy¯ö^õ ¼úCø,èΕ´âŠêqe•¸ÂR\iA®87Wà 2°’T¬( +KÀ Ei€}ÈרMüÙøÄÅó»ñ¼g¤ø[GX4öŽ&qŽÆ‘j´š¨fëR”Ÿc­ËŸï“FÔ£47˜[]òØ"—*UêÈ)rh­«ÒOº]×2£µæ( íuih§›Ñ ݆nj÷ÃПné>ŒX:êêÝ8ïK?k÷Ã0ŽnëÑŒØ ºèfïp>†~Ñ2î‡á Ýç«Å=½úë…ÐOÎù~úC˸†3ô@ŸâØõ:Žïøø4ý©eÜÃ-z¨¯sì†!ú3ŽË||ƒi÷Ãðý¥ÿä8 ïèC0LÿÎÇé±–q? ñá ߥŸè 0BŸáà®TÇ…–q? iÁèÔ·a´¾É‘Œ_Ô2î‡!'Xã ŒÓa¬~™si÷ÃPŒ_*Ì‘@MÐqÔx]€‹€ ʸ†ÊVàH«&éÔeø¸è ŒûahÂ¥6äÈ©¦ê¬jŠ®ÃÇ NPÆý0t¸ÁŽEÔ ]PMç¾+n°3Ä Ê¸†¡?8ˆ£‚zO—ãèËǃ!APÆý0L†„Á õÕ]‡c O„DA÷ðp´Wóuk5Oφ‚ 9dÜÃJl\Æ1÷y“8òñ l”q? [펥¼Ï[Èñ!¶ n澌ûa8Àh_1ê&Þç}ȱ‡ó¯±uPÆ=ÝíÇ^{^ïæ8ÆÇ§±MPÆý0üÌh78¾·ÿÑG9®`ÛàMl”q? !F{ÄqÕ^â=ø%}Ÿcû ŒûaHlÛpܳWôÍÇ m‡ ŒûaÈd;30b€w`Ö^Ó©9Ïh;eÜC~F{•#ïÀ’ð~/;絃2 £•æx…we™y¿WÔv ¾É!ã~êØ®ÁšyW–Ÿ÷yUø¸¶í”qOûVFkÍQŽ÷yoñ>¯)·±Ýƒ2î‡a€íìÈõ莮E¿êîœ÷³=ƒ2î‡a<£åhGwyþ›ÁÇãl¯ ŒûaXÀhs9úóÞµ7ý®gØÞÁy2î‡á²üÇvÞçmá}Þ>¾heÜW?=0øÇA é¯8nÙAÁ»2$F/È‘Ÿß áA÷ÃP‰Ñ*p¤å}^jŽ·hD°"‡Œ{ÚUÒÈ`CFÌÅû¼lu8oD£‚2£uæ(Æû¼Âíø¸ ʸ†whLp#Vá}^Žþœ¥±A÷Ã0Ѧp4á}^CŽñ|<•ÆeÜÃrF[ÂÑ’ò½\Æ!ã~6Óøà&F Éyž<¸žóiBPÆý0|Åh_rL”¼OÜÍÇûhbPÆcËðì§[áïF÷¦Þ0œªóŽ2§^n«ºÜÏ3 A[j«Á|[¦Û:0Æ6‚¾¶%´¶¡ºíEìPÞé¼ qì,¸Ëá;Ü[p7ÌÅ#0/@ üÊarbb•3ªæUõSR0ÕÔǦ‰Zb:©I¦¿bF©nf²jef«†f‘ªeV¨ªf•ªbV«zfT°¾lbÞ ¶6ƒ]L¯àÓ18Ö4Î1u‚kÌÛÁ¦Hð{“3xÓ¤ ’IL‹õëø³®Žgug<¤Çá½×êÏq>“ôŸ8L'³=u.ÛV—µ u#[]w³åõp[RO³oðî?¿^ióèu6×?®>ß“ƒð“ÈÿMÍ8§¦¶S³‹Õª0A0þ¥ â-]Ïè.xP¿‹ÛõJ\£¿Àùú«yÄjR°š<¶.ÇjšØjº‡-§GÚzº-¤Û|zµÍí”l°9´œ+ÙqMPjù7UÿýuѱÑé¨ ¹þffp°éìnº™v¬¡ip¶©\Å>5Eƒ‡MžàE“)ø‡IL€*ø2Þ×Eñ'] OóªУxUâ‡z3.ÕßàL} Çê'8X'·Ýu^™’¶‘®ikê6¶‚îkßÔ£mQÖó:¯N^^\.V=Õ.rsäy¯þ‹íkz&¯êö£Ÿ-«ÛÚʺ¶­£KÙ¦:§íÀÞõÒ!öð'¯âl½WèE¸QÁ]º+Öuø,*Ž7u þ©a0ø§I¼l²˜|Á¦DðS)8×Ô Ž7-‚Cx-{šžÁf@°…lÌk-Ñèi4ähàbÄÓ/%þ·gÜÿÛô0¹‚}M¶à`®e´IœÂuÍ3‰ØÜlé}æW}Â\Õ?™Óú‘9¤²žÌ¬«ë«Ì:[²Þ~8TOžz¶ÓÛ°¯C } Ëé?°˜ŽË¾¥åó%·Í¬‹Û´º²M®ØDºµ«»ZÅkbý8ú?–8@ÿJ÷Ým}O Ú$¼ËO¥KØ |¾Æèô¼fñlAýKr'YAÁÚúSlÊŸÖŽz2öÑp¸nÍçxUœ§ ã*?щñsýØÑ7Ì}Êü¨¿6wõVóD`‚Áæ…à4“š¯ƒCÍ+Áþ&G°Ÿ‡Ç«¼6¯{¸ÈÃçmî§‘+ØãiÄv ÂWÈ‘æœeΪqæ´šlŽ«÷̵Ø|­Öš]j›Ù¬¾6kÔ)³XÝ03Ôc3F%Æ* vRE°©ªŽÕU[|K Á‚j&fWë0½Ú‹IÔ ¨_ñ({RÛŸ §½Eí)¨h¿…zö ´°_A»ºØÏ¡›Ý½íZèi×qþ!´±¡¡ÝUìgPœç䲇àE{œ±.À/xNâ}ØVbB5Ó¨>˜M5aþ²XFåÁš*6WdºªÛf°úÁ¼ËõÏR[Ì2µÒ¬WsÌV5ÑìQÃYßÖÙË|ÇWíª«9©Ä‡ûñãÇG¸‹õ°#¡—Å1•'»<¶×Ü[·n=9·CN 5ìtî4§²/“¡©-íxhkDZ‡cسюI»òœŽ<·­ÁsÞã¹³ù=sù½óc¡Ã‰mEÃî4~FEé]E‰ ‘]«¸™æCg;‡ÙgqÌãã<¶šÛ¥Ì¼ÂÍ‹-ã—_~ÁƒÚŒ*D‹hm¢Q´Šæ®O]÷»sÞ™ÇÛóë­y^s®°1WWŸ«œØVy½§˜™jŸ]ÓÍR5Å,Q’?ŸÖ°»#ÍZ>GרѼ{gÞWøüašl–s¾R5(™÷|gX˜q8ÂG™…Ì6Ñg3Û{ŽQ˜¥©D*’y~Ü[dÆóîi"ÇlµˆÙ$÷ãÞ ®{*×9“õÌf=óÌÇ L Ì\5×,P³x&óü¸7•W~¦™ÎlS˜m’Ó"ŒÂ,H%RÑÔ(ÎÈî­3ï¨Ípõ;¸ÎLP’ûqo)ŸÑ‹¹öe|½_i¦ªX0ÓZÖ·ÚLS+X‡ÌóãÞbvk™Ël£™m„Ó"ŒÂ,H%RÑâ(ÎÈîí0}ÕNÓc„ÚÁ.Jîǽ ìÒz®s£§>á»åV3Ò1ÓvÖ·•u~̯Ë3}ÔnÓ‹Ùz0[W§E…Y*J¤"™çǽӦ¥:kZqtåýI%¹÷¾a—ñê1½Õw¦§:aº9a:eº«ã¬ó¿.óü¸wˆ»ß#¦³µc¶ÖN‹0 ³T •HE2Ï{?™úê¦iÀÑZ]g%÷ãÞ^ù󦣺dÚ««¦C–M[u…5þ‡_?ÇNž‰âlìÞÓ‚›1cflè´«°KR°É¼Ø2V«V-âµ=È=z"î/’'q¯5Ѥ †÷ÿïòþ*ï‡çšCJæÅ–±^½zç˜Ãj¡9À×ð}|çØÃ÷¬Ïx7þ@o0é5õûÜé-qU޵Æ-ZD¼îT›Ì§®wÙi6ò§x=Ÿ×¹—üYï1wôvsOo6j™[Æ:D`üÂ|躤oxWöï—NóÞâ¢ùAŸ5ç¹{½¤škú ¹¡e^l»wïQú±sf¾ºÌû‹ë|/¾ÍwÉ?¸?¾cŽê›æ{}ÕœÔÿq½eìwkŒÀø33üÆ÷ãÜQ=á» ñ8>îÔîdÑìãî|¿¾gk™[Æ#FD`´Ì q˜J€ƒTRìÏ}]oõ~¤ÓàÇ:nåz»Ž‹»´â^ðìkK˜1%öQi±‡Ê„]UVì¨ra[õ:.Ó¯âû:~Àû:7h™[Æ™3gF`̉íT>l­ rÏZ ›¨ÒØ@UÄ÷tœ£Kâ]ë\Ì‹-ã‚ "0–†ªÖU•°–ªÁÝ{]¬¢šá8Ý'èÚ8EWÅéºW óžOc¸o«…ÕT}¬Ì=zÕ˹ï´ãhïâMÕ£'Ñ=\ ÕÝ9ºá0݇ë68J7DZºŽ×‚ÛŠ&Nœ¡"© –R=°¸ê‡EÔ`,¤FaO= ûèØ_÷ÆA®‚®ÿ#ÚbWýØV4zôè«2 «¡X«xM½‹yÕÌ¥fc{=;鉨UÁz8öÖ2/¶Œýû÷À8ó¨i˜SÍÂljƨ¥˜Y­qßµj¡ck=Û陨QË´êL­vbm½ëéMØP¯ÃÆz%6Ó2ÏÏuy#¦Q[0•ú S¨/0©ú«£XQÄ*úK¬®wc-ý)ÖÕ2ÏϽçKL¢`"f‰¯Žc÷}°ËXZŸÇ·ô),§a}+k™[Æ D`<‰Au•º„?¡Ÿñ1ÜÇBúÑ7±¸¾Š¥ôðM-óbËX³fÍŒ70¿â_pÿ„Gx þqlM˜O?ÁúÔ¿aa-óbËX¹r匙Åâ]Ú_!¡ý’Ú›ÆÆè6›Nlsêx6·V6¯–y±e,[¶lÆÄÌ’ÜÞ`–á%{bì%ÈmÓél6£Îl3ëô6‹Ne³j™[ÆâÅ‹G`ÌÄ,YíEf¹¯Ù³ð†= ¥lr]Ô¦Ô¯Ûu^›Vç°´ÌóÃXÀž"ö³œ€²ö;÷½ÙZ6¾®jê·í úM›L³)´Ì‹-cÁ‚#0–g–*ö(³†úö 4±û¡ÝÜt#G×±ñt5f—y~ÚÐÊîƒö èúô{Íýì_¾öq ‡ :Y ´´JËìVÍa‡jÛT'تD™Ôò|IدIpPe¥¹,4'0ö+Éc‹œ.]ºÈ‚6nØIpÓ ªä~ž)‹â„8"ΈCâ”8&Ήƒâ¤8*ΊÃâ´8.ÎË ÈJÈŠÈÊÈ ÉJÉŠÉÊÉ ÊJÊŠÊÊÊ ËJËŠËÊË •¤é}ŠKË)-¦äĈ4“bhå¥ÑT”†PyêMµ©µ¤ÔêÓPªF©Ï,N«éuÚB¹i¿ã¥§k”‚îSBÒ ”ðÄÆÀ¶Ü±¥Ù½*pÕÖ‡‹¶9œ³íàÛ N[9·Å‡Ø:zýäÏp´‰s4¤¢Ä* %T/S• ”¡{Ð~‚žôL¢ð} ûh5\¢9ð˜ÆA 9¡ ”€VPA]÷·Ÿª U9ªŠÁH•ƪl0Q¥ƒi* ÌæZ¨‡´LݦÕê}È+ò‰:@ÛÕNÚ£6ÑWj5VÓé5®«–ôPU¢¸‚”šW!&†rRRÞ€Ôù|Ÿæ°b©W*¢D‰2Q(JE±(Ä qDœ‡Ä)©äНÒAzÅè&T§³Ð†à ÚÓé#XMË`-€4 ÐT8Aãܦ¡ðúCzò§¥3¤ƒv ZB~®®Ô‡rPªBu®°Š«óù>5áÏã+”ZUc¶jÐ[½B/$õ5÷ìÙÈ=)½B:È^õ¤œJòçÛA†‘»Ó‹Œ–J jwÊ¥$-òýû÷ÿiHÝRo4È‘ï@rfȹú½3$šsö¾¹¡oªK¨1µá«I jGM¨ 5¤^T—PMFUùªS‘c £í0€ÏÁ^ôt¡¯ „tÓwŒqÒáĶ"ªüÊ3*Êî*JíitàèÈщFrŒâÃùX—_Ïì\´åã¶ü k˯·£Ñ#ÝûŸïyh¸’ô&œä8ÅqšÞâ(ÃQŽóò<^_¯Ç9¾ã8Æù1z›£çeyü-÷þç[ÿp%s¨2,e†ÕT ÖQuøêó×Vœwåñ~üú˜JïÀ»4 FÑ@A=øk[Îóx-÷þX_Õ¯_F%…]%éÓLf™Æl“9&8Ö¡0–Á¾þŒ¦Þx¬)3×¹Tºê+Áûp¬¥*°Þ©¨ýL%Ï÷i {6•ºs•Ýa{1“zÂ{\Ù{Ô‡ûñX¾šà9XE¾*÷ƒ‰üÚDž3‰çNæ÷Èûc[ÉÑ£GŸQI>WIjG-Ù§Æ0…ê2{Ígz²†=YË㲺ë©ûQ–ó×En~m~_=~#Æiêð|W/3C&XF™¹’XI9ùëkœáñRüzö©ûQ–™ß„ñTŒ¿¾ÎyÏæÞïë¼*³˜e&³Mã˜âXËðj¼É«RŠYKð×B<–—W/;{ \õ/³™Ù«—aeáê_aÙž©ÄÏy5ŠrE¹Òb|>㪋s”àãR¥y¼4¿^šç•b%¥ø<*ÉQ‚‹ssï¾ó*\ÉdÊÏȲ9˜9kObžú’ó×¹ìßtÊíÞÛJ*V^á.2‚šÑ8jÄûÔú4ƒêо{,äérªÌ»Ò ´žw¨ë©/à±ÁüÚ0ž3‚çŽæ÷Œã¿8›B‚ã§SˆáÝH ïF²QŽŒÉý ¢øBt^¦ÿpÄ Hî§oú¯ÝTWº£ÙMEFÎFÝ­£ïeô}.÷…|€‘¿fä´é•ä~KByU„=¯KBY%¹äÐãéÊÅ ”€nJr?çF1èÅ}JyF,ëP%¾½H©9ï-ó+õ8)Éý O¢‡ðä_Çî¹ÜOwj¨ÔPAå‚âe•ä~öï²Çy Ä?ȯFqnDþ*i –C ×+¹7¾á]ò7î÷í…ËÜJîÇ«Üo\á¾#Œ,¹7ŽÒ)‡®WòçëïÂÿþà÷¶ûéÇ÷|ŸºÁñߣÐ?_Ÿ—Ê1Äwh‚*è+uýÊ;­û¼Ózâ^{¾Uý¯ž¿¯ª ƒøÓ>Rå€É*ÌWh­º@;ÔçtX­  j,ýª:ªšôB (ed£ì4”Ÿ;¹7 ©ÍHK™9(U _—ªÓ_ª ý¬ñ•o:Q«ésµ‰ñvÒfu€>R'èu‰–«Û´P=$ù.Èt•Ä}WD¾;2Bå‡!|åé¯ÊqW^º«ºÐEI~:ÆÑ\ý0Ê@ù½¸íB…í¨X • 4¦2ºô6Ǫ1ÝU-èÕŽnª.ô£êE—ÕvcQ£é¤œhΚ«ámh;T3Ø¥êÁç¬pŸ*Ta8¢rÃqõüÀ«p‘ßý£z@·Õ ú]£GêY^‘8O(q`5¥ L¥,þT€ë.¨Hµ©U õ¤ Áø4ÊE¼§—#|#\Ä¥á.’Ñ€@fê(@ÍoS@3*èÇÞL¡LU”,ð1%ì¡@à ©³ô@]§;êöDÁ•ΫŒp’¯6ÇÔpH½_©*ð¯Ö.Õ”5¶†m.Ú<¶.>åØþ4v¨6O#¶?#ö0 ÅQéÉ@NúŠÓPNCþœ¢¼O]ÏŸ—%°‘æÁz¾¢)ÜÙ¾ 繿ÎÝÞ=î™ õ‚øÐRB{Èä¾ãÕ BC¾o×…·¡&Twßoª 5žFMÕÜ+GþV€:P @!þ\å†Úòç¸$€î`©/Üçîò& ‡ 4¾§‰ð5M‡46ÑBî”–ó~{ ¡]Üÿ†štJòg>7ßÓ2’…dOI$¥ø.’¸ˆ§^ ¸O#ŽJò4þígÅ#_áûØ©¶b¨T UããÁVr?¿3ìJGïP!Za7Ùv‘•üù®ð¯:äT®æ©v‰]k7Ø}ös{Á³ìe›ˆîÚ,díôU¢ Ô˜rR'*Hý¨$ §òô.Uá{ ޳פ¶&·ݱÑû?ÏÆ×]i r¨9ô°Ól8z>^.¦sÌpÑÓÎtQ•ù$ª<Ê.Zr´xÍÿ‰ÿ·ßÒø_«:ØN¡N©(”ÜÏŽ ¼9 åÌmÈmCó«ËýìÂÈMMÚš;Q!?û| ?}+kªŠ&Žªa@Õ7è„©×_ØüùͧGæùqi‚ù˜cô0Ç¡ƒùÚå~\ #/7'a­Ùrd—Þ5×`2ßEß3ç`¡9í„i4×?Ô‚~æ¨Ó#óü¸ô¡Y ëÍF˜iö8’ûq)Œ¼Ï|ߘO¢BŽìÒ:s 6šÃ°½ßm¾t ´Šë_b¶Â\³Ãé‘y~\úÖL€£f!l1ëœÉý¸FþÉ|¿š%Q!GvéˆÙ ß›mp†½¿d68a:Àõa–óÊé‘y~\ºkúq¼ §Í§Cr?.…‘ãáNÌóãÒÛX–£>äÁ¶N‡ä~\ #7ÃÐE…Ù¥rØ*aO¨É®4ÀNŽA˜ÞĆP›@láôÈìÊ`¬ç„©5–ƒ&Xêb§Gæùqif€‰˜za §Cr?.…‘W`iX‡¯E…Ù¥ X ¦bE˜Í®,·ƒ0Áü0 _‡þXØé‘y~\Úƒ–ö`RX‰/1c2—ûq)Œ|_†‹˜"*äÈ.íâÕÜ‹¹à fƒï0Æ1ÓvLc*^“´NÏ®hÎÞˆ.]ÁÛt À„N‡ä~\ #?ÂÄ@HQ!Gvé"¦‡15ÜfWîaa:ÇõŸ@G0ˆ™çÇ¥€ý”½E·ð‘Ó!¹—ÂÈéìcÊb‰ 9²K`ãA€ÄÖRJr Ââú຃÷™çÇ¥¬veµ§(¡ýÑéÜKaä’ö:•·g¢BŽìRŒ}@9ì]ÊÇÞ¶7ƒ0eâúÓØó”Ì^rzdž—ÙUÔÐ~J¥í~fÜA’ûq)ŒÜÓ¤ö³¨#»Ô€ÝhjSû-u¶‡ƒ0Õæú«ØÝTÎîuzDsöFtiˆACìûÔÊ~âtHîÇ¥0òL»…ÚÕQ!GviŸ•ïØ=4–½Ÿl·9aêÇõw·k©ƒýÈéÍÙÑ¥%v-¶ÓhŒ]âtHîÇ¥0òV»ŒvÛ™Q!Gvi¡ÝHËí:ZÃÞo´+ƒ0Íåú§ÛÙ4ÁÎwzdž—p/ßì…ßBßÁÐ>—ûq)Œü²99ÍWQ!Gv)®¹ ‰ÍyHi~€ôæ¤c¦€Ù¡Ð~xúÆé‘y~\Êýtnó$7»œÉý¸F.kö@³)*äÈ.å2G!Ÿ9o°+%ÍŽA˜²rý/™Íð¢ùÔé‘y~\ªÎ½t53 š5N‡ä~\ #·3ë ›Yrd—ªšPËl†ì} ó¡c¦ \ÿ›f)5ï;=2ÏK½LèiÆB}3ËéÜKaäñfL7ã£BŽìRw³ úše0„½eæ9aêÌõ·1“ ©™æôÈ´ƒl|îyÒ8’ûq)Œ<ƒw.r–FƒÙ¥¼kæ>Yò Ëà„©×ßÕ&¡v6…Ó#óü¸´È^³‹ì;Êj§Cr?.…‘7Û8îÓ rd—ð®q)²V³÷Ùx$ Â4‡ëŸfŸØñÖ:=2ÏK×0]Åbt+ÒXœ$÷ãRù1Vá=`ɨ#»tÑu¬K¿bMú«9aº€%è–¦o±¬Ó#óü¸TÄþi‹ðz¼d_ä=l’ÜKaäš|•Ïr4È‘]zƒïa%ÜõG®Céƒ0àúss—òŠMîôÈák’0ÓfyKÑd,ãôÈr¹Ÿ#§0›!½YräëÖ­Ð7ðKè üú†ö‚ ímv@³ ’˜-ŽQ˜†Þ‡{¡U ­„u¡¹.÷ôýÙ§È&4‚fbTÈ‘;øÃ¡­ðmèîÄ7ÀùÐ:¸Æ]úíÐ2¸Z …8Fa¾šÀ¯O†¡iðMhì ͇]âp—ž;öä¼6i¹³aî´‡±›Ãœ™çÇ¥\¼ïÎiZ@RÓÝéÜKaä·¸S¬dZG…٥ܥ¿Ê{Aö¾8wV L1\îÂRq7&zdž—ªñ¾»ª©Lc§Cr?.…‘Ûr§ØÕT 9²K•M¨É{ö¾9wV Losý¥¹ +Âݘè‘y~\êÁûîî¦0Ô3o;’ûq)Œ<Ž;Å©¦XTÈ‘]êf@oîØ±÷#¸³aêÈõ·â.¬1wc¢Gæùqiï»§›W`€)àtHîÇ¥0òS6™ìQ!Gviš) ³¸c_ÈÞ¯`w„A˜&šl0𻰡܉™çÇ¥-i³I óÍKN‡ä~\ #c^†&ETÈ‘]úØäƒO¹cßî|mbƒ0}d’Ãj“ –š´NÌóãÒis›NC»L§Cr?.…‘5‰á¡¨#»tÒ¤‡³Ü±_fWn˜$ ÂtÌX:hì5q@ôÈ·Σ8›†²C£q M ìØZ€#Øw£0Çn¼¦=höáót uåñv<§Ï½}¼ý¾“nXŽºa}*Ë:‹c+êÅ¿šŠìby vpFƒÙÅ&8œš³#mpuÂ~Ô{S®(;7;:Faî„ ø³Ø˜ç6£¬­¶¥*üúÛT .‡ŠÃõP¸*¿‡ ÀƒP>xÊ I¸×NlÞ„ø¦,LyÀP%xª ÷¹ªßBµ¦§ç¡ ŽQª:*äòç;·ÃÿGî0r(ô:k(ÊZJ:]/š×¢b‰ìn›"È„ w÷Ê Š;Ì8&+$4Y ™É©MÈÀÝff˜TÜŸgƒ"&;än4¯É9¹W1¯ÃKæ HÇX‚éÇÝž"ŒR•h–Ü»aäìÜ/æ5™YË+NW“&*–Èî–åÞ¼$;Xؤ‡üÌ–Û$寉¡8÷_UŒ¡fÜaô0·h¸¹L“ÌYšnNs—tƒÞ7?Ó\ó;½ËýX?£¹ êpÏ_‘;\ÁôõÔû+Ç(U‰fÉý¸FžÍ}Á"s…õüätmbþXÂלU¡vða¨ |êá®x_„Úx¼þ|Ìßz^ŸUÜ.aMóÍ÷´Ð|GKÍQZɽÎ:s€u}Å]á^ÚÁ»ùf7àþç{sŒ»ÈãtÀœ¢/ÍîÏÓ§ÜAnf?ÓÓïì1ë£T%ÎJîÇÝ0òæKÖp¾5Gœ®ó拨X"»{Á¢ØÁï¸:Äl_™í´ß|Ê]ð:f>¦Sf3®§Ëf ýhVqw¹’Ðl¥÷̺gvѯæsºÁU^5_ÓE®T0ý¸{ÃÌtŒR•h–Ü»aäÛf-kØH™ÍNWÞ÷FÃÙݸ¸‰˜uô³ýf–Òïf wœ ¹óœGdf3ãLJÈ}Jî$’ñî:'.¢ìÜYÄpÿ•‘;4Ü%ǵ”˜»ŠøÜƒ ¦w“óÞJ¥*Ñ,¹wÃÈ©q:k˜C¯à§K:½hX,XéÿblÇÓFÛ‡ŠP 5 ¢$yl‘‡Ýiy§íGÛù€íL‡mW’Üò-Û„®Û†ôÀÖ G¶6IîùEz“RP)ö¢e£Â$ùÿ†¬AþüQ÷Ïnð -Î61¥,Ï*äd5ÿ‰PNG  IHDR œ€'ÓgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<PLTEôôô®®®f†¹yyyÕæø¢ÆìåãÞ]}²q‘ÂÆÆÆþÓ]u–ÆŽ±Û%%%yšÉóòñŸ‡cÝÚÓò©:€€€&B‚ÛÛÛ(D„èèè¶ÔóYy®ˆªÖ;}žÍ $jºººáÞØ¬U ßßßm¿îŒ.(ŽÈiмÙÕÎ-qûûú1M‹4PŽ’´ÞNl¤”””Š¬Ø†¨Õ¡¡¡Fj8U’ëq’!<}ªö²W¥Èïkkk.J‰Jh¡ 9{¢Ð_~³°“¶à‚¤Ñ~ Î=Z•EFFœA^™ÀèEcéòü›¾æ­Ïñ™¼å²ÝŒ®ÙÉ+„¦Ò0tRq¨Gež†††ÿÿÿUt«zœÊnŽÀÖÒËß²Œ`€´öööc‚¶ÕÕÕhˆº–pH6xÑm*3vTr©B`š^^^Kj¢Pn¦ ­íy#ÊðŽŽŽ6S (m?OmÀÚõQQQ ÄëŸÂêë¦or¶æææs”ÄWv¬È—o´´´ò̧É;›››¡ÏQp§l‚©R9®ƒ=W‡öúþ[z¯é˜C>\—Ÿ #AO'-L¥Ö+G‡ÅßýÔÐÈ*o,5UÊÊÊ¢ýýýùùùìììâââÑÑÑÏÏÏÐÐÐþþþáááÕÑÉ&&·ÙÙÙ¬«HfŸIg –¹â—ºã;X”üüûèæâÚ×Ð×ÓÌõôóíëèžÂé÷öõœ¿ç…§Ôw˜È˜»äùø÷Xw­d„·\{°ñðïïî땸áüüüøøøúùùëéåîîîýýü?]˜#?€ãããþþÿíííoÁš½æb‚µkŒ¾ýþÿ£Çîr“Ã|˘»ãv—ÇMk£ŸÃêCa›cƒ·š½åÁ镸âaµ××ׯ~ÂÓÓÓñöýüýþùûþáíúúüþ¼p¸ß >OABh´ÝþÁ:•yn‚¿âHx­“Š{^¼Œ²ô$SpŒ™’еÎC?D]6 '²˜‹ˆŽžÆæ‘Èæ999]oW`|àYåh Š)~IDATxÚb˜< F*X¸paLÌ:uõµBB llknس[`ý¦í4Wž1þüˆ€b˜1 F@ÀÔ1š‰FËe@¦ŽÑÔ;u “~[ˆã€—&ŠòHñäJò'J)BÊìŒ8 %IˆšÖy2Γ]žX^ÃýñlݬMݳi1îf»»=óF|¿¿»ßCŸ×ð!;þsE=ø†|ÛÔ u웣¦¨_7ÕCÜûf¨aj„Š“¾GÏ q …Â*:¶m¯yv€$I²,Ï‚sT­VÇкǢ]âär¹^$Šâ3hC àÔëõRéÐqœ|>ßBƒÄ;bf¼¢vdšf"‘è *•Êê{¨\.÷ƒe$ÂÏ8Øôth”XDº®)Š¢ªêg6‰Djµ7–e5M …\×M§¯-Ëây¾•0 c]Rë  Æã©T h6ÃáF#™üùýþ(£Ñ?„š:Z[ßË ~M£©’:–:¾Çʵþ}ÛúîM±ðKÁÑÔ1üSZûS¿ÿ,0qD,uÔ5XX4üøüëçkÁ—/GSÇðO(íC‘”vÇLHê xêಈ­hûøâéÓo_¾ §fꈈ )uDDh¡Ôtúhê rê×3d”眷x&B’¨ì@IÚ ‚R³€èU¤áIGŽ“Çhê ]ê hêøó/O¥[%×äÿת*÷—\ɸS¸Ý¡‚‘:"`EöÔ+<@4$u€RJê¦ ´²#½ì€¨©Ã$0Z³Ð$u¬Ïô?OEE±ß¨ªêy#—ž²’:B0ËŽpña®X°”híqX«–:@‰‘: [ꀷ;FSÍS@ÁRG‰J^ês#£6.®69D«Wê¡rê'rRÇhÍBvꨬ´µåãÓ:>’î,=òrsMr?¼L-–CêÑBZ¥ f)¢G I!`^Rê€T-8Z¥ØSžV)–Ô± Q³Œ¶J©:0z´O_=‚‚þ™˜äæ~PœJ¥‘tPÒ+Êc¥„˜…ûûÍØBû¿Ê¦Ž:D@ <<¼ @O¯ ˜:êå9§Í»-vLbÖn†xhê ä9Úâ/@0utD¤w((--ÍÌ´b /hÕ+Óéã0u̘? €F×wŒÎàãžÁ ÑÔ1š:p§€]98ºr÷ÊA€M£©wê ÑÔ1š:p§€M£©wê ÑÔ1š:p§€M£©wê ÑÔ1š:p§€Âš:\ ìJO_¸RîW*©a© €PR‡+LvÅNyHHbWå •#0ƒˆ‘"9u¸b˜Ï×ÑÔ+ujê N®h©Wê (›báJž!£©ƒ’Ô1”:Kêç}¬yÛ)w»bU⊢ŽpÄNKà@¶IÈfº«+ÎhG5‡s‘\‹§Di©c8uŽš{à iœ5 ,Ò©Oê Æ”„€”~]æã+€\ ¸æãÉx|=‚S@á(;\]qf5âRR:Ãj"Rp7]à$¬8é„JÀ ¢Rî"¥½5š:j€Â•:ðÔæÄ–“ñ¥ŽÉ“IHÈeº4îhÇ0¯C&¦ÌV)@áId•(qB ñJ|ê@J æO&6uJ¦£©#ui­Rh›Z¶ã˵®®®øº0pƒpöhQ›”“]±Ô,xzƘ­RÜÍìÑV)ÎÔ@£c¥#w<Œpê Ì>‹+þ1,ü¹‹° „*WJŒ˜L¹+02š:ÐR@–#N4š:FSîÔ@£©c4uàN4š:FSîÔ@àÔ!2 F(€ï…cdDÝ §¹o0u8uŒ> °€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€BIà)) —z×lò8•ã”qÅÁ9€I®DHàBxÃqÅ"çŠÃ¡`qW˜nW8ˆÀ©ƒØ‹p%:RI4‚§A„Vvr,ñ¸b%àÒáŠÓ ¨:x8%HôN‡¸âJp8Å]Ѳ‘+ ±‹;w¸R\`7‚wê B©Ã•²ƒÄäíJ¬bËW" @þÄ•\]±€d0r!LJê FÙA­² €FS©Ý¨ºýÔ€Ï*:(A´;°ÿ$ï#S0_—rülÂy·Y¢þâ”%Kðu7QL®œbÎÐÚÜ ¹mÄÔ‚Œ” påŽâI¥‹s7´uüM;vФrb°Då¬âJ)®$hoºÖc;>-c€aN–òv`•lŸ4±}~ <²é·¾ö( æê‚•¨ùÌ#T†ÉêqŽÕ)¤‰ :œ“TŸ§øÈûv=ï anZm&*Ô‘&“1¾T÷+×ïÝñÀwå‚ ôtªÛ·µ¶Dž}õ4tνÃþ¾”“õjª§b/P'¢z3-î‘d± À«hšée¤­‡"5¥%ûY^âò’1F&fpü&Ë€°²;aðtîU¾í½Š‡@¬>’ðÛã󲨠};¬K×Á=\ÈN“7·VÈ·†¤Çö1)ëWhÚKÐ}„­4®!M…T$‘î}\¨Gâ–¡ãf=´ìšI–™þlÇ)€°¦WDj§FêÀZ³àO¸³‹+j¦G’•˜±…³¼Ê,©èÔQ‰%rQÄ!)v©[‚!œ:2Ô€Î28†aàÝÊ;t•›½Ÿ(%+—‰I¡DGÉ)KW¼ábIZ8D31C#Hb¿\Ú'¶Dˆ,ßE§ƒÿÞc€î;œEGýÓÕüK£éÐc°K§ƒ™—…ƵzÇs¢ã€k»´Ý';°J·¯E^§¦M¨Bš:H ñûìÃ<ˆâyWDG0 RÇ¡Ý ñp—4š:Ftꨖ8İwá@”¦lþèÐÄIJÇ$vÇkâL4:ƒ?¢S‡˜Rõ!†8S@¦ŽÁf Tê¸-vìÃ̸Ü@£©cD§ŽD±Ù³ð¤€M£©wê ÑÔ1š:p§€M£©wê ’Rµu)©ƒ–Gi¢‡˜+±±À"¬†D 'üHJ2h”˜‡JËà×G\ê -;ðæJDz¥fZ®t(e\É);p$È’2øõ•:hЦ¢W´ަt9`)!ƒ%1ž:}mÒ„¯@UèŠåÄž)ÏJÀZ°¢°m}&S¬”@a™:ˆf©{q‚±ÈË–IÔ3/±BjêÀ^)FàZäHFêpÅe'ªéôK(摟:-u¸b?ŠG&G^„ŠçÄQôE£Èy k˜G`T=(¥ÁvÚ©ª®Ø˜I£åŠK=zêpÅÙ\rE¯Y°¬ÞÅš:p¶;dZØR¼]+ƒ+uÙî Rú,h+JÑ¡¢ztŸ‘+úaØð.¢ý޲„åƒÔ §æÏß11Þa¨ÎŒÔgŸïŠvÚá§èþC8"…F^ÖŠmI-ªç]Q›°®èý˜u”Õ»°†#$ÂQÚ‘ð>‹ ¢Ïk»B:,O+Ý0u20"@|Ÿ €°Ô,4Î nltž…< ƒwxƒÔñ€MÃlN†”ÄA(uæxÖ‰1ÚOAŒèŨԜ£•!!qJ4:ƒ?ÜR¼A…Ô@£©cØ¥*®ï ÑÔ1š:p§€M£©wê ÑÔ1š:p§€M£©wê ú§W«ˆˆíÛ.†1¬Èr)#:à·9æøå±ihê˜ÉÐ;[,qÎܹsMç@— ³@á<¯}]¨+²‚Ä᤮®ÈS»X®¤'x)æ•ØADß>Í™'$ÀíFC=P»£Ôý7d†Ö|'ê%ð¸=_7èŠ>‹¾²—æææ¸É`­Ìá, ÁØ™¨ÆÀ™ûö÷’¨>fj:Ût6˜ššBi0 ¦¡B®³ÂºŒ!TÂ!§à¢pŒÀù„ïDÊÔuŸX F /ÐĹÓÕÛ™—Èk$0ŒA[¦ Ä'"S‡Ô;kV/ƒ@/ƒE¡R`Y×YàŠ \áX‰ gºÂD¡à³gêˆÀ³–×ÃØõ8Žm kDÖOQ§é ©#’: }XÍbAp…4æšY¤Í˺Xäš=²ÍINh¢`jþ>óýñ½ @&P©^ à ® àŠ €ì~$ „ŒBÓNàÜ0€Ây"%–›èa §Ô…œø#Åqº+VÖ,Ð-h§$zꨌÀ8£ßóŬ+\‘Óé©# q2±§Žˆùæû4Íg˜@¥Ì!4 Ït‰®pÚUÆJ¸¢¨Q•HÚ œ9@øÎ+%;uà\§‰5¿R–:À+±¤¤k¾#"Я“ÀrW9ÊmäØîˆX ÁKL(Ì…@œL c`ÔüùKg˜@¥–BhžQ9*át%ªL%”¨DQ‡¦hóJïy¥ØŽuEO®®ØR‡«+®Õ˜èÇ‘b¿ëÛ>WôÔ!mw@RÇoŒÔ½@ÆB¹NõVùÊ,©§²‘ÀPS.ÅH1|Ll©céÒ¥pÞRTÑãÒÔ4Œ”z+#"ÐS%†wѲ!@¸Î+E[Œ‰¾b<¹Ÿ}{œ+öÕ˜˜Ç‘bôYP5a.Mx ž-6'¶?Â’8øø ×Wb/ À ¥ ðôªD ì%K–@qƒI0 &#" æ¸1P6 b.” U1;*¾Ž‘‹´ÊÊJd"»ÎDõ'$tˆOdmâÈ3¼‰Ô»[›I94+cK7›ˆÔÔA¿ÄAè oúãÈLDZê¡câ t†7A@Õ‹åA×Ô;v ½@‘\³ š3¼Gí@ÁRÇüÁ—:ŒãڀĩƒÀÀ( = Aœ:̎ڀĩƒÀÚƒQ@{@°Ô1cð¥ë–Fí@a¤‚ƒ28¶_QePD†˜±3öAèj%¨@ª|iiiú¦ 1 ,ê R„‚­¯”H-DR¬:éx4+@¡§2F9ÐOȤhTD†pꘙ˜ži‰ˆ¨ÏÓ"@&gF`Š¡„U‹f *'Z1:É7ˆt@h©C†¸R'dRTŒÈµšþ@x.â6˜Çˆ,e…D¢ F` â”À ¬HSަˆ„%ôV˜:éxt/@Qž:°œIŸÔÁ¢Å0SÖÓKq ¯·¢ÎKe&Q=V'2GPítVb@V® `†}DØy/JÞµ©MÓî°Ë%4•¶ÐSª:FwŸIóK¼†qÝ!s %¬‰Ò}Æ=6Û#Œ{Ü|¨ãÜêX?£pÀ œ¡0‚£Ñô”êƒÈ@á¬>¡†ÔÌŒ.L¯¨MËѵv´Cÿ¸n„™:°œZ…r<¦ Þ3'¡Y…„ÑÔD:òLåt,’RÇl0MVr–˜âP1=8ÖÓÓ‹@DÈé!‰è!ë@Öˆª.“ÓCbF Ø®‡f ª™z®KBYz¨’hv£[FE@R‡ŒŒ Æáwˆctepœ‰F£%5´HÐÎ<#2uìƒ,ñˆ¨ó¦aÈBq„!‚¢ áLT98 I „`.-†H:rh–£*BS…i4ªaØ$ŽBq;5@aI“d #1J…I'dÒ1uìÑ`Þ!­Ï‚ÔAê!—ƒdÐZ§xRtòeÍ3 ôÌÁQ@1 ¤³ŽAçƒÎD€òóJG… €F@¦ŽQ€Ðhê¸@¦ŽQ€Ðhê¸@¦ŽQ€Ðhê¸@¡ßG Äh%VÝ(² €0î…C¾‹‹pò Àa kê 2ÞGSÇp„;u \öùŽ?¸b˜¢Ñ3¼@á©Y Ñtñ#êm®ˆ{!G“Çð„™:à­RØ=öh—AŒ‚aÙ”JFSÇÈ„§UŠш†ÇhêI €ˆI®¤V/£`˜€""uŒÖ,#‘íôš%~Ó=JŸe4u /@¸GÒ#ê°äáêêŠÒ‘EH#Ô¯'@£³p£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔ1 p€M£7 ÑÔAo0it·ÐhêM€~Ì#@¦ŽÑÔèGÄÐhêM€~¼4@¦:ƒùƒ9u M@£©c4u úµ4š:FS _‰@£©c4u úuZ4š:è f æÔ~@¦ŽÑÔû’W€M£©wê Ì]Ö02I “X€¬ˆ³PqË"l7`À•he®¸ôº’o2¸d@€xmxD±¤€B?¡k Žy¡Fðâ3¯ ®$DМþpu¥N.‡¦…_Q¢ØR@ @êˆp%3wºR/q¸’[,PTʸ’_v`Ïÿ2„J Ë€".uÀbu`Sö{§hI ƒ3Â)L踂B¶ëtöŸÄO(ôx‰’úêŠ,èhжÎÒÈ( "(Л“3(?ºpv©ÃSlˆÆ´”ΕÐÿ…È`qO£‹×4þh˜F$Š3.b/Ÿ«ÁnaŽQcÿ3ïaìnV訫T‰›ž'^—å2Ñq ã ŽAÐ"®ãî?I×Ud¯:­DûÙÏ+µO$OZS¨³ ¡Ã˜(µ‘’§ÁB¥Àæ>.ÄMERˆÚ™Ç»ô#ó–xðÞ¢ˆ¯Ðmt`Qèa‰î&) ΀«G'YÞ¶)òk6ÎŽ!£epÂÀEX§;°ÿ$~L ¥^>„&¦Ge™‰%A™\cGRPyˆ?rz:LhIšÒ®eðü+z"êÈ÷8›÷gaÿÉNÿ K‡•Š\D_WbAÇ@¤§äò^s`É(5 †ùÈU 5SªSð§„Z©£RsEªþ°¥„‘®Hú\QŠ)RS¼]-uÀJ"RRû„èÔ@Ħx™%u¸FDàO¨a’¨œ:\ñIàu+±©§¨¦S-u`˜©Q2¸JâR@:Ð O´¸pÅZ—G` ,Ô¦)–* [†»ÝhLbs Ö¸ƒ0]ÑÔº¢ù-yº¢ÙÃX̆¢= ±kêÀÛîÀlp —'ð–-¶QˆjŠ-øS@ÂÎÝ †‹°Žw`ÿI^Á'gzE„BQ _Šðê•Ê'Njê/¹f »ËœdÓ¼˜ˆªø¸DRœà’¶ TêÎ,1™¥.ÙmEÄÛ+À^HL9™8)mXÑ#Ë‚YÃc´D—m»@p>CÁ±Œüò_ŸÂ;ÏâJÑxò( õ<‹ Cͳ¾Ô1š8û,œ uFê ’çhG2Ls´2TM© €Fgð‡ö ¾ þ9Z S@¦ŽÑõ¸S@¦ŽÑÔ;uÐhêM¸S@¦ŽÑÔ;uÐhêM¸S@a¤\K|ˆºÜ›ZÊW‚b56•‚ñWÒ¼ö9æèò8U›?y‚³÷ÚÁÞO%®"Cœš>© €ÐS‡+Ž bbØ[„Q¾”zëɳ)7')uàTm,;ž¥¸¦Bˆë½ÊÈ—‚ÐS@a™…£¼ìÀÌØ®Ô/;(¾u%΋ÍqXÅp§Ž™ ³f‹%Ι‹ LÁ¤+’ˆ+E‚0p%B¦ÄôÔ@4N”ÿÃ6uœ8&vûÞd` &]‘D\Ñø(„+0%î¡ï… ÔÔºžÓ}­$Úl$ê"NÔe—®˜©y*Ò¼(¶Õ¡¨2HKu"°¬ñtŶ(iš·“Ñ @_1ꊼ<ß ê  \DÊ0GRW\É@„€áPµ’˜i¢©i"˜‚(S0™èšˆ6Ð` ! ®98…%B¥ òý`Q;¦º21‘/‘Ä,Í´²AßG €n+¸a„•ònž§®Ð!ò´º‚™ã¦©x0Eÿ«Èh‚€ãìÃ_nISrF›x,ê êI†lqN²€NwVbÿgåCä‡5»æ|tqY•ý½xé£7¬9—aÝ RÕ1¤¦'Ìïçþy|ËsŽÞD“q°HG})-Z÷È´oTy5nØÖ¸¯BÌððqî6Â0E¢†šE(©Y!«œå 6‰‚¹0Á>‘¬³GIì§”y£CÛj+_B®Ž@Xä êèp¾¥ô0óBœ‰Æ]‘þè€xÚ’ Ø]ý¢#Y:î–§Jßdd—µÚº©')v¾}öd€: "–f&4TÄ/!¼Â¹š<­HCŽ"õÿï8¾ÔQY–/aɤ^ÊTbÑD(u@µ“›:´WVâLðäŒâd4 P ¨Dj xB/à%&”@ŠX²¦ +=Æx†Ý‡¦Ïš5k:Íš£*g!@%œ®D•©„•(ê*Q™p•©Jt lgÍâR¿gÍ*R"'ÐÏþ@Æä°%Þ}Iÿáij ÿñèOÔy®Û€¬-P(|IkJ:‚¬BïÞ@°ÒîÖ©Õl79Áío΄ ƒOcÁæaȉð~áés«LÙaœÊÔ#Ÿ×sorˆÔª$?AØ  ¿‚p>x©e€.š Î…ÞRû2 ÿ†}Ðqm7‚0pÝÃ!n ò¾Üĸ—?"PúŠÈÝ(C‰@-ɱ;–M#cJ×är—‹Šþ99†ý÷½0CIƒ ìuÈ/ùbÇi5Dì½9 .Ñ+#sí˜+ #R ^{S„À¨Fl":§â£Ï(¶Öˆçh†¯+˜)ìÍ'ÇÄÞÕÑ;eÊ¿ô¿º`†ŒnAzc2Ý‚ Ï3Q âÿb!4Ðú¸¹G ß3smX51ü]![ŒÑæˆf®OBÈgʉNËaˆdF SŒUE uP$ˆ ¸üÀÿâ€Z2:(„aà3ûÝ]Oáam«â· DôLð3™ÅÆ"߃q,°(½C#g@:ûñi\lÒˆ]–¥KÙ^ íÿJÉÓP/.5xâw4˜!bþ˜Žw£8ZéCߤ:À—B1sõÉÈü*äöç´”°=\“Þ[6›b@EÍÑñ!ÐÌÝ Æ_ê"ÐUн ‡ŸâÇs²}¥ÿ=Kf©í€„Ý]ºÿ$æP%àB-´?£Yfüøïˆ?Ã,Ϊ8ÙhOQÞq„jï_NF{JH±Å®yó¢y¶µ€›’AwL¸á©2v0´u¥xûw,İ:bõê‘8…p»À üêOŒ¬@ †Ã‡ÄÔ!€]@¿z‘HÄ0#bÆŒ˜8âãã±a -=,@1Ì@ÝÂ0 FÐhê¸@¦ŽQ€™ß¶jëÛIEND®B`‚èò é(€àà€ òú/È 0ÒÕ0·DTimes New Romanœ©ÃhÖPÖvÇ 0hÖ(Ý 0·DComic Sans MSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„B ·DCourier NewSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„10·DArialr NewSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„"¤ €`ÿÿÿÿ¥ .©  @£nÿý?" dd@ÿÿïÿÿÿÿÿÿ  @@``€€ „ð|ð`, Û ?<> 5  !Oð°2ð$5X¾t˜‹gFŽêûÅ»Nkˆÿj Þbð$"ë&ÓBwêÐõ<@å§ _ÿæjÞ2ð$ßèÓ!WY—“r†Z¦!Rÿ&9PÞbð$Î61¥,Ï*äd5ÿ-v?Þc ð$ƒ¿Àÿ@ñÌìÿfÌÿ™™ÿ@ñÿÿÿÿ÷ðó€Ð7N×ÑÊš;2NÍÉÊš;úgþý4QdQdvÇ 0\Ö8þÿÿ¸ÿÿÿpûppû@ <ý4!d!d`ó 0ÚˆªÃ<ý4dddd`ó 0ÚˆªÃÿ ?Ù Ú%ð­óŸª Ÿª ó Ÿ¨How address harvesting works¡ ª Ÿª óŸ¨'Challenge-Response based authentication¡(( ª' Ÿª ó Ÿ¨&How viruses/spam should not be treated¡'' ª& Ÿª ó Ÿ¨)Challenge-Response system causing Joe-Job¡** ª) Ÿª óŸ¨"How SPF helps to prevent forgeries¡## ª" Ÿª óŸ¨"How MTA level UBE prevention works¡## ª" Ÿª óŸ¨*Procmail with battery of statistical tools¡++ ª* Ÿª óŸ¨Tools¡ ª Ÿª êøêï `ð ÿÿÿÿÿÿÿ™ÿÿÿ–––`ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²`ð ÿÿÿ333ÝÝÝ€€€MMMêêê`ð ÿÿÌff3€€3™3€3ÌÿÌf`ð ÿÿÿ€€€ÿÌfÿÌÌÀÀÀ`ð ÿÿÿ€€€ÀÀÀfÿÿ™`ð ÿÿÿ€€€3™ÿ™ÿÌÌ̲²²£>ÿý?" dd@ÿÿïÿÿÿÿÿÿ,£|ÿý?" ddØ@ÿÿïÿÿÿÿÿÿ € Ô €" Ð@€ ð`€»€ £nÿý?" dd@ÿÿïÿÿÿÿÿÿ   @@``€€P£R    @ ` €`£ p£>€£> $ððð´ð( ð ððÒ ð “ ð6€ôßǃ¿Àÿ ð€°ÐPðà à ðTŸ¨ Click to edit Master title style¢!ª !ð ð ƒ ð0€¤âÿÀÿ ðà°Ððà à 𞟨RClick to edit Master text styles Second level Third level Fourth level Fifth level¢!    ª SðÐ ð ƒ ð0€€çÿÀÿ ð`°`€ðà à ðXŸ *¡øªðÒ ð ƒ ð0€ôìÿÀÿ ð`°Ð€ðà  Ã ðZŸ *¡úªðÒ ð ƒ ð0€ÈñÿÀÿ ð` Ѐðà à ðZŸ *¡ØªðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²² ºDefault Designîäï€ ”ðŒ0ðð$ð( ð ððr ð S ð€à_ ¿ÿð °Ðpðà   ð žðr ð S ð€à] ¿ÿð ` à ðà   ð žðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²î¾ ï € n ðf  ð ðæ ð( ð ð ðÝ2 ð ó ðZ€¤ý²…‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ðpà€ P ðSŸ¨ ¡ª ðx ð c ð$€d·¿ÿˆðÀ@°ðà  · ð žðp ð à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿð€  p ðýò ð € Ó ðN€Ø·‰¿GeèÿÿHÀ°ÿÿƒ¿ÀÎ ÿ ðp °°  ðŸ¨/A program collecting items from various sources¡00ª/ ð• ð ã ðT€H·…‡€ƒðF‹¦ÿŒdœ @¿Àÿðà PÀ °  🨙Mail addresses are collected and later used as a false SMTP MAIL FROM: identification to send Unsolicited Bulk Email (forged addresses in mail messages)¡>š< /$ª™ ðˆÒ ð  ð`¡Ûí…‡GV,H€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ðP ðõs ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðð °€ 1ðÃ2 ð “ ð6€ ·…‡ÌÿÌ¿Àÿð€Ð  ð]Ÿ¨ Mailing lists¡ª  ðX’ ð ƒ ð0…‡ƒ¿Àÿðð 0 Ð ðÔ2 ð ³ ðB€Ì·…‡ƒ¿ÀÎÿð° ðp  ðbŸ¨Usenet newsgroups¡ª ðÒ² ð C 𪀀AÁ’E:\home\jaalto\vc\project\sforge\pm-lib\doc\html\pic\www-page-email2.pngð€·¡ ðÐ ð £ ð<€·…‡ƒ¿ÀÿðÀ   ðdŸ¨addr@example.com . . .¡ ª ðË¢ ð £ ð<€”·…‡¿ƒ¿Àÿð@°  ð_Ÿ¨Saved addresses¡ª ðÅ¢ ð £ ð<€ ·…‡¿ƒ¿Àÿð` p   ðYŸ¨ WWW pages¡ ª  ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ðð ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²î¡ï € QðIð4ðÉð( ð ððø² ð S ðЀ€AÁ²HáC:\Documents and Settings\Administrator\Application Data\Microsoft\Media Catalog\key.gifð¯p0 iðx ð c ð$€@²²¿ÿˆðÀ@°ðà  ² ð žð¼¢ ð ƒ ð0€t³²¿ƒ¿À™fÿÿð°0 À p ð\Ÿ¨Send challenge¡ª ðᢠð s ð*€Ô·²¿¿À™fÿÿð ° t ð‡Ÿ¨Bar sends his first mail to Foo¡6 ª  ðXB ð À ƒ ð0D¿ÀË>Ñÿð p ðp ð à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿðð°  ð¢ ð ƒ ð0€˜½²¿ƒ¿Àÿð0€°ð 𠟨 ¡ ª&  òóÿ!0ßð® ð ³ ðB€²…‡‚€ƒ¿ÀÿðPPÅà  ð<Ÿ¡ª ð¢ ð ƒ ð0€Å²¿ƒ¿Àÿð0Pð 𢟨¡ª&   òóÿ!0ß ð® ð  ³ ðB€°É²…‡‚€ƒ¿Àÿð8À5à  ð<Ÿ¡ª ðÐ ð! 3 ð¨B CÂDEÁFÁƒ¿ÀÁÄË8cÎÑ×ÿðÿ¢i‰ ¬@­ ­ ­€ððp²ð ¢ ð £ ð<€̲…‡¿ƒ¿ÀÿðàÀ ´ 𠟨Add foo to whitelist¡R ª ðXB ð#€ ƒ ð0D¿ÀË>Ñÿð p ð¢ ð$ ƒ ð0€Ó²¿ƒ¿À™fÿÿðP ° `  ðbŸ¨Respond to challenge¡ª ðp ð' à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿð  ` ð ð¢ ð% £ ð<€üÖ²…‡¿ƒ¿Àÿð `Ìþ  𱟨%Accept challenge Add bar to whitelist¡R& ª% ð^B ð(€ “ ð6D¿ÀË>ÐÑÿð€ p€ ð' ð ã ðT€À¨²…‡€ƒðF‹¦ÿŒdœ @¿Àÿð p€  𣟨CBar and Foo exchange messages (Passwords/Catchpas no longer needed)¡&D& ªC ðÁ¢ ð) £ ð<€@á²…‡¿ƒ¿Àÿð€à ½ g ðUŸ¨A¡ÿþª ðÌ ð- £ ð<€øæ²…‡ƒ¿Àÿð `€(  ð`Ÿ¨bar@from.com . . .¡ ª ðÊ ð. £ ð<€8ë²…‡ƒ¿Àÿð ðP À ð^Ÿ¨foo@to.com . . .¡ ª ðµ¢ ð/ ƒ ð0€Ì岿ƒ¿ÀÿðÐ €O·  ðUŸ¨C¡ÿþª ðÁ¢ ð0 £ ð<€hñ²…‡¿ƒ¿ÀÿðP Ï 7 ðUŸ¨B¡ÿþª ð5ò ð2€ Ó ðN€Hõ²‰¿G \H½íÿÿƒ¿ÀÎ ÿ ð` ÀðÀ  𷟨AThere are serious problems in the C-R system at points A, B and C¡<B7ªA ðF² ð3 C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðP`‘ðF² ð4 C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfð °€aðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ðð2ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²îlï € ð ð (ð„ð( ð ð(ðx ð( c ð$€üB ¿ÿˆðÀ@°ðà    ð žð¢ ð( s ð*€DD ¿¿À™fÿÿð`@0Π𸟨4mail sent in the name of Bar (forged address) to Foo¡R5  ª5 ðXB ð(À ƒ ð0D¿ÀË>Ñÿð @Ð ð¢ ð( ƒ ð0€L ¿ƒ¿Àÿð€°À 𠟨 ¡ ª&  òóÿ!0ßð® ð ( ³ ðB€ Q …‡‚€ƒ¿ÀÿðPPÅà  ð<Ÿ¡ª ð¢ ð ( ƒ ð0€¨T ¿ƒ¿Àÿð@Ð † 𻟨MAIL FROM: ¡ª4     òóÿ!0ß ð® ð ( ³ ðB€ÈX …‡‚€ƒ¿Àÿð8À5à  ð<Ÿ¡ª ðp ð( à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿð 0° ð¢ ð( £ ð<€P[ …‡¿ƒ¿ÀÿðÆ 3œ  𔟠.1) Message is rejected and returned in full 2) Or notification is sent:  Your message contained virus or spam and it was not delivered ¡˜˜ª— ¦ø @`€ ðEò ð(€ Ó ðN€f ‰¿GîZHÒƒ¿ÀÎ ÿ ð@`P   ðÇŸ¨]But this person never sent that message. His mailbox is being filled with false notifications¡0^-ª] ðF² ð( C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfðÀð’€ðF² ð( C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfðÀ°R€ð¢ ð( ³ ðB€èk ¿GËQHÈÿÿƒ¿Àÿ ð€p   𖟨>Scanner found that ncoming message is spam or carrying a worm ¡&?> fÌÿþª? ðâb ð( “ ð6€p …‡Ììÿ¿ÀÌÿÿðp 0à  ð|Ÿ ,bar@from.com s mailbox¡ª ðXB ð (À ƒ ð0D¿ÀË>Ðÿð@@Ð@ðH ð( ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?/ð ð(ð(ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²îÄï € tðl€ð$ðÜð( ð ð$ðø² ð$ S ðЀ€AÁ²HáC:\Documents and Settings\Administrator\Application Data\Microsoft\Media Catalog\key.gifð0°`ÒðÝ2 ð$ ó ðZ€c²…‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ðpà€ P ðSŸ¨ ¡ª ðd2 ð$ £ ð<…‡ƒ¿ÀËŸoÎÿð`Ð P ðR2 ð$ s ð*…‡¿Àÿð0Ðà ðx ð$ c ð$€Tf²¿ÿˆðÀ@°ðà  ² ð žð ¢ ð$ ƒ ð0€4g²¿ƒ¿À™fÿÿð€ ÀР  𪟨0http://cr.yp.to/smtp/mail.html See also RFC 2821¡11 ªB   ðÓ¢ ð$ s ð*€ll²¿¿À™fÿÿð€°° î ðyŸ¨#A challenge is sent to: foo@to.com¡$$ ª$ ðÈ¢ ð $ s ð*€r²¿¿Àÿð0 °   ðnŸ¨SMTP connection¡"ª ðXB ð $€ ƒ ð0D¿ÀËŸoÑÿðÐ` à ð ðF² ð $ C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð€ " ÐðF² ð $ C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð@âÐðXB ð $@ ƒ ð0D¿ÀËŸoÑÿðLàp|ðÆ¢ ð$ ³ ðB€4v²¿GÇHUiƒ¿Àÿ ðp` à ðTŸ „Bar s C-R system falsely concludes that foo@to.com is the sender¡JC% ª2*   òóÿ!0ß*1ðF² ð$ C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð ÐrÀðF² ð$ C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð` 2 ðF² ð$ C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfðÀ ð’ €ð|Ò ð$ ã ðTê…‡€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ðp`À ðp ð$ à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿð€ ðÐð 𤢠ð$ £ ð<€˜²…‡¿ƒ¿Àÿð° ð  ð8Ÿ Šfoo@to.com  Joe-Job Multitude of challenges sent to wrong address¡6F .ª$ > òóÿ!0ßð¢ ð$ ƒ ð0€È…²¿ƒ¿Àÿðpð 0 𮟨 ¡ fÌÿþª4   òóÿ!0ßðíò ð$€ Ó ðN€‰²‰¿GôÿÿHOøÿÿƒ¿ÀÎ ÿ ð` ð ðoŸ¨More users running C-R systems¡  ª ðÈ ð$ ³ ðB€‹²…‡‚€ƒ¿Àÿðð`0à ðVŸ¨TO.COM¡ª ðÊ ð$ ³ ðB€4‘²…‡‚€ƒ¿Àÿððà@ à ðXŸ¨FROM.COM¡  ª ðF ð$ ã ðT€4•²…‡€ƒðF‹¦ÿŒdœ @¿Àÿð °@  ðŸ bSpammer s messages which all use forged addresses¡&2ª1 ð3 ð$ ³ ðB€è¤²…‡ÌÿÌ¿À™fÿÿ?¿ð€ `€  ðÁŸ¨220 mailserver.from.com ESMTP MAIL FROM: 250 ok RCPT TO: 250 ok DATA 354 ok Buy our product, and visit URL . . .¡´         ª*)  _ òóÿ!0ß)1ðˆÒ ð$  ð`¡Ûí…‡GV,H€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ðä ·  ‡ ð¿¢ ð$ £ ð<€|§²…‡¿ƒ¿Àÿð!d ðSŸ¨(2)¡ª ð¿¢ ð$ £ ð<€x«²…‡¿ƒ¿Àÿð@ ¡   ðSŸ¨(1)¡ª ð¬ ð$ Ó ð„B° C8DEÁFÁƒ¿ÀÑÿðÿpÔ8` P° hH 4à@­ ­ ¬€ð0 ÀhðH ð$ ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?/ð ð$ð$ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²î¤ï € TðLpð> 0ñ ð¨ð( ð ð ðæ2 ð' ó ðZ€ô´ …‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ð9d  ð\Ÿ¨ IP 111.2.3.4¡  ª  ðr ð S ð€Ì· ¿ÿðÀ@°ðà    ð žðt ð ã ðT€È¹ …‡€ƒð-‹¦ÿŒdœ @¿Àÿðpà P  ð🠀SPF result:  No, mail did not come through our Mail Exchanger ¡6A 2ª@ ðC¢ ð s ð*€L ¿¿À™fÿÿð€ € Æ ð韨!SPF check: consult DNS TXT record¡J"  fÌÿþª*   òóÿ!0ßðXB ð À ƒ ð0D¿ÀËŸoÑÿðÙ ¤Ä™ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfðàÀ b ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð ¦Éð%¢ ð ³ ðB€¨ ²¿G] H¿Àÿ ð0°à à 𳟨AIs this message coming from IP 111.2.3.4 authorized to send mail?¡@B   fÌÿþªB ðp ð" à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿ÀÿðÉ $9ð4ò ð( € Ó ðN€è&²‰¿GíÒÿÿH0ƒ¿ÀÎ ÿ ð Ô $) ð¶Ÿ fHost located at some ISP s address space 111.2.*.* ¡44ª3 ðÈ ð+ ³ ðB€Ü*²…‡‚€ƒ¿Àÿðé$ôÙ ðVŸ¨TO.COM¡ª ðÊ ð, ³ ðB€ô.²…‡‚€ƒ¿Àÿððð P à ðXŸ¨FROM.COM¡  ª ðß ð0 ³ ðB€¼2²…‡ÌÿÌ¿À™fÿÿ?¿ðÉ$´y  ðmŸ¨%220 mailserver.to.com ESMTP ... 550 ¡&& ª& ðÊ ð/ # ð¢BàCÈDEÁFÁƒ¿ÀÁÄË8cÎÑ×ÿðÿà0|@ÈpÀ ¸P @­ ­ ¬€ð°Àw xð¿¢ ð1 £ ð<€Ü5²…‡¿ƒ¿Àÿð© „mV  ðSŸ¨(1)¡ ª ð¿¢ ð3 £ ð<€4:²…‡¿ƒ¿ÀÿðàÀ© ðSŸ¨(3)¡ ª ð°¢ ð5 s ð*€H=²¿¿À™fÿÿð™ ´„Ì  ðVŸ ÔSMTP 5xx reject: message is returned to sender due to SPF result:  you did not use from.com to send mail. ¡Pk &   ªk ð¿¢ ð4 £ ð<€¼D²…‡¿ƒ¿Àÿð) ôÝÖ  ðSŸ¨(4)¡ ª ðF² ð. C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðð Р 1ð‚Ò ð! ó ðZ”…‡€Ìÿ̃ðt‹yÿŒdœ @¿Àÿ?¿ð sO # ðe¢ ð £ ð<€”M²…‡¿ƒ¿ÀÿðÉ Tc/ ðùŸ¨=Spammer sends message pretending to come from foo@from.com¡6>1 fÌÿþª21    òó!0ß1:ðÈ¢ ð s ð*€˜O²¿¿Àÿð äÔÙ  ðnŸ¨SMTP connection¡$ª ð¾ ð8  ð–´BàCÈDEÁFÁƒ¿ÀË8cÑÿˆðÿà0|@ÈpÀ ¸P @­ ­ ¬€ðð Èð¿¢ ð9 £ ð<€ T²…‡¿ƒ¿ÀÿðÐÐ ¹ } ðSŸ¨(2)¡ ª ðp ð< à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿ÀÿðÀP @°ðü¢ ð= £ ð<€èX²…‡¿ƒ¿ÀÿððP  ðŸ @TXT  v=spf1 ip4:64.126.106.0/24 ¡!! ª  ðÞ¢ ð> £ ð<€ˆ\²…‡¿ƒ¿ÀÿðP À ðrŸ¨"DNS configuration includes record:¡##ª" ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?/ð ð ð( ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²î#ï € ¶"ð®"Pð.=ð>"ð( ð ððXB ð  ƒ ð0D¿ÀËŸoÑÿð` ° ðÄ ð ã ðT€Ph¯…‡Ììÿ‚€¿Àÿ¨)¨)?¿ðÐ€à  ð@Ÿ¡ª ð$ ð ³ ðB€Øm¯…‡ÌÿÌ¿À™fÿÿ?¿ð€À@ð  𲟨220 mailserver.to.com ESMTP MAIL FROM: 250 ok RCPT TO: 250 ok DATA 354 ok Buy our product, and visit URL . . .¡¤‘   ™™þ      ª*'   ] òóÿ!0ß'4ðä2 ð ó ðZ€€r¯…‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ð@ð  ðZŸ¨ IP x.x.x.x¡  ª  ðx ð c ð$€Üt¯¿ÿˆðÀ@°ðà  ¯ ð žðࢠð s ð*€ìv¯¿¿À™fÿÿðà@°Y ð†Ÿ  Is this mail coming from correct location (SPF) - Is this IP in block lists? Has this email  DATA seen before as spam?¡T-€--€-€ ª ðXB ðÀ ƒ ð0D¿ÀËŸoÑÿðP ð ðF² ð  C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð¢ÀðF² ð  C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð2Àðp ð  à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿððð@ ð¿¢ ð £ ð<€°€¯…‡¿ƒ¿Àÿðþ´ ðSŸ¨(1)¡ ª ð¿¢ ð £ ð<€…¯…‡¿ƒ¿Àÿ𢠋 ´ ðSŸ¨(3)¡ ª ð¿¢ ð £ ð<€ˆ¯…‡¿ƒ¿ÀÿðÀ m ðSŸ¨(4)¡ ª ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðP @‘ðÖÒ ð # ðl€dŒ¯…‡‰€Ìÿ̃ðt‹yÿŒdœ @¿Àÿ?¿ðPl U ð:Ÿ¡ª ðV¢ ð £ ð<€X¯…‡¿ƒ¿Àÿð @  ð꟨r SPF check IP block lists (DNSBL) Known bad domains Razor2, Pyzor, DCC email spam collection checks . . .¡>K-"€-mªr ðÈ¢ ð s ð*€`“¯¿¿Àÿð0 €ð  ðnŸ¨SMTP connection¡$ª ðÈ ð ³ ðB€€›¯…‡‚€ƒ¿Àÿð°à°  ðVŸ¨TO.COM¡ª ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð`` ðÛ¢ ð s ð*€Hޝ¿¿À™fÿÿð@P  ðŸ¨-Access control lists (ACL) or Content filters¡".-ª. ð^B ð  “ ð6D¿ÀË|ÎÑÿð^à^ð^B ð! “ ð6D¿ÀË|ÎÑÿð^ @^ð^B ð" “ ð6D¿ÀË|ÎÑÿð^` € ^ð^B ð# “ ð6D¿ÀË|ÎÑÿð^  À ^ð¿¢ ð$ £ ð<€£¯…‡¿ƒ¿ÀÿðjS ´ ðSŸ¨(2)¡ ª ðRB ð'@ s ð*D¿ÀÑÿð` ð ð¾¢ ð+ £ ð<€4§¯…‡¿ƒ¿Àÿð°°Öª ðRŸ¨??¡ª ðRB ð, s ð*D¿ÀÑÿðÀ ° ðR’ ð- s ð*…‡ÿf¿ÀÿðÐ@` ÀðÄ¢ ð. s ð*€t«¯¿¿À™fÿÿð ð °þ  ðjŸ¨Virus scanners (Clamv)¡"ª ðÀ¢ ð/ s ð*€´¯¯¿¿À™fÿÿðp 0 PÞ  ðfŸ¨Spam checkers (Spamassassin)¡ª ð½¢ ð0 £ ð<€¨³¯…‡¿ƒ¿Àÿð¤8Pë ðQŸ¨A¡ª ð½¢ ð1 £ ð<€D·¯…‡¿ƒ¿ÀÿðùúN ðQŸ¨B¡ª ð¿¢ ð3 £ ð<€àº¯…‡¿ƒ¿Àÿð` I ­ ðSŸ¨(5)¡ ª ð¿¢ ð4 £ ð<€|¾¯…‡¿ƒ¿Àÿðà ‰ ðSŸ¨(6)¡ ª ðXB ð5 ƒ ð0D¿ÀËŸoÑÿð  À   ð^B ð6@ “ ð6D¿ÀËŸoÎ ÑÿðP  À ðd2 ð8 £ ð<…‡ÀÀÀ‚€¿ÀËŸoÎÿðà` ` ð¹2 ð9@ “ ð6€¨Â¯…‡¿ÀÿðPð ° Ð ðSŸ¨ ¡ª ðX2 ð7 ƒ ð0…‡ÀÀÀ‚€¿Àÿðà` ` ð¾¢ ð& s ð*€tƯ¿¿À™fÿÿðÀ ð à ðdŸ¨External process¡"  ª ðXB ð:€ ƒ ð0D¿ÀËŸoÑÿðà÷ Q ð|’ ð; ã ðT…‡HKI½€ƒð‹¦ÿŒdœ @¿Àÿð€ Ðpð‚’ ð< ó ðZ=ÿ…‡HKI½€ƒð‹¦ÿŒdœ @¿Àÿðp ððÐ2 ð= ³ ðB€l˯…‡ƒ¿ÀÎÿðð 0 0  ð^Ÿ¨Other Programs¡ª ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ðð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²îmï € ð@ð ;ð¥ð( ð ðð¾ ð) Ó ðN€˜æ …‡Ììÿ¿Àÿ¨)¨)?¿ðÐ  ð@Ÿ¡ª ðÝ2 ð ó ðZ€Œé …‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ðà  @À ðSŸ¨ ¡ª ðx ð c ð$€ë ¿ÿˆðÀ@°ðà    ð žðp ð à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿð`   ðÄ ð ã ðT€hí …‡€ƒðF‹¦ÿŒdœ @¿Àÿð0 p00 ð@Ÿ °Procmail s rules cannot reliably identify content, so external statistical (Bayesian) programs are called in chain to determine if message is Unsolicited Bulk Email (*.rc modules interface to statistical programs)¡VÙ@ I1ªØ ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðP à‘ðÆ¢ ð% £ ð<€÷ …‡¿ƒ¿Àÿð ?À ðZŸ¨ MTA (Exim)¡ ª  ðX ð& ƒ ð0…‡ƒ¿ÀÿðÀÐpp ðR ð' s ð*…‡¿ÀÿðÀЀp ðä¢ ð( s ð*€üú ¿¿Àÿð`ú  ðŠŸ¨*LDA (Procmail) to deliver mail to user foo¡&+'ª* ðv’ ð Ó ðN+7ˆÿ…‡€ƒð‹yÿŒÎÿÿÿœ @¿Àÿð° `ó¼ ðˆÒ ð  ð`Ð…‡GV,H€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ð ð`% ð¯ ð* ³ ðB€¯…‡ÌÿÌ¿À™fÿÿ?¿ðP`  @  ð=Ÿ¨¡# ~/.procmail recipe SHELL = /bin/bash ... ... # Detect spam INCLUDERC = bayes1.rc INCLUDERC = bayes2.rc ... # was message spam? :0 * ERROR ?? [a-z] spam.mbox ¡j¢   0   ª¢ ðÊ2 ð+ à ðH€$ ¯…‡ƒ¿ÀË8cÎ ÿðP à°  ðRŸ¨ ¡ª ðÀ¢ ð$ “ ð6€Ôà…‡¿¿ÀÿðàÐ þ   ðZŸ¨ bogofilter¡ ª  ð¿¢ ð, “ ð6€¯…‡¿¿Àÿðà   ðYŸ¨ Spamprobe¡ ª  ð­¢ ð- s ð*€¯¿¿ÀÿðÀP ðSŸ¨Bmf¡ª ð´¢ ð. s ð*€È¯¿¿Àÿð p`  ðZŸ¨ Spamoracle¡ ª  悁ð/ s ð*€¯¿¿ÀÿðP à 3  ðUŸ¨Ifile¡ª 悁ð0 s ð*€ ¯¿¿ÀÿðkÐ # +  ðUŸ¨. . .¡ª ð^B ð1€ “ ð6,, D¿ÀË8cÑÿðW ‡ ½ð^B ð2€ “ ð6õ€¡ÿD¿ÀË8cÑÿð°Ààð^B ð3€ “ ð6ûŠÿD¿ÀË8cÑÿða¡ÏŠð^B ð4€ “ ð6ËA?ÿD¿ÀË8cÑÿðd 1a” ð^B ð5€ “ ð6¹öKD¿ÀË8cÑÿð/ V † _ ð^B ð6€ “ ð6mÿD¿ÀË8cÑÿðb¦Ö’ð½2 ð7 “ ð6€($¯…‡Ììÿ¿Àÿðx ‚ p ðWŸ¨ ¡  ª  ðТ ð8 £ ð<€Ä(¯…‡¿ƒ¿Àÿðð ä6 ðdŸ¨incoming mail message¡ª ð¢ ð9 £ ð<€°,¯…‡¿ƒ¿ÀÿðÐ$G ðVŸ¨Host A¡ª ð¢ ð: £ ð<€À/¯…‡¿ƒ¿Àÿðàà' ðVŸ¨Host B¡ª 𢢠ð; £ ð<€Ì4¯…‡¿ƒ¿Àÿð i° ð6Ÿ¨UBE?ª ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ðð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²îvï € &ð`ððž ð( ð ððÝ2 ð ó ðZ€ôᯅ‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ðpà€ P ðSŸ¨ ¡ª ðx ð c ð$€L㯿ÿˆðÀ@°ðà  ¯ ð žð¢ ð ƒ ð0€¤æ¯¿ƒ¿À™fÿÿð 0@  𥟨+http://cr.yp.to/smtp/mail.html See RFC 2821¡,, ªB   ðÈ¢ ð s ð*€$쯿¿ÀÿðÀ § ðnŸ¨SMTP connection¡"ª ð|Ò ð ã ðTê…‡€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ðà @ pðp ð à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿ÀÿðP€`Àð>ò ð€ Ó ðN€Ô﯉¿GúïÿÿH­áÿÿƒ¿ÀÎ ÿ ðÀ  ðÀŸ pA  robot program making a collection of email addresses¡99ª8 ðÈ ð  ³ ðB€ô¯…‡‚€ƒ¿Àÿðà РР ðVŸ¨TO.COM¡ª ð ð  ã ðT€d÷¯…‡€ƒðF‹¦ÿŒdœ @¿Àÿð@0À  𑟨1Spammer injects messages: All use forged address¡&2ª1 ð% ð  ³ ðB€ä²…‡ÌÿÌ¿À™fÿÿ?¿ð €À  𳟨‘220 mailserver.target.net ESMTP MAIL FROM: 250 ok RCPT TO: 250 ok DATA 354 ok Buy our product, and visit URL . . .¡¤’    fÌÿþ      ª*+  _ òóÿ!0ß+3ðˆÒ ð   ð`¡Ûí…‡GV,H€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ðà @ƒ ðF² ð  C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðð ðÀ 1ð·2 ð “ ð6€0 ²…‡ÌÿÌ¿Àÿð €Ð  ðQŸ¨RFC¡ª ðX’ ð ƒ ð0…‡ƒ¿Àÿðà ÐðË2 ð ³ ðB€ð̯…‡ƒ¿ÀÎÿð à à  ðYŸ¨ Libraries¡  ª  ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ððð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²r0°ú ì‡eA£3€ž"¶»Ø»HG9õœ 4Ê tèò é(€àà€ òú/È 0ÒÕ0·DTimes New Romanœ©ÃhÖPÖvÇ 0hÖ(Ý 0„·DComic Sans MSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„B ·DCourier NewSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„10·DArialr NewSnœ©ÃhÖughts about increasing spam annoyance” by 5  !Oð°2ð$5X¾t˜‹gFŽêûÅ»Nkˆÿj Þbð$"ë&ÓBwêÐõ<@å§ _ÿæjÞ2ð$ßèÓ!WY—“r†Z¦!Rÿ&9PÞbð$Î61¥,Ï*äd5ÿ-v?Þc ð$ƒ¿Àÿ@ñÌìÿfÌÿ™™ÿ@ñÿÿÿÿ÷ðó€Ð7N×ÑÊš;2NÍÉÊš;úgþý4FdFdvÇ 0\Ö¬ÿÿÿ(ÿÿÿpûppû@ <ý4!d!d`ó 0ÚˆªÃ<ý4dddd`ó 0ÚˆªÃÿ ?Ù Ú%ð­óŸª Ÿª ó Ÿ¨How address harvesting works¡ ª Ÿª óŸ¨'Challenge-Response based authentication¡(( ª' Ÿª ó Ÿ¨&How viruses/spam should not be treated¡'' ª& Ÿª ó Ÿ¨)Challenge-Response system causing Joe-Job¡** ª) Ÿª óŸ¨"How SPF helps to prevent forgeries¡## ª" Ÿª óŸ¨"How MTA level UBE prevention works¡## ª" Ÿª óŸ¨*Procmail with battery of statistical tools¡++ ª* Ÿª óŸ¨Tools¡ ª Ÿª êîhï € ð@ð ;ð ð( ð ðð¾ ð) Ó ðN€˜æ …‡Ììÿ¿Àÿ¨)¨)?¿ðÐ  ð@Ÿ¡ª ðÝ2 ð ó ðZ€Œé …‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ðà  @À ðSŸ¨ ¡ª ðx ð c ð$€ë ¿ÿˆðÀ@°ðà    ð žðp ð à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿Àÿð`   ðÄ ð ã ðT€hí …‡€ƒðF‹¦ÿŒdœ @¿Àÿð0 p00 ð@Ÿ °Procmail s rules cannot reliably identify content, so external statistical (Bayesian) programs are called in chain to determine if message is Unsolicited Bulk Email (*.rc modules interface to statistical programs)¡VÙ@ I1ªØ ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðP à‘ðÆ¢ ð% £ ð<€÷ …‡¿ƒ¿Àÿð ?À ðZŸ¨ MTA (Exim)¡ ª  ðX ð& ƒ ð0…‡ƒ¿ÀÿðÀÐpp ðR ð' s ð*…‡¿ÀÿðÀЀp ðä¢ ð( s ð*€üú ¿¿Àÿð`ú  ðŠŸ¨*LDA (Procmail) to deliver mail to user foo¡&+'ª* ðv’ ð Ó ðN+7ˆÿ…‡€ƒð‹yÿŒÎÿÿÿœ @¿Àÿð° `ó¼ ðˆÒ ð  ð`Ð…‡GV,H€Ìÿ̃ðt‹yÿœ @¿Àÿ?¿ð ð`% ðª ð* ³ ðB€¯…‡ÌÿÌ¿À™fÿÿ?¿ðP`  @  ð8Ÿ¨œ# ~/.procmailrc SHELL = /bin/bash ... ... # Detect spam INCLUDERC = bayes1.rc INCLUDERC = bayes2.rc ... # was message spam? :0 * ERROR ?? [a-z] spam.mbox ¡j   0   ª ðÊ2 ð+ à ðH€$ ¯…‡ƒ¿ÀË8cÎ ÿðP à°  ðRŸ¨ ¡ª ðÀ¢ ð$ “ ð6€Ôà…‡¿¿ÀÿðàÐ þ   ðZŸ¨ bogofilter¡ ª  ð¿¢ ð, “ ð6€¯…‡¿¿Àÿðà   ðYŸ¨ Spamprobe¡ ª  ð­¢ ð- s ð*€¯¿¿ÀÿðÀP ðSŸ¨Bmf¡ª ð´¢ ð. s ð*€È¯¿¿Àÿð p`  ðZŸ¨ Spamoracle¡ ª  悁ð/ s ð*€¯¿¿ÀÿðP à 3  ðUŸ¨Ifile¡ª 悁ð0 s ð*€ ¯¿¿ÀÿðkÐ # +  ðUŸ¨. . .¡ª ð^B ð1€ “ ð6,, D¿ÀË8cÑÿðW ‡ ½ð^B ð2€ “ ð6õ€¡ÿD¿ÀË8cÑÿð°Ààð^B ð3€ “ ð6ûŠÿD¿ÀË8cÑÿða¡ÏŠð^B ð4€ “ ð6ËA?ÿD¿ÀË8cÑÿðd 1a” ð^B ð5€ “ ð6¹öKD¿ÀË8cÑÿð/ V † _ ð^B ð6€ “ ð6mÿD¿ÀË8cÑÿðb¦Ö’ð½2 ð7 “ ð6€($¯…‡Ììÿ¿Àÿðx ‚ p ðWŸ¨ ¡  ª  ðТ ð8 £ ð<€Ä(¯…‡¿ƒ¿Àÿðð ä6 ðdŸ¨incoming mail message¡ª ð¢ ð9 £ ð<€°,¯…‡¿ƒ¿ÀÿðÐ$G ðVŸ¨Host A¡ª ð¢ ð: £ ð<€À/¯…‡¿ƒ¿Àÿðàà' ðVŸ¨Host B¡ª 𢢠ð; £ ð<€Ì4¯…‡¿ƒ¿Àÿð i° ð6Ÿ¨UBE?ª ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ðð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²rhðbûõœ DðÒ tè é(€àà€ òú/È 0ÒÕ0·DTimes New RomanÄ©ÃhÖPÖvÇ 0hÖ(Ý 0h·DComic Sans MSnÄ©ÃhÖPÖvÇ 0hÖ(Ý 0hB ·DCourier NewSnÄ©ÃhÖPÖvÇ 0hÖ(Ý 0h10·DArialr NewSnÄ©ÃhÖPÖvÇ 0hÖ(Ý 0h"¤ €`ÿÿÿÿ¥ .©  @£nÿý?" dd@ÿÿïÿÿÿÿÿÿ  @@``€€ „ð|ð`, Û ?< >5  !Oð°2ð$5X¾t˜‹gFŽêûÅ»Nkˆÿj Òbð$"ë&ÓBwêÐõ<@å§ _ÿæjÒ2ð$ßèÓ!WY—“r†Z¦!Rÿ&9PÒbð$Î61¥,Ï*äd5ÿ-v?Òc ð$ƒ¿Àÿ@ñÌìÿfÌÿ™™ÿ@ñÿÿÿÿ÷ðó€Ð7N×ÑÊš;2NÍÉÊš;úgþý4QdQdvÇ 0\Ö üÿÿ²ÿÿÿpûppû@ <ý4!d!d`ó 0Ú°ªÃ<ý4dddd`ó 0Ú°ªÃÿ ?Ù Ú%ðÐóŸ ÀSource pictures for document  Thoughts about increasing spam annoyance by <jari.aalto@cante-net¡aaªa Ÿ¨ License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). ¡ ª ó Ÿ¨How address harvesting works¡ ª Ÿª óŸ¨'Challenge-Response based authentication¡(( ª' Ÿª ó Ÿ¨&How viruses/spam should not be treated¡'' ª& Ÿª ó Ÿ¨)Challenge-Response system causing Joe-Job¡** ª) Ÿª óŸ¨"How SPF helps to prevent forgeries¡## ª" Ÿª óŸ¨"How MTA level UBE prevention works¡## ª" Ÿª ó  !"#$%&'()*+,-./0123456þÿÿÿ89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œ¹ÒŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´Ðýÿÿÿýÿÿÿ¸þÿÿÿº»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËžþÿÿÿÎÏÑþÿÿÿÓÔÕÖþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿd›Oφꪹ)è;ªa0õÇÍ€Picturesÿÿÿÿÿÿÿÿ‡lCurrent Userÿÿÿÿÿÿÿÿÿÿÿÿ,SummaryInformation(ÿÿÿÿt PowerPoint Document(ÿÿÿÿÿÿÿÿÿÿÿÿ7S#DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿPÖvÇ 0hÖ(Ý 0„"¤ €`ÿÿÿÿ¥ .©  @£nÿý?" dd@ÿÿïÿÿÿÿÿÿ  @@``€€ „ð|ð`, Û ?<> 5  !Oð°2ð$5X¾t˜‹gFŽêûÅ»Nkˆÿj Þbð$"ë&ÓBwêÐõ<@å§ _ÿæjÞ2ð$ßèÓ!WY—“r†Z¦!Rÿ&9PÞbð$Î61¥,Ï*äd5ÿ-v?Þc ð$ƒ¿Àÿ@ñÌìÿfÌÿ™™ÿ@ñÿÿÿÿ÷ðó€Ð7N×ÑÊš;2NÍÉÊš;úgþý4FdFdvÇ 0\Ö¬ÿÿÿ(ÿÿÿpûppû@ <ý4!d!d`ó 0ÚˆªÃ<ý4dddd`ó 0ÚˆªÃÿ ?Ù Ú%ð­óŸª Ÿª ó Ÿ¨How address harvesting works¡ ª Ÿª óŸ¨'Challenge-Response based authentication¡(( ª' Ÿª ó Ÿ¨&How viruses/spam should not be treated¡'' ª& Ÿª ó Ÿ¨)Challenge-Response system causing Joe-Job¡** ª) Ÿª óŸ¨"How SPF helps to prevent forgeries¡## ª" Ÿª óŸ¨"How MTA level UBE prevention works¡## ª" Ÿª óŸ¨*Procmail with battery of statistical tools¡++ ª* Ÿª óŸ¨Tools¡ ª Ÿª êîšï € JðBpð> 0ñ ðžð( ð ð ðæ2 ð' ó ðZ€ô´ …‡€ƒðŒÎÿÿÿœ @¿Àÿ?¿ð9d  ð\Ÿ¨ IP 111.2.3.4¡  ª  ðr ð S ð€Ì· ¿ÿðÀ@°ðà    ð žð~ ð ã ðT€È¹ …‡€ƒð-‹¦ÿŒdœ @¿Àÿðpà P  ðúŸ ŠSPF result:  No, mail did not come through our Mail Exchanger (MX) ¡6F 7ªE ðC¢ ð s ð*€L ¿¿À™fÿÿð€ € Æ ð韨!SPF check: consult DNS TXT record¡J"  fÌÿþª*   òóÿ!0ßðXB ð À ƒ ð0D¿ÀËŸoÑÿðÙ ¤Ä™ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfðàÀ b ðF² ð C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl59\j0223568.wmfð ¦Éð%¢ ð ³ ðB€¨ ²¿G] H‹šƒ¿Àÿ ð °à à 𳟨AIs this message coming from IP 111.2.3.4 authorized to send mail?¡@B fÌÿþªB ðp ð" à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿ÀÿðÉ $9ð4ò ð( € Ó ðN€è&²‰¿GíÒÿÿH0ƒ¿ÀÎ ÿ ð Ô $) ð¶Ÿ fHost located at some ISP s address space 111.2.*.* ¡44ª3 ðÈ ð+ ³ ðB€Ü*²…‡‚€ƒ¿Àÿðé$ôÙ ðVŸ¨TO.COM¡ª ðÊ ð, ³ ðB€ô.²…‡‚€ƒ¿Àÿððð P à ðXŸ¨FROM.COM¡  ª ðß ð0 ³ ðB€¼2²…‡ÌÿÌ¿À™fÿÿ?¿ðÉ$´y  ðmŸ¨%220 mailserver.to.com ESMTP ... 550 ¡&& ª& ðÊ ð/ # ð¢BàCÈDEÁFÁƒ¿ÀÁÄË8cÎÑ×ÿðÿà0|@ÈpÀ ¸P @­ ­ ¬€ð°Àw xð¿¢ ð1 £ ð<€Ü5²…‡¿ƒ¿Àÿð© „mV  ðSŸ¨(1)¡ ª ð¿¢ ð3 £ ð<€4:²…‡¿ƒ¿ÀÿðàÀ© ðSŸ¨(3)¡ ª 𜢠ð5 s ð*€H=²¿¿À™fÿÿð  @ æ  ðBŸ ÔSMTP 5xx reject: message is returned to sender due to SPF result:  you did not use from.com to send mail. ¡<kDªk ð¿¢ ð4 £ ð<€¼D²…‡¿ƒ¿Àÿð) ôÝÖ  ðSŸ¨(4)¡ ª ðF² ð. C ð€€AÁG:\Documents and Settings\Administrator.W2KPICASSO.000\Application Data\Microsoft\Media Catalog\Downloaded Clips\cl5e\j0235958.wmfðð Р 1ð‚Ò ð! ó ðZ”…‡€Ìÿ̃ðt‹yÿŒdœ @¿Àÿ?¿ð sO # ðe¢ ð £ ð<€”M²…‡¿ƒ¿ÀÿðÉ Tc/ ðùŸ¨=Spammer sends message pretending to come from foo@from.com¡6>1 fÌÿþª21    òó!0ß1:ðÈ¢ ð s ð*€˜O²¿¿Àÿð äÔÙ  ðnŸ¨SMTP connection¡$ª ð¾ ð8  ð–´BàCÈDEÁFÁƒ¿ÀË8cÑÿˆðÿà0|@ÈpÀ ¸P @­ ­ ¬€ðð Èð¿¢ ð9 £ ð<€ T²…‡¿ƒ¿ÀÿðÐÐ ¹ } ðSŸ¨(2)¡ ª ðp ð< à ðH…‡€Ìÿ̃ð‹¦ÿŒdœ @¿ÀÿðÀP @°ðü¢ ð= £ ð<€èX²…‡¿ƒ¿ÀÿððP  ðŸ @TXT  v=spf1 ip4:64.126.106.0/24 ¡!! ª  ðÞ¢ ð> £ ð<€ˆ\²…‡¿ƒ¿ÀÿðP À ðrŸ¨"DNS configuration includes record:¡##ª" ðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?/ð ð ð( ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²rÊŠÕõœ lÊ,ð tèò é(€àà€ òú/È 0ÒÕ0·DTimes New Romanœ©ÃhÖPÖvÇ 0hÖ(Ý 0„·DComic Sans MSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„B ·DCourier NewSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„10·DArialr NewSnœ©ÃhÖPÖvÇ 0hÖ(Ý 0„"¤ €`  Aþÿÿÿ!"#$%&'()*+,-./0123456789:;<=>?@þÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿà…ŸòùOh«‘+'³Ù0D `hˆ˜ ¨´ Ô à ìøäPowerPoint PresentationnonePoinonePoi47eMicrosoft PowerPointon@ð;ë·@Ðmjj¦Ä@P¡a0õÇÅG< ÿÿÿÿ‰g  –]&ÿÿÿÿÀÐ &ÿÿÿÿ&#ÿÿÿÿTNPP Ã2ÿÿOMiP & TNPPô &ÿÿÿÿ&TNPP   ÐÀ üÿÿÿ-ú-- !ðÐÀ-üÿÿÿ-ðú-&ÿÿÿÿGÁ&ÿÿÿÿûÉ’}ôw@k3 m½¬ôwƬôw0- &ÿÿÿÿGyÁ&ÿÿÿÿ ü--iyðH-- ûàÿ@Times New Roman½¬ôwƬôw0-ð .þÿÕÍÕœ.“—+,ù®0`ˆ¨¸ÀÈÐ Ø àè ðø  ýäOn-screen ShownonereeS#Î   Times New RomanComic Sans MS Courier NewArialDefault DesignaSource pictures for document ”ThoŸ¨*Procmail with battery of statistical tools¡++ ª* Ÿª óŸ¨Tools¡ ª Ÿª êîäï€ ”ðŒ0ðð$ð( ð ððr ð S ð€Ø›õ¿ÿð °Ðpðà õ ð žðr ð S ð€”œõ¿ÿð ` à ðà õ ð žðH ð ƒ ð0ƒ“ŽŸ‹”Þ½h¿ÿ ?ð ÿÿÿ€€€Ì™33ÌÌÌÿ²²²r+!õœ ê# t[2 $o8Source pictures for document ”Thoughts about increasing              . .=2 JÍ$spam annoyance” by VERBOSE = "on" LOGABSTRACT = "all" LOGFILE = $HOME/tmp/pm.log # SHELL # - it is highly important that shell is set to /bin/sh. See faq # SHELL = /bin/sh # VERY IMPORTANT UMASK = 007 # James Bond :-) LINEBUF = 8192 # make sure procmail won't choke # PATH # - be sure the `sendmail' is along PATH. Typically /usr/sbin # - This is a generic path structure that will work accross # various platforms: SunOS, HP-UX, Linux. Actually It doesn't # matter if there are non-exixtent paths; it only slightly # decreases performance to find a particular program, like # `awk'. Place the "best paths" first. PATH =\ :$HOME/bin\ :/bin\ :/usr/bin\ :/opt/bin\ :/vol/bin\ :/usr/sbin\ :/usr/local/bin\ :/usr/local/sbin\ :/opt/local/bin\ :/vol/local/bin\ :/usr/contrib/bin\ :/usr/ucb\ :/usr/lib\ :/vol/lib\ :/usr/ccs/bin\ :${PATH} # ................................................................. # Using Procmail Module Library http://sf.net/projects/pm-lib # # The variable's name must be `PMSRC' - All pm-ja*.rc # depend on it. PMSRC = /usr/share/procmail-lib # Load the central initial startup code. This will define all # modules an variables INCLUDERC = $PMSRC/pm-javar.rc # ................................................................. # Now, start using modules. # Alan K. Stebbens's libraries do not include central setup. # Peek inside every code. Here the "date" module is called. INCLUDERC = $PMSRC/date.rc # The complete list of defined $RC_* variables is defined in # pm-javar.rc, peek there. # Activate mailing list detection module. JA_LIST_CONVERSION = "\ jde java.jde,\ java java.lang,\ FLAMENCO flamenco,\ " INCLUDERC = $RC_LIST :0 : * ! LIST ?? ^^^^ mailinglist.$LIST # ... other modules ... other recipes ... # End of ~/.procmailrc example procmail-lib-2009.1202/doc/examples/spam-bayesian.procmailrc000066400000000000000000000027331130547513300236030ustar00rootroot00000000000000# ~/.procmailrc.bayesian # # This module demonstrates "Using battery of Bayesian shields from procmail" # described in README.txt of Procmail Module library. Please read that document # before trying to use this file. You need to install external programs first. # # Copy this file to suitable location, modify it as needed, and # include file from ~/.procmailrc with call: # # INCLUDERC = $HOME/.procmailrc.bayesian SHELL = /bin/sh PMSRC = /usr/share/procmail-lib INCLUDERC = $PMSRC/pm-javar.rc # Define variables # If you have one of these programs installed, # simply remove *comment* from the line. # JA_UBE_ANNOYANCE_PRG = "/usr/bin/annoyance-filter" # JA_UBE_BMF_PRG = "/usr/bin/bmf" # Bayesian Mail Filter # JA_UBE_BSFILTER_PRG = "/usr/bin/bsfilter" # JA_UBE_BOGOFILTER_PRG = "/usr/bin/bogofilter" # JA_UBE_IFILE_PRG = "/usr/bin/ifile" # JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/spamassassin" # or use 'spamc' # JA_UBE_SPAMORACLE_PRG = "/usr/bin/spamoracle" # JA_UBE_SPAMPROBE_PRG = "/usr/bin/spamprobe" # This module is "umbrella" for all Bayesian programs. # Variable ERROR is set if any of the programs classify # message as spam. INCLUDERC = $PMSRC/pm-jaube-prg-runall.rc :0 : * ERROR ?? ^()\/.+ spam.mbox # Program `ifile' is special. It can be trained to detect several kinds # of messages. Header X-Spamifile will appear INCLUDERC = $PMSRC/pm-jaube-prg-ifile.rc :0 : * ERROR ?? \/[a-z]+ $MATCH.mbox # End of file procmail-lib-2009.1202/doc/examples/spam-procmail.procmailrc000066400000000000000000000025041130547513300236120ustar00rootroot00000000000000# ~/.procmailrc.spam-procmail # # This module is demonstrated in "A lightweight UBE block system with pure procmail" # README.txt of Procmail Module library. Please read that document # before trying to use this file. No external programs need to be installed. # # Copy this file to suitable location, modify JA_UBE_VALID_ADDR and other # variables as needed, and include file from ~/.procmailrc with call: # # INCLUDERC = $HOME/.procmailrc.spam-procmail # PMSRC = /usr/share/procmail-lib INCLUDERC = $PMSRC/pm-javar.rc # Define variables enabled = "yes" # Set to "no" to disable following block :0 * enabled ?? "yes" { saved = $VERBOSE # Don't record logs VERBOSE = "off" JA_UBE_ATTACHMENT_ILLEGAL_KILL = "yes" JA_UBE_VALID_ADDR = "(me@example.com|another@example.com)" INCLUDERC = $PMSRC/pm-jaube.rc # If ERROR is empty, it means the previous module # did not see anything special. Try another # spam detection module: search bad keywords :0 * ERROR ?? ^^^^ { INCLUDERC = $PMSRC/pm-jaube-keywords.rc } VERBOSE = $saved # If ERROR was set, the message was classified as UBE. # The "\/" records reason to procmail's log file :0 : * ERROR ?? ()\/.+ spam.mbox } # End of file procmail-lib-2009.1202/doc/index.html000066400000000000000000000240501130547513300171500ustar00rootroot00000000000000 Procmail Module Library homepage
Procmail Module Library project

Links and download

Note: that the most up to date version is in version control. See development page instructions how get latest source code.

What is Procmail Module Library?

Procmail is a mail processing utility, which can help filter your mail, sort incoming mail according to sender, Subject line, length of message, keywords in the message, etc. It can be used to implement an ftp-by-mail server, mailing list and much more. Procmail is also a complete drop-in replacement for your MDA (if this doesn't mean anything to you, you may not want to know). Procmail runs primarily under Unix, but it is also included in Cygwin (Win32). See Infinite Ink's Procmail page for information about related utilities for various other platforms, and competing Unix programs, like sieve (there aren't that many).

The Procmail module library is a collection of self standing plug-in modules that intend to make procmail more fun. Instead of having to write cryptic looking procmail files, you could see if any of the existing modules would already solve the problem. For example, if you subscribe to many mailing lists and wonder how you could save the messages to separate folders, take a look at plug-in pm-jalist.rc, which is able to adapt and find new mailing lists. Or if you've been a victim of spam and would need a quick shield, you can plug in Unsolicited Bulk Email (UBE) modules pm-jaube.rc and pm-jaube-keywords.rc. But for serious long term spam protection, please see the article mentioned at the top of this page which will outline more efective measures. There is lot more to see, just refer to the Manual link at the top of thispage.

The modules have been developed using Emacs and there exists an Emacs minor mode tinyprocmail.el which can assists to write and "Lint" (=code check) procmail recipe files. The tinyprocmail.el's Lint output will look something like this, when run on procmail file:

      *** YYYY-MM-DD HH:MM (.procmailrc) <version> tinyprocmail.el
      cd /home/foo/
      pm.lint:010: Warning, no right hand variable found. ([$`']
      pm.lint:055: Pedantic, flag order style is not standard `hW:'
      pm.lint:060: Warning, message dropped to folder, you need lock.
      pm.lint:062: Warning, recipe with "|" may need `w' flag.
      pm.lint:073: Warning, Formail used but no `f' flag found.
    

Platform Support

Only the latest released procmail version is supported. Procmail is usually installed as MDA/LDA (Mail/Local Delivery Agent); the software, that delivers incoming mail to users' mailboxes. Ask your sysadm, if you do not know if procmail is available in your system. Version number can be checked with:
    procmail -v
    

Contact

There is no mailing list for the project. See Development page how to contact maintainer and submit feature requests and bug reports. See also Procmail mailing which can be read at news.gmane.org NNTP group gmane.mail.procmail.


GNU GPL All files in this project are licensed under GNU GPL. Savannah Logo This project, as well as many other projects is hosted by Savannah.
Savannah Logo W3C CSS logo W3 validated.
procmail-lib-2009.1202/doc/license/000077500000000000000000000000001130547513300165745ustar00rootroot00000000000000procmail-lib-2009.1202/doc/license/COPYING.GNU-FDL000066400000000000000000000476631130547513300207020ustar00rootroot00000000000000 GNU Free Documentation License Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. procmail-lib-2009.1202/doc/license/COPYING.GNU-GPL000066400000000000000000000431031130547513300207000ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. procmail-lib-2009.1202/doc/license/LICENSE.txt000066400000000000000000000042731130547513300204250ustar00rootroot00000000000000Copyright information This program runs solely with Free Software. It does not rely on any component of non-Free Software. Copyright (C) 1997-2010 Jari Aalto This program (referring to all files, including documentation, distributed in project "Procmail Module Library") is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with program; see the file COPYING.GNU-GPL. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Visit for more information. - - Exception: The documentation of project "Procmail Module Library" (*.txt and *.html files) is DUAL LICENCED and may be distributed under the terms of GNU General Public License (GNU GPL) --see above--; *or*, at your option, distributed under the terms of GNU Free Documentation License (GNU FDL). The end user can continue to distribute the documentation in this dual licence form *or* select the other license (GNU GPL, GNU FDL) and remove the unwanted one. Copyright (C) 1997-2010 Jari Aalto Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License"; see the file COPYING.GNU-GFDL. Visit for more information. End procmail-lib-2009.1202/doc/manual/000077500000000000000000000000001130547513300164275ustar00rootroot00000000000000procmail-lib-2009.1202/doc/manual/index-body.html000066400000000000000000012305271130547513300213710ustar00rootroot00000000000000 Procmail Module library documentation

Document id

Copyright © 1997-2009 Jari Aalto

License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL).

This page documents of part of the files included in Procmail Module Library project. Each modules is can be used as a plug-in. Some can be used as subroutines to your own programs and some are self containing recipes. There is no user or site specific settings in these modules.

An attempt to minimize the use of external processes was the design goal. The modules try to use pure procmail way as much as possible e.g. to get date and directly from message without calling expensive shell date. It is important to remember that procmail is run on every incoming message and every CPU tick spent counts.

Document control

This document has been automatically generated from the procmail files with 2 small perl programs in the following manner:

      % perl -S ripdoc.pl `ls pm-ja*.rc|sort`   > pm-lib.raw

      % perl -S t2html.pl                                           \
        --html-frame                                                \
        --base http://freshmeat.net/projects/procmail-lib           \
        --button-previous http://freshmeat.net/projects/procmail-lib \
        --title  "Procmail module documentation"                    \
        --author "Jari Aalto"                                       \
        --meta-keywords "procmail, sendmail, programming, library"  \
        --meta-description "Procmail plug-in module documentation"  \
        --name-uniq                                                 \
        --Out                                                       \
        pm-lib.txt    

The perl program assume that the documentation sections have been written in Technical Text Format. The perl program ripdoc.pl can be found at CPAN entry http://www.cpan.org/modules/by-authors/id/J/JA/JARIAALTO/ and t2html.pl is available at project perl-text2html.


Pm-jaaddr.rc – extract 'foo@some.com' email address from variable INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc extracts the various components of email address from variable INPUT. You can do quite a lot interesting things with your email address. One of the tricks that you could use if you don't have sendmail plus addressing capabilities, is that you put the additional infomation to the RFC comment. Eg. If you read and followup to posts in usenet games groups, you could use:

      From: <em>login@site.com</em> (John Doe+usenet.games)    

Or if your email address's localpart (that's characters before @) already signify your First and surname, you don't need to repeat it in comment. However, place special marker "+" to mark additional information part for your procmail recipes:

      From: <em>first.surname@site.com</em> (+usenet.games)    

The use of RFC comment should work everywhere because RFC requires that comments are preserved along with the address information. If you would have sendmail plus addressing capabilities you would have used:

      From: <em>login+usenet.games@site.com</em> (John Doe)    

The idea is that the list infomation is readily available from the email. The following recipe will derive the plus information and use it directly as a mailbox where to drop the message. If The Editor: Emacs, means anything to you, you can program it to generate the appropriate From headers automatically when you send mail from Gnus Mail/Newsreader MUA. Drop me a message if you need an example how a piece of Emacs lisp code makes those magic RFC plus addresses in the background while you compose the body of the message.

      RC_EMAIL = $PMSRC/pm-jaaddr.rc
      TOME     = "(login1|login2)"

      :0
      *$ ^TO\/.*$TOME.*
      {
          INPUT       = $MATCH
          INCLUDERC   = $RC_EMAIL
          PLUS        = $COMMENT_PLUS

          #  If COMMENT_PLUS was defined, we found "+"
          #  address which contain "usenet.games". Save it to
          #  folder.

          :0 :
          * PLUS ?? [a-z]
          $PLUS
      }    

Notes

1998-05 David Hunt dh@west.net also mentioned that "you need to remember that some MTAs, (qmail for one, and soon vmail) use a dash ( - ) as the subaddress delimiter. So you'll want to allow for that in your code". For this reason the email part accepts both "-" and "+". The RFC comment however accepts only "+" and "--".

Example input

      "From: foo+procmail@this.site.com (Mr. foo)"        traditional
      "From: foo-procmail@this.site.com (Mr. foo)"        new styled    

NOTE: M$SOFT mailers tend to send idiotic smart quotes "'Mr. foo'" and this recipe ignores these two quotes ["'] as if message had only the standard ["]

Returned values

      ADDRESS     "foo+procmail@this.site.com"
                  containing the email address without <>

      ACCOUNT     "foo+procmail"
                  all characters before @

      ACCOUNT1    "foo"
                  characters before plus: account1+account2@site
                  Note, if there is no "+", this is same as ACCOUNT.

      ACCOUNT2    "procmail"
                  _only_ set if plus found: account1+account2@site

      SITE        "this.site.com"
                  all characters after @

      DOMAIN      "site.com"
                  the main domain, preceding words in site are
                  considered subdomain (local) addresses.

                      sub.sub.domain.net

      SUB         "this.site"
                  all the sub-domain names without the NET part.

      SUB1        "site"
                  The first subdomain counted from the _RIGHT_ after NET

      SUB2        "this"
                  Second subdomain.

      SUB3        ""
                  Third subdomain.

      SUB4        ""
                  Fourth subdomain.

      NET         "com"
                  last characters after last period ( net,com,edu ...)

      COMMENT     Anything unside parenthesis (Mr. Foo) or if no
                  parentheses found, then anything between quotes
                  "Mr. Foo"

      COMMENT_PLUS Anything after the "+" in the comment, like
                   "Mr Foo+mail.usenet" --> "mail.usenet"

                   Note: some MTA's don't allow + character, so use
                   alternatively '--':
                   "Mr Foo--mail.usenet"  --> "mail.usenet"    

Additionally there is variables DOT1 DOT2, which behave like ACCOUNT1 and ACCOUNT2, but in respect to dotted firstname.surname type address:

          john.doe@site.com

          ACCOUNT1    = john.doe
          ACCOUNT2    = <empty>
          DOT1        = john
          DOT2        = doe    

If there is plus, the ACCOUNT2 is defined

          john.doe+foo@site.com

          ACCOUNT1    = john.doe
          ACCOUNT2    = foo
          DOT1        = john          (in respect to ACCOUNT1)
          DOT2        = doe           (in respect to ACCOUNT1)    

Variable ERROR is set to "yes" if INPUT wasn't recognized or parsing the address failed.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there.

Call arguments (variables to set before calling)

      INPUT = string-to-parse    

Usage example

Read From field and address from it. This is lot faster than using external formail call.

      PMSRC   = $HOME/pm
      RC_ADDR = $PMSRC/pm-jaaddr.rc

      :0
      *  ^From:\/.*@.*
      {
          INPUT = $MATCH

          #  Turn off the logging while executing this part
          VERBOSE="off"   INCLUDERC = $RC_ADDR  VERBOSE="on"

          :0
          * ERROR ?? yes
          {
             # Hmm, no std email address found. Any other ideas?
          }
      }    


Pm-jabup.rc – Keeep N arriving message backup in separate directory

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details <http://www.gnu.org/copyleft/gpl.html>.

Description

Preserve last N arriving messages in a separate sub-directory. This should be your safety-belt recipe that you put to the beginning of your .procmailrc.

Procmail saves the backup files with names like: msg.rcG msg.scG msg.3YS1, msg.4YS1, msg.VYS1, msg.fYS1 to the backup directory.

Note: this recipe will alawys call shell commands for each message you recive. That is needed because cleaning of the backup directory. If you receive only small number of messages per day, the performance drop of your .procmailrc is not crucial. But if you store many messages per day, then the shell calls may be a performance problem.

In that case, consider moving the cleanup to the pm-jacron.rc module (The cleanup is run only once a day, not for every message)

John Gianni send his simple bsckup script to Jari, who packaged and generalized the code. The code is reused with John's permission and maintaining responsibility was transferred to Jari

Required settings

(none)

Call arguments (variables to set before calling)

  • JA_BUP_MAX, How many messages to keep at maximum. 32 is default
  • JA_BUP_DIR, Where to store the messages. $HOME/Mail/bup by default
  • JA_BUP_FILES, regexp to match the saved files. Procmail default.
  • JA_BUP_CHECK_DIR. Once you have verified that this recipe works, that directories are ok, please set this flag to "no" to prevent running unnecessary test command for each email.

Usage example

You only want to keep backup of messages that are not from mailing lists. You may want to use TO_ macro to detect addresses better, this example matches against all headers

      LISTS          = "(procmail|list-1|list-2)"
      JA_BUP_DIR     = $HOME/Mail/backup/.        # Create the path too
      JA_BUP_MAX     = 42                         # this should be enough

      :0
      *$ ! $LISTS
      {
          INCLUDERC = $PMSRC/pm-jabup.rc
      }    

If you get many messages, please don't use this module. Instead see pm-jacron.rc where similar backup work is done better.


Pm-jacookie1.rc – Generate unique id from INPUT variable.

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

When given a string, this subroutine returns a unique number representing a string, a cookie.

Required settings

(none)

Call arguments (variables to set before calling)

  • INPUT, String from which the magic-cookie is calculated
  • JA_COOKIE_CMD: shell command to read INPUT and return decimal or hex cookie string as one continuous block of characters. It decaults to HP-UX cksum, but your system may have md5 or chksum

Return values

  • Variable OUTPUT will contain the cookie.

Example usage

      INPUT           = "foo@site.com"
      JA_COOKIE_CMD   = "md5"     # or chksum
      INCLUDERC       = $PMSRC/pm-jacookie1.rc
      cookie          = $OUTPUT    


Pm-jacookie.rc – Handle cookie (unique id) confirmations

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with program. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Visit <http://www.gnu.org/copyleft/gpl.html>

Overview of features

  • Each user must register himself to cookie cache before he is considered "known"
  • Unless user return the generated cookie string; which is typically a decimal or hex number, he is not considered as known and should not have access to services you provide.
  • Can be used as a "doorbell" spam/UBE shield

Description

This recipe handles generating the cookie to new users, comparing the returned cookie against the original one and passing known users through if they already had returned their cookie.

When you run automatised scripts, eg. to manage mailing lists where users can subscribe and unsubscribe, you have better to install safety measure so that someone can not subscribe his enemy to 30 mailing lists.

The cookie is any continuous block of random characters that is sent to person who wanted to use the service. He must send back the cookie before the service starts an action, like subscribe. If someone forges the From address to pretend to be someone else and then subscribes as-beeing-someone-else to a mailing list, the cookie protects this from happening.

The cookie is sent to someone-else, and he must return the cookie before the "subscribe" service is activated. Obviously this someone-else will not be interested in sending back the cookie and thus the forgery fails. Isn't that simple, but efective protection against misuse?

Should I use this as Challenge-Response Spam shield?

Unsolicited Bulk Email aka Spam is crawling from every possible domain thinkable, so you might think that a challenge-response policy could be deployed to regular email communication as well. The idea would be that unknown people are requested to "join" to a white list, before discussion is initiated with them. Bulk email shotguns do not reply to challenges (here: cookies), so confirmations are not returned. Individual people that want to talk, may want to return the cookies.

Sounds like a perfect Unsolicited Bulk Email shield? No more non-invited mail? Wrong. Don't use this module for that. The whole idea of challenge-response is flawed and causes trouble for every person who tries to contact. Imagine for 10 people using C-R systems; they would all need to authenticate themselves. Who is going to believe that he is not replying to a spammer who is collecting email addresses? And what about automatic messages that might be received – there is no artificial intelligence to deparate "human" messages from automatically generated messages, so challenges just increase the overall mail traffic. Every C-R system doubles the mail traffic and becomes spam problem by itself.

In short, don't use this module for implementing a C-R system to block regular mail to you.

How it works

By default the cookie generated uses CRC 32 cksum, but if you have md5, you should use it. The cookie is generated from the reply address and immediately stored to cookie database file with entry

      DATE FROM-a COOKIE-a
      DATE FROM-b COOKIE-b    

If this was a new user or an old user, who has not registered his cookie yet, then original message is sent back to the sender with instructions: "please place the magic string to Subject line and resent the message."

When cookie is returned back, a new line to the database is added, simply by adding a duplicate entry. The file now looks like this:

      DATE FROM-a COOKIE-a
      DATE FROM-b COOKIE-b
      DATE FROM-a COOKIE-a    

When there is two or more same entries, like FROM-a, the address is supposed to be known and person behind it "cleared".

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jadate.rc
  • pm-jacookie1.rc
  • pm-jastore.rc

Call arguments (variables to set before calling)

  • JA_COOKIE_SEND, flag. Default is "yes". Set to "no" if you want to take full control of the message returned to user. You can check variable ERROR and use key which holds the unique cookie
  • JA_COOKIE_CACHE, cache to determine if this is new user or not.
  • JA_COOKIE_AUTO_KEY, flag. If set to "yes"; the cookie is initially put to the Subject when the message is bounched back. Receiver only has to press "r" to reply to send the cookie and message back (convenient). You set this flag to "no" when you want to avoid accidnebts eg. when receiver is about to subscribe to a mailing lists: he has to manually insert the cookie into subject. But keep flag to "yes" if you use this module to get your friends registered easily.
  • JA_COOKIE_KEYS, the cookie database. Email address and person's access cookie.
  • JA_COOKIE_RC, dubroutine to generate the cookie id from INPUT. By default uses CRC 32.
  • JA_COOKIE, the string from which the cookie will be generated. If you already have the return addres for the sender derived, you should assing a value to this to save unnecessary formail call.

Returned values

ERROR will contain the efective action when this recipe file ends

  • "new-user", This is first message from sender.
  • "known-user", message has email that has been "cleared" ie. cookie had been returned and user registered.
  • "key-mismatch", This is at least second message from sender. But he dind't send the confirmation in this message.

key is an internal variable in this recipe file and will hold the cookie id in case of "new-user" and "key-mismatch". You may want to use it if you generate your own reply.

Example usage for UBE shield

This is what I use to prevent unknown people from sending me UBE. It takes a bit extra, but they can easily return the message. Fill in the missing variables, this won't work out of the box for you.

      WORK        = "(domain1|domain2|domain3)"
      LISTS       = "(procmail|list-2|list-3|list-4)"
      VALID       = "(postmaster|abuse|$LISTS|$WORK)"
      RC_COOKIE   = $PMSRC/pm-jacookie.rc
      UBE_SPOOL   = $HOME/Mail/junk.ube.spool   # Save spam here

      :0
      *$ ! From:.*$VALID
      *$ ! ^FROM_DAEMON
      {
          JA_COOKIE_SEND  = "yes"         # Activate it
          INCLUDERC       = $RC_COOKIE

          :0 :
          * ! ERROR ?? known-user
          $UBE_SPOOL

          #  ... Past this point: it was user in whitelist, so the
          #  recipes after this block will take care of it
      }    

Example usage for subscriptions

      $RC_COOKIE   = $PMSRC/pm-jacookie.rc

      ...Mailing lists handled here...
      ...Your work messages filed here..

      TO            = `formail -rt -zxTo:`  # We need this elswhere
      JA_COOKIE_TO  = $TO

      #   For List-X all subscribe requests must
      #   be confirmaed

      * ^TO_()list-x
      * ^Subject: +subscribe\>
      {
          JA_COOKIE_SEND  = "no"
          INCLUDERC       = $RC_COOKIE

          :0
          * ERROR ?? known-user
          {
              #   User sent the subsribe request again, allow joining
              #   immediately.
          }
          :0 E
          {
              # Because the Send was set to "no"; we're in charge
              # to send a reply to the user.
              # ...generate suitable message with formail -rt
          }

      }

      #  End of example    


Pm-jacron.rc – Procmail: Run cron once a day

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>

Description

Framework for all cron tasks that can be run once a day. This is a wrapper recipe to your cron task list: when the day changes, you cron includerc is called.

Required settings

PMSRC must point to source directory of procmail code. This recipe will include

  • pm-javar.rc
  • pm-jadate.rc

Call arguments (variables to set before calling)

  • JA_CRON_RUN_FLAG, You must define this flag file.
  • JA_CRON_DATE_FILE, File where the date information, last cron run, is kept. Defaults to $HOME/.yymmdd
  • JA_CRON_RC, your includerc which is run when cron triggers.

A file JA_CRON_RUN_FLAG which defaults to ~/.yymmdd.run is created when your includerc, that contains list of cron tasks, is run. If new mail arrives while your cron recipes are still running, you should prevent invoking the cron again by checking if this file exists. When all the cron tasks have been run, this flag file is removed. Remember to use "w" flag in your cron recipes where necessary to serialize the work.

Return values

(none)

Usage example

Save backups to separate directory, but do cleaning only once a day We do not keep backups from mailing list messages

      LISTS          = "(procmail|list-1|list-2)"
      BACKUP_DIR     = "$HOME/Mail/backup/."

      #   Store backups: separate files to directory

      :0 c:
      *$ ! $LISTS
      $BACKUP_DIR

      #   Run JA_CRON_RC once a day. It contains all daily cron tasks

      CRON_RC             = $PMSRC/pm-jacron.rc   # the framework
      JA_CRON_RC          = $PMSRC/pm-mycron.rc   # the tasks to do
      JA_CRON_RUN_FLAG    = $HOME/.cron-running   # define this!

      #   Do not enter here if message arrived at the same day when
      #   the cron is already running. The CRON_RC takes care
      #   of deleting the file when cron has finished.

      :0
      *$ ! ? $IS_EXIST $JA_CRON_RUN_FLAG
      {
          INCLUDERC = $CRON_RC
      }    

The pm-jacron.rc file may contain anything. For example to clean the backup directory; you add these statements there

      #   rm dummy: if ls doesn't return files, make sure rm has
      #   at least one argument.
      #
      #   ls -t: list files; newest first
      #
      #   sed: chop $max newest files from the listing, leaving the
      #   old ones

      max = 32

      :0 hwic
      | cd $BACKUP_DIR && $RM -f dummy `ls -t msg.* | $SED -e 1,${max}d`

      # End of file pm-mycron.rc    


Pm-jadaemon.rc – Handle DAEMON messages by changing subject

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

When you send a message to a address that had delivery troubles, you get a DAEMON message back explaining the error problem. I usually want to save these daemon mesaages to a different folder and check the folder from time to time. A typical daemon message is like this (shortened)

      From: Mail Delivery Subsystem <em>MAILER-DAEMON@my.domain.com</em>
      Subject: Warning: could not send message for past 4 hours

      The original message was received at...
      ----- Transcript of session follows -----
      Deferred: Connection timed out
      ----- Original message follows -----
      [YOUR MESSAGE AS YOU SENT IT WITH HEADERS]    

Well, when I read the subjects, I do not like the standard error messages, but I also like to know to which address the delivery failed and what was the original subject. This small recipe changes the daemon message's Subject to

      Subject BRIEF-ERROR-REASON, SENT-TO-ADDRESS, ORIGINAL-SUBJECT    

and from that you can immediately tell if you should be worried Eg. if SENT-TO-ADDRESS was your friend's, then you want to take actions immediately, but if it were your complaint to UBE message to postmaster, you don't want to bother reading that daemon message. Here are some real examples:

      fatal errors,postmaster,ABUSE (Was: Super Cool Site!)
      Host unknown,postmaster,ABUSE (Was: A-Credit Information)
      undeliverable,postmaster,Could you investigate this spam
      Warning-Returned,friend,Have you looked at this    

Required settings

PMSRC must point to source directory of procmail code. This subroutine needs scrips

  • pm-javar.rc

Call arguments (variables to set before calling)

  • JA_DAEMON_SAVE. This is by default yes which causes the original subject to be saved under header field X-Old-Daemon-Subject. If you don't want that extra header generated, set this variable to no
  • JA_DAEMON_REGEXP, which messages to trigger

Return values

  • Variable ERROR will be set to "yes" if daemon message was handled otherwise; value is "no"

Usage example

Just add this recipe somewhere in your .procmailrc. The place where you would put this daemon message trapper subroutine is crucial: think carefylly how you order your recipes. One suggested order could be: backup important messages, cron-subroutine, handle duplicates, DAEMON MESSAGES, plus addressed message, server message (file server, ping responder...), MAILING LISTS, send possible vacation replies only after all above, apply kill file, detect mime, save private messages and las FILTER UBE.

      PMSRC           = $HOME/pm
      RC_DAEMON       = $PMSRC/pm-jadaemon.rc
      DAEMON_MBOX     = $HOME/Mail/junk.daemon.mbox

      ...

      INCLUDERC       = $RC_DAEMON

      :0 :            # If that was a daemon message, save it
      * ERROR ?? yes
      $DAEMON_MBOX    


Pm-jadate1.rc – 'Tue, 31 Dec 1997' date parser from variable INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc parses date from variable INPUT which has string

      "Week, Daynbr Month Year"    

Example input

      "Tue, 31 Dec 1997"      -- without comma
      "Tue 31 Dec 1997"       -- with comma    

Returned values

      YYYY    = 4 digits
      YY      = 2 digits
      MON     = 3 characters
      MM      = 2 digits
      DAY     = 3 characters
      DD      = 2 digits
      hh      = 2 digits      If available
      mm      = 2 digits      If available
      ss      = 2 digits      If available
      TZ      = 5 characters  If available    

Variable ERROR is set to yes if it couldn't recognize the INPUT and couldn't parse the basic YYYY, YY, MM, DD variables.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there.

Call arguments (variables to set before calling)

      INPUT = string-to-parse    

The INPUT can have anything after "Week, dayNbr Month Year", or before it: you can pass a string like "Thu, 13 Nov 1997 11:43:23 +0200".

Usage example

The first Received header will tell when the message was received by your mailserver. We parse the date and avoid calling expensive date command.

      PMSRC           = $HOME/pm
      RC_DATE_WDMY    = $PMSRC/pm-jadate1.rc #Week-Day-Month-Year parser

      # Get time from first header, it ends like this:
      #
      #       Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200

      :0
      *$ ^Received:.*;$s+\/...,$s+$d.*
      {
          INPUT = $MATCH

          #  Turn off the logging while executing this part

          VERBOSE=off   INCLUDERC = $RC_DATE_WDMY   VERBOSE=on

          :0
          * ERROR ?? yes
          {
             # Use some other way to get the time or shout loudly
          }
      }    


Pm-jadate2.rc – 'YYYY-MM-DD' ISO date parser from variable INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc parses date in format "YYYY-MM-DD hh:mm:ss" like 1997-12-01 and sets following variables whenever called

          YYYY    = 4 digits
          YY      = 2 digits
          MON     = 3 characters
          MM      = 2 digits
          DD      = 2 digits
          hh      = 2 digits  If avaliable
          mm      = 2 digits  If avaliable
          ss      = 2 digits  If avaliable    

Variable ERROR is set to yes if it couldn't recognize the INPUT and couldn't parse the basic YYYY, YY, MM, DD variables.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there.

Call arguments (variables to set before calling)

      INPUT = string-to-parse    

Last string in INPUT that matches number sequence NNNN-NN-NN is parsed.

Usage example

      PMSRC          = $HOME/pm
      RC_DATE_ISO    = $PMSRC/pm-jadate2.rc # ISO date parser

      INPUT = "This is 1800-10-11, a very old date"

      #  Turn off the logging while executing this part

      VERBOSE="off"  INCLUDERC=$RC_DATE_ISO  VERBOSE="on"    


Pm-jadate3.rc – 'Tue Nov 25 19:32:57' date parser from variable INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc parses date from variable INPUT which has string

      "Week, Month dayNbr hh:mm:ss yyyy",    

Example

      Tue Nov 25 19:32:57 1997    

Returned values

          YYYY    = 4 digits
          YY      = 2 digits
          MON     = 3 characters
          MM      = 2 digits
          DAY     = 3 characters
          DD      = 2 digits
          hh      = 2 digits
          mm      = 2 digits
          ss      = 2 sigits    

Variable ERROR is set to "yes" if it couldn't recognize the INPUT.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there.

Call arguments (variables to set before calling)

      INPUT = string-to-parse    

Usage example

The first Received header will tell when the message was received by the mailserver. Parse the date and avoid calling expensive date command.

      PMSRC           = $HOME/pm
      RC_DATE_WMDT    = $PMSRC/pm-jadate4.rc #Week-Month-Day-Time parser

      # Get time from X-From-Line: Which was added by my MDA
      #   X-From-Line: procmail-request@informatik.rwth-aachen.de \
      #    Tue Nov 25 19:32:57 1997

      :0 c
      *$ ^X-From-Line:\/.*
      {
          INPUT = $MATCH

          #  Turn off the logging while executing subroutine

          VERBOSE=off   INCLUDERC = $RC_DATE_WMDT   VERBOSE=on

          :0
          * ERROR ?? yes
          {
             # Use some other way to get the time or shout loudly
          }
      }    


Pm-jadate4.rc – make RFC 'Mon, 1 Dec 1997 17:41:09' and parse values

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine calls shell command date once and prses the values. This should be your last resort if you haven't got the date values by any other means. This subroutine assumes that the DATE command knows the following % specifier formats (HP-UX)

      Y   NNNN    year
      h   MON     month
      d   NN      day
      a   WEEK    Like "Mon"
      H   NN      hour
      M   NN      min
      S   NN      sec    

Returned values

      DATE    = RFC date in format "Mon, 1 Dec 1997 17:41:09"
                This is same as what you would see in From_

      YYYY    = 4 digits
      YY      = 2 digits
      MON     = 3 characters
      MM      = 2 digits
      DAY     = 3 characters
      DD      = 2 digits
      hh      = 2 digits
      mm      = 2 digits
      ss      = 2 sigits    

Variable ERROR is set to "yes" if values couldn't be set

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jadate1.rc

Call arguments (variables to set before calling)

(none)

Usage example

The First Received line will tell when the message was received by the MDA. If thata fails, then get date from the system. If you send test messages to # yourself, you don't usually put From_ header in it and thus there is # no date information in 'dry run' tests.

      # Get time from first eader, which is always same in my system
      # Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200

      INCLUDERC   = $PMSRC/pm-javar.rc    # to get $s $d definitions
      TODAY       # Clear it

      :0
      *$ ^Received:.*;$s+\/...,$s+$d.*
      {
          INPUT     = $MATCH
          INCLUDERC = $PMSRC/pm-jadate1.rc
          TODAY     = "$YYYY-$MM-$DD"
      }

      #   Check that variable did get set, if not then we have to call
      #   another date subroutine: Call shell then to find out date
      #
      #   You could also do this with ':0 E', but this is more
      #   educational

      :0
      *$ ! $TODAY^0
      {
          INCLUDERC = $PMSRC/pm-jadate4.rc    # Get date from Shell then
          TODAY     = $YYYY-$MM-$DD
      }    


Pm-jadate5.rc – 'Fri Jun 19 18:51:56 1998' date parser from var INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc parses date from variable INPUT which has string

      "WeekDay Month dayNbr Year"    

Example input

      "Fri Jun 19 18:51:56 1998"      -- without comma
      "Fri, Jun 19 18:51:56 1998"     -- with comma    

Returned values

      YYYY    = 4 digits
      YY      = 2 digits
      MON     = 3 characters
      MM      = 2 digits
      DAY     = 3 characters
      DD      = 2 digits
      hh      = 2 digits      If available
      mm      = 2 digits      If available
      ss      = 2 digits      If available
      TZ      = 5 characters  If available    

Variable ERROR is set to "yes" if it couldn't recognize the INPUT and couldn't parse the basic YYYY,YY,MM,DD variables.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there.

Call arguments (variables to set before calling)

      INPUT = string-to-parse    

The INPUT can have anything after "Week, dayNbr Month Year", or before it: you can pass a string like "Fri Jun 19 18:51:56 1998 11:43:23 +0200".

Usage example

The first Received header will tell when the message was received by your mailserver. We parse the date and avoid calling expensive date command.

      PMSRC           = $HOME/pm
      RC_DATE_WDMY    = $PMSRC/pm-jadate5.rc #Week-Day-Month-Year parser

      # Get time from first header, it ends like this:

      :0
      *$ ()\/From .*
      {
          INPUT = $MATCH
          #  Turn off the logging while executing this part

          VERBOSE=off   INCLUDERC = $RC_DATE_WDMY   VERBOSE=on

          :0
          * ERROR ?? yes
          {
             # Use some other way to get the time or shout loudly
          }
      }    


Pm-jadate.rc – Read date from the message hdrs: From_, Receved:

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This recipe will scan several headers to find the date string. When suitable header is found and the parsing has succeeded, the return variables are set. The Date values reflects the arrive time of the message; not the sending time. If nothing works, a shell call date is used as a last resort.

Returned values

      YYYY    = 4 digits
      YY      = 2 digits
      MON     = 3 characters
      MM      = 2 digits
      DAY     = 3 characters
      DD      = 2 digits
      hh      = 2 digits      if available
      mm      = 2 digits      if available
      ss      = 2 digits      if available    

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jadate1.rc
  • pm-jadate3.rc
  • pm-jadate4.rc

Call arguments (variables to set before calling)

(none)

Usage example

      INCLUDERC = $PMSRC/pm-jadate.rc
      #   now we have all date variables that we need
      #
      $TODAY    = $YYYY-$MM-$DD    


Pm-jadup.rc – Procmail: Handle duplicates; store to separate folder

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This recipe stores duplicate messages to separate folder

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jastore.rc

Call arguments (variables to set before calling)

  • JA_ID_CACHE, Where to keep the Message-Id cache.
  • JA_ID_CACHE_SIZE, how big cache, defualt is 8192
  • JA_ID_MBOX, where to store duplicate messages when delivering message to duplicate mbox.
  • JA_ID_IGNORE, if set to "yes", then ignore duplicate check

Return values

  • Variable ERROR is set to "yes" if duplicate message was trapped, otherwise value is "no"

Usage Example

For simple usage, just put this somewhere after backup recipes

          RC_DUP      = $PMSRC/pm-jadup.rc
          ...
          INCLUDERC   = $RC_DUP    

When you are testing messages, you send them over and over to procmailrc; which means that same message should not be trapped by
duplicate check. You can call procmail with option "-a test" which will set pseudo variable $1. The recipe below sets flag JA_ID_IGNORE to "yes" if test is on going and the duplicate filter should be bypassed.

      RC_DUP  = $PMSRC/pm-jadup.rc
      ARG     = $1        # Copy pseudo variable to $ARG

      :0
      * ARG ?? test
      {
          JA_ID_IGNORE = "yes"
      }

      #   Some microsoft product is known to send same message ids
      #   over and over. If we detect one, tunr off the duplicate test,
      #   because it would trash every message.
      #   <MAPI.Id.0016.00666479202020203030303430303034@MAPI.to.RFC822>

      :0
      * ! ^X-msmail
      * ! ^Message-ID: *<em>MAPI.*@MAPI.to.RFC822</em>
      {
          JA_ID_IGNORE = "yes"
      }

      #   Run this command every time a duplicate message is found.
      #   It writes a small log entry to MY_LOG

      INCLUDERC    = $RC_DUP

      :0 hwic:
      * ERROR ?? yes
      | echo "    [duplicate]" >> $BIFF    


Pm-jaempty.rc – check if message body is empty

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This simple includerc will define variable BODY_EMPTY to "yes" or "no" when called like this You can file empty messages to separate folder based on this value

      INCLUDERC = $PMSRC/pm-jaempty.rc

      :0
      * BODY_EMPTY ?? yes
      the-empty-mail-folder    

This is more designed to be part of other modules. If you just want to check for empty message, a simpler recipe like this might be better:

      INCLUDERC = $PMSRC/pm-javar.rc

      :0 B:         # if body has only whitespace characters
      *$ ! $NSPC
      the-empty-mail-folder    

Required settings

(none)


Pm-jafrom.rc – get message's best FROM field without calling `formail'

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc extracts the most likely FROM address from the message. The order of the search is Reply-to, From_, Sender, From and if none found, then as a last resort, call formail. You would usually use the returned value for logging purposes.

Avoiding extra formail call could be usefull if you receive lot of messages per day.

Example input

      (none)    

Returned values

      OUTPUT, containing the derived FROM field    

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. You nee procmail 3.11pre7 in order to use this subroutine. (due to formail -z switch)

Call arguments (variables to set before calling)

(none)

Usage example

INCLUDERC = $PMSRC/pm-jafrom.rc FROM = $OUTPUT # now we have the 'best' FROM field


Pm-jafwd.rc – Controlling forwarding remotedly

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Overview of features

  • Requires latest procmail (formail -z switch)
  • You can send forward-on and forward-off control messages via email to control the forwarding in remote site.

Description

This includerc makes it possible to control your message forwarding via simple remote email message. Thanks to Era Eriksson and Timothy J Luoma who gave the initial idea to this forwarding module in the procmail mailing list 1997-10-07.

Activating the forwarding by hand

If you want to activate the forwarding from the local site where this module is, then you could simply write the forward address to the file pointed by JA_FWD_FILE which is ~/.forward-address by default.

      % echo Me@somewhere.com > ~/.forward-address    

and when you no longer need forwarding, then remove that file. But really, this module is not used for that purpose, because it is lot easier to write

      :0
      ! Me@somewhere.com    

as a first statement in your .procmailrc when you want to forward your mail to another account.

Activating the forwarding by remote email

Suppose you're on the road and suddenly realize that you want your mail forwarded to the current account, then you send following control message

      Subject: forward-on password new-address@bar.com
      To: my-account@bar.com
      From: onTheRoad@some.com    

That message is is enough to get the mail forwarded to the address new-address@bar.com This script will respond to address From that the current forwarding is now pointing to address "new-address@bar.com".

Deactivating forwarding by remote email

The message is very similar, but the Subject header says

      Subject: forward-off password    

And no other fields are checked. Not even Reply-To. In this case the confirmation message is sent directly back to From address.

Activating forwarding via body message

If for some reason you have no control over the headers of email, eg when you send GSM-Mail message from your phone to your account:

      EMAIL foo@bar.com FORWARD-ON PASSWORD new-address@bar.com    

The email message looks like this:

      From: GenEmail <em>sms@FooBar.net</em>
      Date: Thu Sep 17, 11:42am +0200
      To:   "'Foo.Bar'" foo@bar.com
      Subject: Message 03384874987

      FORWARD-ON PASSWORD new-address@bar.com    

Instead of looking at the Subject field, you can get this module to look at the first words in the body field. See variable JA_FWD_CONTROL_FIELD which you want to set to "body".

Restricting the control message aceptance

If you only have persistent accounts, then you should set the JA_FWD_FROM_MUST_MATCH to match those addresses that you have. The following setting says that only control messages sent from these addresses are accepted. Nobody else can't change your forwarding settings.

      JA_FWD_FROM_MUST_MATCH = ".*(acc1@a.com|acc2@b.com)"    

Hm, that's not a bullet proof, because someone may in theory forge the From address. You probably should also set this variable to point to accounts where the mail can be legally forwarded to. Then, even if the imposter forges the From address; he can't get the email forwarded anywhere else than to the valid locations.

      JA_FWD_TO_MUST_MATCH = $JA_FWD_FROM_MUST_MATCH    

Consider also setting JA_FWD_PASSWORD_CASE to Procmail flag D which causes your control word "forward-on" and password to be case sensitive.

Diagnostics

If you don't receive confirmation message, then your control message was ill formed or you're not in the JA_FWD_FROM_MUST_MATCH list. There is no notification sent on failure, so that no attacker can draw conclusions.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc

Installation

You should preset all necessary variables prior adding the includerc command to your .procmailrc. Here is one simple setup

      #JA_FWD_SENDMAIL    = "tee $HOME/test.mail" # Uncomment if testing
      JA_FWD_COPY         = no    # no copies stored while forwarding
      JA_FWD_PASSWORD_CASE= "D"   # case sensitive
      JA_FWD_PASSWORD     = "MyMagicString"
      JA_FWD_FROM         = $FROM # This is already known.
      INCLUDERC           = $PMSRC/pm-jafwd.rc    

Comments from the author

Please realise that when you set the forwarding from a remote site, be very carefull when you type in the forward address or your mail ends up to somebody else's mailbox. Also I recommend that you keep JA_FWD_COPY to yes so that your local account always keep the copy of forwarded message.

A step further would conventionally encrypt(1)'ing your forwarded messages. This way even your top secret messages would be mostly safe even if they end up to someone else's mailbox.

File layout

tinybm.el/&tags and tinytab.el for the 4 tab text placement.


Pm-jalist.rc – Subroutine to detect mailing LIST from message.

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine tries to detect and derive the mailing list name as it appears in some of the known methods that ezlm, smarlist, listserv, majordomo etc. normally use. After this subroutine has been applied to message the variable LIST contains the mailing list name. Subroutine adaptively finds new new mailing lists from the messages.

The alternative to subscribing to many mailing lists is to read them from web archives. Even better way is to use NNTP server at http://www.gmane.org which allows you to post as you would to a regular newsgroup. Consider using the NNTP interface and you may save you from receiving lot of messages that can already be found from Gmane's server.

Quick start

If you just want to jump in and use this module and you noteice that some list isn't trapped, please set

  • JA_LIST_HEADER_REGEXP to match the From: field

If you want to make some list more unique, like if name "Alert" was detected as a list name, please set

  • JA_LIST_MAKE_UNIQUE to match the list name, like "Alert". After that the list name will be converted to HOST-LIST format.

Sendmail plus type method for list subscription

If you can use sendmail type PLUS addressing capabilities, you may not be interested in this module, because you have an alternative way to handle mailing list messages. The extra information after "+" is available to procmail scripts via $ARG pseudo variable when procmail is the LDA. Let's suppose you want to subscribe to procmail mailing list and want to save all messages to folder list.procmail, then you'd subscribe with address:

      login+list.procmail@site.com    

If your email host doe snot provide the plus addressing then it the traditiona approach have been to add a piece of recipe to ~/.procmailrc to catch each list. But that's manual work for every list. When you use this subroutine, you no longer need to write separate mailing list recipes to your ~/.procmailrc every time you subscribe to a new mailing list. The detection of a new list will happen automatically.

What you need to know before using this module

There is lot of heuristics going on in this module and one thing that you must note:

      If 'To:' domain is same as `From/Sender:/Reply-to:' domain
      then it is considered a mailing list message.    

This causes certain messages to be treated as mailing list messages. The module can't possibly know that the following is not from mailing list, because it doesn't know "what is mailing list", only "how it probably looks like it". This is definitedly categorized as mailing list message, because From and even Reply-to has the same domain foo.bar.net as in To.

      To: support@foo.bar.net
      From: message@foo.bar.net
      Reply-to: support@foo.bar.net
      Subject: Vmail See message to Eric    

You must prevent checking messages like this by surrounding call to this subroutine with a check statement:

      #   Do not check these messages

      noList = "From.*(foo.bar.net|support.my.com)"

      :0
      *$ ! $noList
      {
          INCLUDERC = $RC_LIST
          # ... save messsag by examining variable LIST (which see)
      }    

Ask for help

If you find mailing lists that this subroutine does not detect, but which could have been detected by looking the headers in standard way, please send a email to maintainer. There may be cases where it is impossible to detect the mailing list and in those cases you just has to carve a new entry to your ~/.procmailrc. When you keep your procmail log running, you may see message

       *** potential list ***    

Which is an indication that some new recipe could be added to to this subroutine to detect that mailing list. If the message you received was from a mailing list, please send all the headers to the maintainer so that support can be added.

Further reading

You can search for mailing list that interests you at:

      http://www.lsoft.com/lists/listref.html    

Python based mailing list manager; the mailman:

      http://www.list.org/    

Code note: Errors-To

Bill Houle sent interesting headers which caused to add more heuristic than was feasible to solve the list detection. From the below headers it is practically impossible to derive the original list name. So, the list name is artificially constructed by combining Reply-To's LOGIN with Errors-To field's first host name

      Reply-To: news@doodle.foo.net
      Errors-To: bounced@doodle.foo.net    

The list name formed is "news-doodle". So, If you happen to see an odd name like this which doesn't remind the original list name, it may be due to poor headers that have no clue about the real name. No problem, check below how you would convert this name to better mailbox name.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will followign extra module, which must have been installed.

  • pm-javar.rc

Variable JA_LIST_FROM_TO_IGNORE

This is regexp of sender addresses to ignore so that the if To and From are identical, it is not considered a list messages. This is typical for system generated messages that take form:

      From: root@host (Cron Daemon)
      To: root@host    

Variable JA_LIST_SAVE

If set to "yes" then the list name information detected is saved to separate header. The LIST_DETECTED is the original grabbed word from the headers and the 'LIST' is the final name after possible list name conversions. According to RFC the X- can be user for user headers.

      X-List-Detected: $LIST_DETECTED mapped to $LIST    

Variable JA_LIST_KILL_POSTFIX

If grabbed LIST match this regexp at the end of list name, then the postfix match will be removed. It is traditional that many list names are like list1-info, list2-beta, list3-L and ut would be preferable to see names like list1, list2 and list3. The default value will ditch "-(info|beta|L)".

Variable JA_LIST_KILL_PREFIX

Just like the postfix variable. If this string is matched at the beginning of the LIST, it is removed.

Variable JA_LIST_DISREGARD_EMAIL

In some cases this list detection recipe "thinks" that the address picked is the list sender. You may have a dedicated address where all you mailing list mails arrive and you have named it like mailing-list@me.here.at, which will effectively trigger: Ah, you have -list in email address, so this message must be from mailing list name 'mailing'. Of course it is not and you have to disallow the heuristics to make such assumption by defining a regexp that rejects a possible choice. For the above example, you would define:

      JA_LIST_DISREGARD_EMAIL = "posting-list@me.here.at"    

If you have several such addresses, just add them to the variable separating with normal regular expression "|" OR statement.

Variable JA_LIST_HEADER_REGEXP

This is optional variable, which you can set to match regexp of the mailing list domain address if it slipped through the tests in this module. There are some lists that send messages that don't carry enough information in headers to determine their list status. If you narrow the group by setting JA_LIST_HEADER_REGEXP, then for example lists like these, that identify themselves only through two headers, can be found:

      Reply-To: dispatch-faq@cnet.com
      From: CNET Digital Dispatch <em>dispatch@cnet.com</em>    

For that list you would set

      JA_LIST_HEADER_REGEXP = "(@cnet\.com)"    

Don't worry. all the other list detection recipes has already been tried, so this is last test that are carried out and variable JA_LIST_HEADER_REGEXP helps eliminating possible mishist

You don't need set this variable to include all mailing list domains. Only to those ones that were not trapped. The default value for this is:

      "(amazon\.com|bookpool\.com)"    

Variable JA_LIST_MAKE_UNIQUE

If you're subscribed to many mailing lists, that simply tell that they are news or newsletter, it will be impossible to differiantiate A news from B news. This variable holds regular expression that, if matched, prepend the first host name to the beginning of list name, thus making the list unique:

      news@some.com       --> some-news
      news@here.com       --> here-news    

The default value matches lists that contain word news, but you may need to set this to more matches.

Variable JA_LIST_CONVERSION

Note: before using this feature, make sure your LINEBUF is big enough, say 4096 or otherwise the variable's content is truncated.

Many times the grabbed LIST name is not what you would like to use for your mailbox name. You want to make the name perhaps more shorter, more descriptive or categorize the messages according to hierarchy. Let's say that you have subscribed to following mailing lists:

      LIST            LIST name    Description of mailing list
      (as grabbed)    you want
      -------------------------------------------------------------
      jde             java.jde    Java Development Env
      java            java.lang   Java programming
      FLAMENCO        flamenco    Flamenco music
      tango-l         tango       Argentine Tango dancing
      tm-en-help      tm-en       Emacs TM mime package mailing list
      w3-beta         w3          Emacs WWW mailing list    

First, remember that the variable JA_LIST_KILL_POSTFIX is first applied, so the actual LIST appears as follows:

      jde, java, FLAMENCO, tango, tm-en, w3    

Ok, now we apply the conversion table by defining it as follows. The grabbed LIST name is first, then comes space(s), new name and terminating colon. Repeat this for each list you want to convert.

      LIST CONVERSION[,LIST CONVERSION ...]    

This gives us table below: notice that entries tango-l, w3-beta were not included, because the JA_LIST_KILL_POSTFIX already got rid of the postfixes. Also note how the uppercase match FLAMENCO is converted to more suitable lowercase mailbox name. After you have set up this variable you can start saving messages to folders.

      JA_LIST_CONVERSION = "\
      jde       java.jde,\
      java      java.lang,\
      FLAMENCO  flamenco,\
      "    

The list conversion is done with pure procmail means, so it is very fast. It also means that the conversion is limited to FROM-STRING TO-STRING syntax. No wild cards or regular expressions are allowed.

If you consider using an external process, like sed or perl to convert the grabbed list name to something else (when JA_LIST_CONVERSION method was not enough); think again. For each incoming mailing list message you launch external process. It is not unusual to receive 700 messages from various mailing lists a day, it can be imagined how much load any external process would add to the server. Use the grabbed mailing list name and JA_LIST_CONVERSION table if you care about system load.

If you have many mailing lists that use uppercase names, it may be tedious to add each mailing list name to JA_LIST_CONVERSION. Possible alternative is to use very efficient tr program to convert characters to lowercase. Again; think twice, because any extra process could be avoided if JA_LIST_CONVERSION was used.

      :0
      * ! LIST ?? ^^^^
      {
          :0 D            # still uppercase list name?
          * LIST ?? [A-Z]
          {
              LIST = `echo $LIST | tr A-Z a-z`
          }

          :0 :
          list.$LIST
      }    

List name is not always the same

One important thing to keep in mind is that when mailing list manager sends out list messages, the headers may change. This means that the list name grabbed previously changes too. This is unfortunate, but it sometimes happens. Let's see an example. I was previously receiving messages from Cygwin mailing list named gnu-win32

      To: <em>gnu-win32@cygnus.com</em>, "Foo Bar" foo@example.com    

However, one day that same list was grabbed under name "cygwin", due to new header

      Mailing-List: contact cygwin-help@sourceware.cygnus.com; run by ezmlm    
Now I had two list names that both should be going to the same mailbox. No worries, just add new entry to the translate table to convert the new list name to mailbox name:

      JA_LIST_CONVERSION = "\
      gnu-win32           cygwin32,\
      cygwin              cygwin32,\
      "    

Example: basic installation

Here is recipe to save all your mailing list to separate folders. If you subscribe to new lists or unsubscribe to lists, you don't need to change anything. The grabbed list name will appear in variable LIST

      RC_LIST = $PMSRC/pm-jalist.rc   # name the subroutine

      ...

      #   Handle all mailing lists with one subroutine and recipe
      #   following it. Set also JA_LIST_CONVERSION before
      #   calling this subroutine to cnvert the found list names.

      INCLUDERC = $RC_LIST
      imap      =                 # Kill var. Set to "/" to enable

      :0                          # if list name was grabbed
      * LIST ?? [a-z]
      {
          dummy = "Saving mailing list: $LIST"

          :0 w:
          ${imap+".INBOX."}list.$LIST$imap
      }    

What's that IMAP thing there, you may wonder. Normally procmail delivers to standard mailbox, so the name is something like '$MAILDIR/list.abc'. For IMAP, the delivery must happen using principle "one file, one message", so procmail must deliver to a directory. That's what the added $imap is there for. It is also customary that IMAP folders are prefixed with ".INBOX", so the actual name becomes $MAILDIR/.INBOX.list.abc. For IMAP there should also be proper MAILDIR=$HOME/Maildir setting.


Pm-jamime-decode.rc – decode MIME body contents; quoted-printable, base64

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Documentation

The original father of the decoding scheme used here was presented by Peter Galbraith galbraith@mixing.qc.dfo.ca in procmail mailing list somewhere at the end of 1997.

This subroutine supposes that the header has MIME header Content-Type: text/plain and performs quoted-printable or base64 decoding on the whole message. Note, that if you receive messages that have many mime attachments, then this recipe is not suitable for it.

Procmail is not designed to handle mime attachments and this recipe only applies to whole body.

The pm-jamime-*.rc is really stretching the limits and any serious works hould be delegated to appropriate Perl MIME modules. There is a Perl MIME module which will allow you to manipulate MIME body parts rather elegantly. See http://www.perl.com/CPAN-local/authors/Eryq/ for MIME-tools.

Se also mimedecode at ftp://ftp.dde.dk/pub/mimedecode.c which in included in Debian Linux.

Notes

Perl or python is not used, because both are CPU intensive. It would be too expansive for accounts or environments receiving hundreds of mails per day (like from several mailing lists).

RFC 2047 gives possiblity to use MIME iso-8859-1 extensions for mail headers.

      Subject: Re: [PIC]: RSA =?iso-8859-1?Q?encryption=B7=B7?=
      Subject: =?iso-8859-1?Q?=5BEE=5D:TV_&_video_IC=B4s_!!?=    

There is also base64 possibility (although rare):

      Subject: =?iso-8859-1?B?zvLi5fI6ICAgICAgTVBMQUIzLjQw?=    

In worst possible case there is even multiple ISO encoded strings in subject. Yes, this is valid, the continued line includes spaces at front to keep it with original just like in Received: headers. This subroutine will not touch headers that have multiple ISO tags - procmail is too limited for that.

      Subject: AW: Re: AW: neue =3D?ISO-8859-1?Q?M=3DF6glichkeiten_=3D28was_=3D=C4hn?=3D
         =3D?ISO-8859-1?Q?lichkeiten_von_=3DDCbungen=3D29?=3D    

Required settings

Variable PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc, pm-jamime.rc
  • Programs $MIME_BIN, $MIME_BIN_QP and $MIME_BIN_64 must have been installed (see pm-javar.rc).

Call arguments (variables to set before calling)

  • JA_MIME_DECODE_TREAT_SUBJECT, default "yes". Decode Subject header by removing mime.
  • JA_MIME_DECODE_TREAT_FROM, default "no". Decode From header by removing mime.
  • JA_MIME_DECODE_TREAT_BODY, default "no". Decode body of message by removing quoted-printable from a message that contains only one part. Messages with multiple parts are not handled.

Return values

  • PM_JAMIME_COMPLEX_SUBJECT is set to "yes" if Subject header contains ISO encoding several times, it cannot be handled by this module. This flag is set to indicate that some other program shoudl handle the message.

Examples

Instead of testing the existence of text/plain in the body, you can force decoding by settings JA_MIME_DECODE_REGEXP to ".*".

      RC_MIME_DECODE = $PMSRC/pm-jamime-decode.rc

      :0
      * condition
      {
          JA_MIME_DECODE_REGEXP = ".*"
      }

      INCLUDERC = $RC_MIME_DECODE     # call subroutine.    


Pm-jamime-kill.rc – General MIME attachment killer (vcards, html)

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

Note: If you think this module can do miracles, it cannot. MIME messages are very complex in structure and all this module can do is to detect simple attachements. It cannot be used as - all purpose - all detecting - MIME attachement killer. But the part it can do, is done efficiently, because most of the things are accomplished using procmail and resource friendly awk.

There are meny programs that add additional information to the messages. Microsoft's mail program is one which may include a 7k application/ms-tnef attachment to the end of message. Many other programs may do the same. This was the idea in 1997 when this module was written; to get rid of the extra cruft which should not land in the mailbox.

This recipe works like this: If email's structure is

      --boundary
      message-text (maybe quoted-printable)
      --boundary
      some-unwanted-mime-attachment
      --boundary    

then the attachment is killed from the body. The message-text part is also decoded if it was quoted printable. This leaves clean text with no MIME anywhere. MIME headers have will be modified as needed due to conversion from multi part and possibly quoted printable to plain text and the final message looks like:

      message    

But if email's structure is anything else, like if there were 3 mime sections:

      --boundary
      message-text (maybe quoted-printable)
      --boundary
      some-attachment
      --boundary
      some-unwanted-mime-attachment
      --boundary    

then the "unwanted" part is emptyed by replacing with one empty line. The message structure stays the same, but the killed "some-unwanted-mime-attachment" part is labelled as text/plain so that the MUA (Mail User Agent; the email reader program) can decode the MIME message correctly.

Applications for other mime attachments

The following cases are ncluded on in this module. You need to separately the behavior before this module will start working.

  • Lotus Notes attachment.
  • Microsoft Express attachement. It sends a copy of message in HTML format.
  • Mozilla's Netscape attachement. It sends a copy of message in HTML.
  • Vcard attachments.
  • Openmail attachment. It sends 10-20 line base64 attachments WINMAIL.DAT.

Example of lotus notes attachment

      Subject: message
      From: foo@bar.com
      X-Lotus-FromDomain: XXX COMPANIES
      Mime-Version: 1.0
        Boundary="0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw"
      Content-Type: multipart/mixed;
        Boundary="0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw"

      --0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw
      Content-type: application/octet-stream;
          name="PIC10898.PCX"
      Content-transfer-encoding: base64

      eJ8+IjsQAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcA
      b3NvZnQgTWFpbC5Ob3RlADEIAQ2ABAACAAAAAgACAAEEkAYAyAEAAAEAAAAQ

      <AND-THE-REST-OF-BASE64>

      --0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw--    

Example of MS Explorer's ms-tnef message

      Subject: message
      From: foo@bar.com
      MIME-Version: 1.0
      Content-Type: multipart/mixed;
          boundary="---- =_NextPart_000_01BD04D4.A5AC6B00"
      Lines: 158

      ------ =_NextPart_000_01BD04D4.A5AC6B00
      Content-Type: text/plain; charset="iso-8859-1"
      Content-Transfer-Encoding: quoted-printable

      <MESSAGE ITSELF IS HERE>

      ------ =_NextPart_000_01BD04D4.A5AC6B00
      Content-Type: application/ms-tnef
      Content-Transfer-Encoding: base64

      eJ8+IjsQAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcA
      b3NvZnQgTWFpbC5Ob3RlADEIAQ2ABAACAAAAAgACAAEEkAYAyAEAAAEAAAAQ

      <AND-THE-REST-OF-BASE64>

      ------ =_NextPart_000_01BD04D4.A5AC6B00--    

Example of MS Express's HTML message

      MIME-Version: 1.0
      Content-Type: multipart/alternative;
          boundary="----=_NextPart_000_003A_01BD16E2.C97E27B0"
      X-Mailer: Microsoft Outlook Express 4.72.2106.4
      X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2106.4

      This is a multi-part message in MIME format.

      ------=_NextPart_000_003A_01BD16E2.C97E27B0
      Content-Type: text/plain;
          charset="iso-8859-1"
      Content-Transfer-Encoding: quoted-printable

      <ACTUAL TEXT>

      ------=_NextPart_000_003A_01BD16E2.C97E27B0
      Content-Type: text/html;
          charset="iso-8859-1"
      Content-Transfer-Encoding: quoted-printable

      <SAME IN HTML>
      ------=_NextPart_000_003A_01BD16E2.C97E27B0--    

Example of Netscape's HTML attachment

      X-Mailer: Mozilla 4.04 [en] (X11; U; Linux 2.0.33 i686)
      MIME-Version: 1.0
      Content-Type: multipart/alternative;
          boundary="------------69D9D579CF587DC8BB26C49C"


      --------------69D9D579CF587DC8BB26C49C
      Content-Type: text/plain; charset=us-ascii
      Content-Transfer-Encoding: 7bit

      <ACTUAL TEXT>

      --------------69D9D579CF587DC8BB26C49C
      Content-Type: text/html; charset=us-ascii
      Content-Transfer-Encoding: 7bit

      <SAME IN HTML>
      --------------69D9D579CF587DC8BB26C49C--    

Example of Netscape's vcard attachment.

      Content-Type: text/x-vcard; charset=us-ascii; name="vcard.vcf"
      Content-Transfer-Encoding: 7bit
      Content-Description: Card for Laird Nelson
      Content-Disposition: attachment; filename="vcard.vcf"

      begin:          vcard
      fn:             Laird Nelson
      n:              Nelson;Laird
      org:            Perot Systems Corporation
      email;internet: ljnelson@unix.amherst.edu
      title:          Software Engineer
      tel;work:       (617) 303-5059
      tel;fax:        (617) 303-5293
      tel;home:       (978) 741-3126
      note;quoted-printable:Information is for reference only;=0D=0A=
              please do not abuse it.
      x-mozilla-cpt:  ;0
      x-mozilla-html: TRUE
      version:        2.1
      end:            vcard    

Required settings

To handle base64 encoded messages, package called metamail must have been installed to system. It provides program mimencode which is used through variable $MIME_BIN (see pm-javar.rc).

Variable $PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jamime.rc

Call arguments (variables to set before calling)

First of all, this is primarily a framework recipe to kill any kind of attachment. If you do not set JA_MIME_TYPE before calling this recipe, recipe will try to determine the right value by itself. If the automatic detection fails you need to preset the value of JA_MIME_TYPE beforehand.

  • JA_MIME_TYPE is a case sensitive AWK REGEXP. Always use lowercase letters in this regexp because the line is lowercased before match is made. This regexp determines if the kill recipe is applied to the message or not. Value is set for MS explorer, MS express, Netscape and Lotus Notes etc. messages by default.
  • JA_MIME_KILL_RE, additional REGEXP to kill lines from the message. Value is case sensitive awk regexp and by default matches Lotus notes tag: name="XXX.PCX".
  • JA_MIME_EXTRA_HEADER, name of header added to the message if the MIME portion was killed. Default value is "X-Mime-Type-Killed".

It may be possible that some messages are malformed and that they do not contain proper "boundary" definition string in the header. There have been messages that have text/html attachments, but no proper Mime headers. For those cases there is additional variable that will kill all text up till matching line regardless of message content.

  • JA_MIME_KILL2_RE is set to "text/html|application/ms-tnef". Update this to match attchements you receive. Set variable to "" if you don't want to change the body of non-compliant MIME message.

That variable is the last resort if the standard MIME detection failed. There must have been some problem in the sender's MUA that composed message. It's dangerous, so make sure you don't set it lightly.

Possible conflict with your awk

If you see an error message in the log file saying that awk failed:

      procmail: Executing awk,
      ...
      procmail: Error while writing to "awk"
      procmail: Rescue of unfiltered data succeeded    

it means that the system's standard awk doesn't support the variable passing syntax. Do the following test:

      % awk '{print VAR; exit}' VAR="value" /etc/passwd    

It should print "value". If not, then see if you have nawk or gawk in the system. They should understand the variable passing syntax. The only change needed is to define variable AWK somewhere at the top of ~/.procmailrc.

      AWK = "gawk"        # Better than standard "awk"    

Warnings

You should know that the variable JA_MIME_KILL_RE is used to wipe any lines that match that regexp. This is due to MIME structure where continuing header lines exist in the body:

      ------=_NextPart_000_003A_01BD16E2.C97E27B0
      Content-Type: text/plain;
          charset="iso-8859-1"                << kill this line too    

If you want to be absolutely sure that anything valuable won't be accidentally killed (like a code line in programming language scripts), you should set this variable to nonsense value that newer matches:

      JA_MIME_KILL_RE = "match_it_never_I_hope"    

Usage example: Customizing the attachment killing

Suppose you receive new application/ms type attachment that the default settings doesn't cover. This is a new mime type and you have to instruct this module to kill it. Add this and similar tests for other mime types:

      myCustomMimeType = "application/ms"     # must be all lowercase

      :0
      *$ $myCustomMimeType
      {
          PM_JA_MIME_TYPE = $myCustomMimeType
      }

      INCLUDERC = $PMSRC/pm-jamime-kill.rc    

Usage example

To kill text/html or pdf, postscript and others add something like this to ~/.procmailrc. It demonstrates how the correct MIME types are detected:

      # .....................................................
      # 1) Uncomment following line if your standard "awk" is broken

      # AWK = "gawk"

      # .....................................................
      #  2) Set correct value for attachment killing

      :0
      * ^X-Lotus-FromDomain:
      {
          #  Kill Lotus notes .pcx attachments
          JA_MIME_TYPE = "application/octet-stream"
      }

      :0
      * H ?? ^From:.*foo@example.com
      * B ?? ^Content-Type:.*text/html
      {
          #   Kill html attachments
          JA_MIME_TYPE = "text/html"
      }

      # .....................................................
      #  3) Call module

      INCLUDERC = $PMSRC/pm-jamime-kill.rc    


Pm-jamime.rc – subroutine to read mime boundary etc. variables

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Documentation

This includerc reads MIME boundary string from the message if it exists. The boundary string is typically found from Content-Type header.

      Mime-Version: 1.0
      Content-Type: multipart/mixed; boundary=9i9nmIyA2yEADZbW    

In addition it will define few other mime variables. See the returned values. You use these variables later in your MIME message processing.

Mime Notes

1998-07-28 Brett Glass brett@lariat.org reported in PM-L that there was security exploit in long attachment filenames: http://www.xray.mpe.mpg.de/mailing-lists/procmail/1998-07/msg00248.html

And here is the url to the matter:

http://www.sjmercury.com/business/microsoft/docs/security0728.htm

When you use this module to detect mime messages, you can check the filename length with recipe:

      #  Recipe after calling $RC_MIME, this module,

      re       = ".........."     # regexp with 10 matches
      too_long = "$re$re$re$re"   # allow 40 characters maximum

      :0
      *$ $SUPREME^0  MIME_H_ATTACHMENT ?? $re
      *$ $SUPREME^0  MIME_B_ATTACHMENT ?? $re
      {
          dummy = "** Dangerously long mime attachment filename"
          dummy = "** $MIME_H_ATTACHMENT $MIME_B_ATTACHMENT"

          :0 :
          /var/spool/mail/MimeDanger
      }    

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc

Call arguments (variables to set before calling)

(none)

Return values

  • Variable MIME is set to "yes" or "no" if messages has mime version string
  • MIME_VER contains the mime version string from the header.
  • MIME_TYPE contains the Content-Type from the header.
  • MIME_CTE contains Content-Transfer-Encoding from the header.
  • MIME_H_QP is "yes" if Content-Transfer-Encoding: quoted-printable is in the header.
  • MIME_B_QP is "yes" if Content-Transfer-Encoding: quoted-printable is found from the body.
  • MIME_BOUNDARY contains the boundary string, which is used to differentiate mime sections in the body.
  • MIME_BOUNDARY_COUNT is the number of boundary strings found from the body. The value is 3 if there is two mime sections, and 4 if 3 etc. MIME_BOUNDARY_COUNT -1 = count of sections.
  • MIME_H_ATTACHMENT, contains the filename if there was attachement filename in the header. Content-Disposition: attachment; filename="..."
  • MIME_B_ATTACHMENT. body file attachment. Note however that this is the match of first string in the body. There may be several attachments. MIME_B_ATTACHMENT_FILE_COUNT tells you how many filenames are in the body.

Usage example

INCLUDERC = $PMSRC/pm-jamime.rc


Pm-jamime-recode.rc – re-encode MIME Header: Subject, From as quoted-printable

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Documentation

This subroutine supposes that message has been handled by 'pm-jamime-decode.rc'. The purpose is to restore Subject and From headers back to quoted printable format so that messages can be savely saved through IMAP system which may not handle 8-bit messages. If message is stored directly to mailbox and the used Mail user Agent has no problems with dealing 8-bit characters, this module is not needed.

An example where this subroutine could be applied:

  • Feed message to pm-jamime-decode.rc
  • Feed message pm-jasubject.rc (to clean multiple Re: Re: Fwd ..)
  • Restore From/Subject encodings with pm-jamime-recode.rc
  • Save message to mailbox

Notes

Perl or python is not used, because both are CPU intensive. It would be too expansive for accounts or environments receiving hundreds of mails per day (like from several mailing lists).

Required settings

Variable PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jamime.rc
  • Program $MIME_BIN_QP_E must have been installed (see pm-javar.rc).
  • pm-jamine-decode.rc must have been called and message must contain headers X-Mime-Header-Decoded-*

Call arguments (variables to set before calling)

  • JA_MIME_RECODE_TREAT_SUBJECT, default "yes". Decode Subject header by removing mime.
  • JA_MIME_RECODE_TREAT_FROM, default "no". Decode From header by removing mime.

Return values

(none)

Examples

To fix Subject header and then make it 7bit clean again. Note, this may not be exactly what you want. The pm-jamime-decode.rc file does a little more than From/Header handling (also modifies message body). Read documentation of each file before using following example

      INCLUDERC = $PMSRC/pm-jasubject.rc
      INCLUDERC = $PMSRC/pm-jamime-decode.rc
      INCLUDERC = $PMSRC/pm-jamime-recode.rc    


Pm-jamime-save.rc – save message's MIME attachement (one file) to a file

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Documentation

This module saves one simple file attachment (MIME) from he message. The message must define following MIME headers. If "filename=" does not exists, then the message is ignored.

      Mime-Version: <version>
      Content-Type: <type>
      Content-Disposition: attachment; filename="file.txt"    

The last line can also be in separate line, provided that it is indented according to standard rules:

      Mime-Version: <version>
      Content-Type: <type>
      Content-Disposition: attachment;
          filename="file.txt"    

Procmail is not very suitable for saving MIME attachments and you should not think that this the right tool for you. If you receive anything more than 1 attachment, this recipe does nothing, because that's out of our league and you need some more heavy weight mime tools. E.g. Perl CPAN has MIME libraries.

Note: when the attachment is in the body, it is simply written to a disk and the location in message is replaced with test:

      Extracted to file:/users/foo/junk/<YYYY-MM-DD-hhmm>.file.txt.    

The existing mime headers that surround the attachment are lect untouched, so don't try to press your Mail Agent's MIME buttons at that point. There is no such file in that spot if you set JA_MIME_SAVE_DEL to yes.

Required settings

PMSRC must point to source directory of procmail code. This subroutine includes library:

  • pm-javar.rc
  • pm-jamime.rc
  • pm-jamime-decode.rc
  • pm-jadate.rc (which will call other pm-jadate*.rc files)

Call arguments (variables to set before calling)

  • JA_MIME_SAVE_DIR, point this to directory where you want to store attachments.
  • JA_MIME_SAVE_DECODE, set this to "yes", if you want that attachment is decoded before written to disk. This usually opens quoted printable or base64 encoding.
  • JA_MIME_SAVE_DEL, set this to "yes", if you want to remove the attachment from the body of the message after it has been filed. Be vary careful if you use this option. If you keep backup cache of incoming mail, then you might try "yes".
  • JA_MIME_SAVE_OVERWRITE, set this to "yes" if it's okay to overwrite to an existing filename found from attachment. If you get periodic attachments always with same name, then you would want to set this to yes.

Core dump note

Because procmail uses LINEBUF when filtering messages, a core dump may happen if the attachment being filtered is bigger than the LINEBUF. The current setting accepts 524K attachments, but if you expect to get bigger than that, you want to increase JA_MIME_SAVE_LINEBUF.

Possible conflict with your awk

Awk is used because it is much more system load friendly than perl. If you see an error message in the log file saying that awk failed:

      procmail: Executing awk,
      ...
      procmail: Error while writing to "awk"
      procmail: Rescue of unfiltered data succeeded    

it means that the system's standard awk doesn't support the variable passing syntax. To verify that this is the case, run following test:

      % awk '{print VAR; exit}' VAR="value" /etc/passwd    

The proper awk should print "value". If not, then see if you have nawk or gawk in your system, which should understand the variable passing syntax. To change the AWK, you need to set following variable somewhere at the top of your .procmailrc

      AWK = "gawk"        # if that works better than standard "awk"    

Return values (none)


Pm-janetmind.rc – handle http://minder.netmind.com/ messages

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

** THIS MODULE IS OBSOLETE. THE NETMIND SERVICE NO LONGER EXISTS **

http://minder.netmind.com/

...Netmind, or The URL-minder is a free, automatic Web-surfing robot that keeps track of changes to Web pages that are important to you. When the URL-minder detects changes in any of the Web pages you have registered, it sends you e-mail. an effective way to test if the address is known to Internet. You could use this information to see if some automated reply to a address can be sent.

In another words, if you're interested in some URL; say an FAQ page and any updates to them, you can tell Netmind to monitor the page changes for you and it send a message back every time page changes.

This recipe "pretty formats" the announcement sent by Netmind by stripping the message to bare minimum. You usually aren't interested in 4k message which includes "Note from our sponsors", "Try the free online demo" etc. The things saved from the announcement message are:

  • The changed url, which is moved to subject
  • Cancellation url pointer
  • url to the lists of your monitored urls
  • your id number

[Note]

Please let Netmind send you one "pure" message first so that you have a huch what it originally looks like. Then plug int his module and see how the original message is reduced.

[Thank you]

The Doctor What docwhat@holtje-christian-isdn.mis.tandem.com 1998-03-12 send me a patch, where a)body message is more informative b) URL is now included in the body for auto-click browsers c) mime headers were removed.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • If you se variable JA_NETMIND_SUBJECT to "yes", then the changed url http pointer is put to subject line.

Usage example

      INCLUDERC = $PMSRC/pm-janetmind.rc          # reformat the message

      :0:                                         # drop to folder
      * netmind
      url.mbox    


Pm-janslookup.rc – run nslookup on variable INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine runs nslookup on given INPUT address. This may be an effective way to test if the address is known to Internet. You could use this information to determine if some automated reply to a address can be sent. The know truth is that you can't validate whole email address

          to_someone@foo.com    

but you can validate "foo.com"; that's the closest you get.

[Warning: If you don't use cache feature...]

Do not however use this module to regularly check all incoming from addresses with this subroutine for possible bogus UBE addresses, because calling nslookup

  • may be slow, building to connection and querying the results may take several seconds. (some times, usually it's quote fast)
  • consumes quite a lot resources.

You can however check some messages that are likely UBE to verify your doubts.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jaaddr.rc

Call arguments (variables to set before calling)

  • INPUT, the address (only strict domain part) which is checked. Eg. "this.domain.com". See examples for more. If this string contains "@" character, then additional subroutine pm-jaaddr.rc is called to extraxt the domain name INPUT = "John Doe foo@site.com" --> INPUT = "site.com"
  • JA_NSLOOKUP_CACHE, filename. If exists, cache is used and updated.
  • JA_NSLOOKUP_FORCE, if "yes", then cache is not used but a forced nslookup is performed.
  • JA_NSLOOKUP_OPT, is currently empty, but you could see if you you want to use "-querytype=MX". However this option may give you response: "No mail exchanger (MX) records available", which is flagged as nslookup failure.
  • JA_NSLOOKUP_SERVER, optional, the server to user for nslookup

If the cache file can be read:

  • Each entry has format "address.com ns-error". The error indication is added to the line if the nslookup failed when address was checked. Otherwise line contains "address.com".
  • The cache is always checked first. If there is no entry matching the current address, only then is nslookup called and new entry added to cache.

Return values

  • Variable ERROR will be set to "yes" if nslookup failed or to "no" if nslookup succeeded. It can also contain "maybe" if nslookup returned "No address (A) records available"
  • ERROR_MATCH contains one line lookup failure reason.

Following conditions trigger "maybe" and no "ns-error" is written into the cache.

  • "No address (A) records available for xxx"

Usage example

If you are going to check some header field, like From:, please explode the content with pm-jaaddr.rc first. Suppose you have string:

      "From: foo@ingrid.sps.mot.com (Yoshiaki foo)"    

You have to derive the address from string and pass the site name: Read From: field and address from it.

      PMSRC       = $HOME/pm
      RC_NSLOOKUP = $PMSRC/pm-janslookup.rc   # name the subroutine

      :0
      * MAYBE_UBE ?? yes
      * ^From:\/.*
      {
          INPUT       = $MATCH
          INCLUDERC   = $RC_NSLOOKUP  #   to nslookup

          :0
          * ERROR ?? yes
          {
              #   Hm, nslookup failed, can't send anything back to this
              #   address
          }
      }    

Second example, check if the address is reachable before sending reply

      INPUT       = `$FORMAIL -rt -x To:`
      INCLUDERC   = $RC_NSLOOKUP

      :0
      *    ERROR ?? no
      {
          # okay, at least site address seems to be reachable
      }    


Pm-jaorig.rc – Extract embedded original message (simple recipe)

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Documentation

This subroutine digs embedded message from the body and replaces current message with it. Copy the message to folder before calling this subroutine if you need original.

NOTE: This is simple tool and the sole purpose is to derive simple embedded messages. Write full fledged perl script if you want better extracting features. The used AWK inside this procmail recipe will fail to find 30% of the cases, mostly due to non-standard way of including the message. The recognized formats are as follows. Anything that differs from these are ignored or incorrectly parsed.

  • Message is embedded left flushed "as is". With full headers or Minimum of From: Subject Received
  • The embedded message is quoted with > with optional one space.

Where you would use this module

If you're subscribed to mailing lists that regularly sent copies of original message to the list, like forwarding spam to SPAM-L mailing list at http://bounce.to/dmuth, then you'd like to extract the original embedded message which you can then feed to your UBE filter to test if the shield holds.

      <em>spam-l-request@peach.ease.lsoft.com</em>
      subscribe SPAM-L <First name> <Last name>    

This recipe takes simplistic approach and tries it's best to extract embedded message. Idea for this recipe comes from Era Eriksson's posting "recipe to turn list postings back into original spam" 1998-06-25 in Procmail mailing list.

  • Body must contain headers
  • Remove all > quotations.
  • extract everything to the end of message. (There are no means to get rid of the attached signatures that ot forwarding poster or list server may have attached.

How the message is extracted

When this recipe ends, the current message has been modified so that it is the original message. Like if you would receive:

      HEADER-1        # The poster
      body-1          # his comments
      HEADER-2        # The original embedded message
      body-2
      body-1          # And poster's signature or mailing list footer    

The message now looks like

      HEADER-2
      body-2
      body-1    

And you can save this as original message or feed it to your UBE filter and test if it detects it.

Code note: procmail or awk core dump

For some reason procmail kept dumping core I write the code in more nicer format like below, but if I made it compact, then it didn't dump core. Go figure. I'm not pleased that I had to sacrafice clarity, but there was no other way.

      [The good style]            [The forced compact style]
      if ()                       if () { statement }
      {
          statement
      }    

I have no explanation why this happens, the same AWK code would work just fine most of the cases and then came this message x and caused dumping the code, if I feed some other message, I didn't get core dump. Total mystery to me. Don't let the log message fool you, this had nothing to do regexp "^[> ]*From:.*[a-zA-Z]". If I deletd one line from AWK script, it worked ok, if I added it back the core dump happened with that message x

      procmail: Assigning "pfx=[> ]*"
      procmail: No match on "^[> ]*From:.*[a-zA-Z]"
      Segmentation fault (core dumped)    

Required settings

PMSRC must point to source directory of procmail includerc code. This subroutine needs module(s):

  • pm-javar.rc

Call arguments (variables to set before calling)

(none)

Usage Example

Let's assume that you want to feed all forwarded UBE that is posted to spam-l mailing list to your filter and see if it needs improving by checking the logs later. The forwarded UBE to the list is labelled "SPAM:" in the subject line.

      $RC_LIST = $PMSRC/pm-jalist.rc   # mailing list detector
      $RC_ORIG = $PMSRC/pm-jaorig.rc   # extract original
      $RC_UBE  = $PMSRC/pm-jaube.rc    # UBE filter

      ...

      INCLUDERC = $RC_LIST            # defines variable `LIST'

      :0
      * ! LIST ^^^^
      {
          :0                          # spam-l mailing list
          * LIST ?? spam
          * Subject: +SPAM:
          {
              INCLUDERC = $RC_ORIG    # Change it to UBE message

              #   Ok, next feed it to filter, set some variables first
              #   Log = Short log; What filters were applied to message
              #   mbx = If message was trapped, save it here

              JA_UBE_LOG      = "$PMSRC/pm-ube.log"
              JA_UBE_MBOX     = "junk.ube.ok.mbox"

              INCLUDERC = $RC_UBE

              :0 :            # If comes here, filter failed
              junk.ube.nok.mbx
          }

          :0 :                    # save normal list messages
          list.$LIST
      }    


Pm-japing.rc – reply shortly to message "Subject: ping"; account ok

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

When I'm on remote site and I don't seem to get throught with telnet or even with Unix ping(1), I want to know if the at least the mail server is up. I can send a ping message and the auto responder will reply immediately.

Sometimes, when you send a message to a person, it would be nice, if you could test that the destination address is valid, before sending a message to a black hole. If the receiver had ping service running; like this, then you would know that you spelled the the right address. (after wondering two weeks; why you don't get response). Nowadays finger(1) command seems to be blocked many times.

This recipe answers to simple ping message like this:

      To: you@site.com
      Subject: ping    

Recipe sends a short message back to the sender.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jastore.rc

Call arguments (variables to set before calling)

(see Usage)

Usage example

      JA_PING_MBOX    = $HOME/Mail/spool/ping.spool
      INCLUDERC       = $PMSRC/pm-japing.rc    


Pm-japop3.rc – Remotedly download messages by mail command request

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

Ahem, that pop3 is just to draw your attention. This module has nothing to do with pop3. The idea may resemble it though. This module listens pop3 requests, and when it gets one, it sends the whole mailbox content as separate forwarded messages to the account from where you sent the request.

This is kinda "empty my mailbox in account X and send the messages to account Y"

You might have permanent forwarding on in account X, but if that is your secondary account, you can ask what messages has been arrived there with this recipe.

After you have configured your magic pop3 command, which is your password, simply send a message to account X, and this module initiates emptying the mailbox. Here is an example:

      Subject: pOp3-send [mailbox] [kill]    

  • mailbox, is optional folder name which you want to process. it is $DEFAULT if not given in subject. Use absolute path if you specify one.
  • if word kill is found, the mailbox will be emptied after forwarding. If the word is not found, messages are preserved.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-japop3.rc # Phew! We include ourself, we are recursive.

Call arguments (variables to set before calling)

  • JA_POP3_SUBJECT_CMD is your personal access command string. If this is the first word in the subject line, forwarding starts. This string is case sensitive.
  • JA_POP3_TMP is the file where mailbox is moved before starting to forward the messages. Do not put to point to your $HOME, becaus that may exceed the quota.
  • JA_POP3_TO_MUST_MATCH must contain regexp that match the email addresses where the pop3 messages are allowed to send. BE SURE TO DEFINE this. If you have account X,Y,Z where you want to receive pop3 messages, set this regexp to match those site's email addresses.
  • JA_POP3_LOGFILE is the log where you can see how the forked procmail processes send each pop3 mail. You may want to set this to different location than your default $LOGFILE.

Return value

STATUS will contain mailbox name if valid pop3 request was received. You may wish to save the pop3 requests to separate folder. See example below.

Example usage

You install this same setup for each site where you have account. This is the account X, from where you want to empty the mailboxes.

      RC_POP3             = $PMSRC/pm-japop3.rc

      .. somewhere in your .procmailrc ..

      JA_POP3_SUBJECT_CMD = myPoPcmd
      INCLUDERC           = $RC_POP3

      #   Save all pop3 requests to folder

      :0 :
      * STATUS ?? [a-z]
      mail.pop3-req.mbox    

In account Y, from where you send the pop3 requests. Following code stores

The received messages to separate folder

      #   The MATCH will contain the host name from where the messages
      #   were moved

      :0 :
      *$ X-Loop-Fwd:.*\.rc +\/$NSPC+
      mail.fwd.$MATCH.mbox    


Pm-jarandf.rc – pick (rand)om line from (f)ile

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

Return random line or a line from a file. This subroutine uses shell command awk and possibly wc to be as small burden to the system as possible.

Required settings

You must have awk that supports VAR=value assignment syntax outside the code block: that is, in the input line. I know no awk that would not have this feature, but at least you know now what it takes.

      % awk '{print VAR; exit;}' VAR=1 /etc/passwd    

Try using GNU awk, if your standard awk didn't print 1 in above test. (Put this line to the top of your .procmailrc)

      AWK = "gawk"    

Call arguments (variables to set before calling)

If intend to call this subroutine many times, then please calculate the number of lines beforehand and pass it to this subroutine. If the MAX is not set, then wc is called every time to find your the line count.

  • FILE, from what file to select. Make sure this exists; existence is not checked here.
  • [MAX] optional, number of lines in the FILE.

Returned value

variable LINE

Example usage

      # Select random line from a file

      $RC_RANDF = $PMSRC/pm-jarand.rc
      $COOKIE   = $HOME/txt/cookie.lst

      ...somewhere..
      MAX=20 FILE=$COOKIE    INCLUDERC=$RC_RANDF

      #  LINE contains randomly read line    


Pm-jasrv-check.rc – check FILE validity, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of the TPFS or MPFS file server. Check FILE for nonvalid filenames or other access problems.

Input

  • JA_SRV_F_FILE_CASE_SENSITIVE, flag
  • FILE, filename to check. possibly converted to lowercase.

Output

  • stat, set to "ok" if filename is acceptable. Otherwise contains brief error reason;

Pm-jasrv-daemon.rc – server request check, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of the MPFS file server. Handle BOUNCES to mail server messages, eg if delivery failed due to maximum byte limit.

      552 foo@site.com... Message is too large; 100000 bytes max    

Input

(none) This recipe examines headers and body to see if it's daemon bounce.

Output

  • stat, set to "daemon" if message was handled.

Pm-jasrv-err.rc – send message, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This module is part of the MPFS file server. Ssnd error notice: file didn't exist.

Input

  • FILE, file or command that did ot exist.

Output

  • fld, additional field to be added to the saved mbox log message

Pm-jasrv-from.rc – compose reply, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of the MPFS file server. Compose headers for reply message using formail -rt.

Here is dry run example to test this module

      % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all         \
          FORMAIL=/opt/local/bin/formail                              \
          JA_SRV_FORMAIL_FROM=me@here                                 \
          JA_SRV_CONTENT_TYPE=content-type                            \
          JA_SRV_XLOOP=xloop                                          \
          $HOME/pm/pm-jasrv-from.rc                                   \
          < $HOME/any-sample.email    

Input

  • JA_SRV_FORMAIL_FROM, JA_SRV_XLOOP
  • JA_SRV_CONTENT_TYPE

Output

(none)


Pm-jasrv-msg.rc – send message, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of the TPFS or MPFS file server. Run $CODE and return resutls to to user. Subroutine is meant to be used for informational messages.

Input

  • code, code to run in shell
  • stat, status message for user

Pm-jasrv-multi.rc – send multipart MIME message, subroutine for FileSrv

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of MPFS file server. Send out FILE as multipart MIME message. The message will always be base64 encoded before sending.

Input

  • JA_SRV_MIME_MULTI_SEND, command to feed the composed and message which will handle sending it as multipart MIME.
  • JA_SRV_MULTIPART_THRESHOLD is the hunk size for slitting mail.
  • FILE, only filename part. Included in MIME headers.
  • file, absolute path to send

Pm-jasrv.rc – MIME capable Procmail File server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This is the MPFS (Mime Procmail File Server) and it can send MIME compliant messages with command

      "send <ITEM> [WORD1] [WORD2]"    

Usually only the ITEM arg is used, and the rest of the words are for special uses like password and preventing file encoding. A typical request looks like:

      Subject: send help              # ask for file named 'help'    

Overview of features

  • MIME types gzip and text/plain are supported.
  • .gz .zip etc. files are sent out as base64 attachments
  • .gz .tar.gz files that exceed 100K are sent out as MIME multiparts
  • requires procmail 3.11+ and MATCH operator \/
  • requires mmencode and gzip executables to be present in PATH.

Install: server file directory

You have to create a directory for the server where the files are kept. Usually I don't put the files there, but whenever I want to make a file available, I draw a hard or softlink to the real file.

      % mkdir $HOME/pm-server

      # Repeat this as needed for files you want to put available

      % cd $HOME/pm-server
      % ln -s $HOME/txt/interesting-file.txt interesting-file.txt    

You define the server directory by setting

      JA_SRV_FILE_DIR = $HOME/pm-server    

The short server log is written to file pointed by this variable:

      JA_SRV_LOG = $HOME/pm-server.log    

The incoming "send" requests are stored to mailbox pointed by following variable. The default value is /dev/null, but you may want to set it to ~/Mail/spool/log.srv.spool which can be used read as a newsgroup by Emacs Gnus [In Gnus create newsgroup with `G` m nnml log.srv]

      JA_SRV_MSG_MBOX    

Install: special files

Tweak this variable to commands you want to allow shell to execute in server's directory. This tells when <ITEM> "ls" means command instead of file

      JA_SRV_SH_COMMAND = "^(ls|what)$"    

That means that request like this:

      Subject: send ls            # run "ls" command and return results    

Be sure that the commands exist in your system. See man pages for more if you want to know what these commands do. Commands cannot take switches currently for security reasons. E.g. if you want to give access to "ls -la" listing, put a file "ls-la.txt" available in the directory, user can get it with "send ls-la.txt"

      ls      -- list directory
      file    -- print file type information.
      what    -- prints all @(#) tags from files
      ident   -- print all $ $ tags from files    

Install: file `help'

Users want to get a help file with message "send help" and the help is just a file in your server directory. Be sure to supply it prior to any other files. You can always draw a link to a file if you don't want to name it that way (e.g. if you keep several server help files in a RCS tree)

      #   draw symlink to `help'

      % ln -s $HOME/txt/srv-public-hlp.txt $HOME/server/help    

Basic usage in details

The server accepts command in format

      "send <ITEM> [CMD|PASSWORD]"    

Where ITEM can be any name as long as it starts with [^ .]. The regexp says: Anything goes as long as FILE does not start with space or period. This gives you quite a much freedom to construct filenames. if you want to hand out file:

      .procmailrc    

You can't. Instead make a link to point to plain "procmailrc" without the leading period. There is also additional checks against possible security threat "../" like below; user can't request such file.

      ../../../gotcha  or  dir/../../gotcha    

The filename cannot contain special characters like [*?<>{}()].

Advanced usage

[conversions]

If some of your files are big, it makes sense to send them in compressed base64 format; which in MIME world is called content-type gzip. You can set a regexp to enforce encoding for your big files before they are sent to user. The following setting will send all text files in compressed format to user.

      JA_SRV_XGZIP_REGEXP = "\.txt"    

When the message is composed a header is inserted into the message telling how the message is to be decoded, in case user doesn't have decent MUA that can handle the MIME type:

      X-comment: To decode, cat msg| mmencode -u| gzip -d > test.txt    

[noconv and gz]

The WORD1 parameter after the FILE is optional and user can override base64 encoding and request plain file if he uses word "noconv".

      Subject: send <FILE> [noconv|gzip]    

However, there are files where noconv must not be obeyed, like the compressed packages that you have put available in .zip, .gz, tar.gz or .tgz (GNU tar) format. Following variable controls
when file is always sent as base64:

      JA_SRV_BASE64_ALWAYS    

If the WORD1 is "gz" or "gzip", then the gzip is explicitly requested, This may be desirable, because some of the text files in the server directory may be big and some accounts don't accept big messages. A typical bounce looks like:

      552 foo@site.com... Message is too large; 100000 bytes max
      554 foo@site.com Service unavailable    

These kind of file server bounce messages are handled in separate module which notifies the user that his account didn't accept the sent file.

[case sensitivity]

By default the request word ("send") and ITEM (filename) are not case sensitive, unless you set these flags:

      JA_SRV_F_CMD_CASE_SENSITIVE  = "yes"
      JA_SRV_F_FILE_CASE_SENSITIVE = "yes"    

If values are "no", then these are identical commands:

      Subject: Send Help
      Subject  SEND HELP    

Multi part mime messages

If you want to deliver big files, you better be sure not to send them as a big file. That blocks the connection between every host along the path that the big file is transferred. The solution is to use MIME multi parts that can be assembled back in the receiving MUA. (In case you don't have multi part assembler receive Perl script to do it).

MIME multiparts are sent out if

  • Filename matches JA_SRV_BASE64_ALWAYS, typically tar.gz, zip
  • Filesize is bigger than JA_SRV_MULTIPART_THRESHOLD, where default chunk size is 100K.

When a file meets these criteria, it is read to the BODY of message and base64 encoded. This all happens in memory, so watch procmail logs to see if any problems with very big files. (>30Meg). Next, if the base64 conversion succeeded, the composed is handed to

      JA_SRV_MIME_MULTI_SEND    

Which does the actual delivery and splitting. The default program used is splitmail. Make sure you have it or substitute the program with some equivalent one.

Stopping server

Sometimes you're making rearrangements in you file directory or doing some other maintenance and you are unable to respond to send requests. You can stop the server by setting

      JA_SRV_IN_USE = "no"    

And when you want to enable the server again; just comment out the statement or assign yes. [The default is yes]. When this variable is set to no, the server sends a message from following variable as a response to any "send" request.

      JA_SRV_IN_USE_NO_MSG    

Using password to validate file requests

You should be aware that this file server's implementation is public in nature. Anyone who asks for a file is allowed to get it. But it would be good if you could limit the access to documents with some simple way, like if you set up two file servers (see next chapter) where one is public and the other is interesting only to group of people. You can define a string that must be found in Subject field by setting the following variable

      JA_SRV_PASSWORD = ".*"    # default    

The default value will match anything in the subject, thus making the server public. But if you set it like this

      JA_SRV_PASSWORD ".*123"    

Then string "123" must be there somewhere in the line, like here

      Subject: send <FILE> 123    

Yes, "123" is actually a CMD definition, but it doesn't matter because there is no CMD 123. Subject now matches password and the server can be accessed. Of course the following is valid too.

      Subject: send <FILE> noconv 123    

If the password was wrong, server won't tell it. The message just lands to your mailbox in that case and you can investigate who tried to access the restricted server.

Changing server's command string (multiple servers)

The default command string is "send", but you can change it and thus create multiple services. Here is one example, where you have set up two file servers where each has its own directory.

      #   The public server

      JA_SRV_CMD_STRING           = "send"
      JA_SRV_FILE_DIR             = $HOME/server/public
      INCLUDERC                   = $HOME/procmail/pm-jasrv.rc

      #   Company server, only interests fellow workers.
      #   Here "xyz-send" is just magic server request string.
      #   Notice case sensitivity settings.

      JA_SRV_F_CMD_CASE_SENSITIVE = "yes"
      JA_SRV_CMD_STRING           = "xyz-send"
      JA_SRV_PASSWORD             = ".*12qw"
      JA_SRV_FILE_DIR             = $HOME/server/public/xyz-dir
      INCLUDERC                   = $HOME/procmail/pm-jasrv.rc    

Notes from the author

[basic Mime type note]

All basic files that you send must be US-ASCII, 7bit. At least that is the default MIME type used. See JA_SRV_CONTENT_TYPE. I once received following message back

      ----- Transcript of session follows -----
      554 foo@bar... Cannot send 8-bit data to 7-bit destination
      501 foo@bar... Data format error    

because in the previous releases, the MIME type headers were not in the message saying that the content really was plain 7bit ascii.

[Sending the file as is]

Note, that the file is included "as is" without any extra start-of-file or end-of-file tags. This is possible, because the file is sent in MIME format.

[Using one line log entry]

It may look very spartan to print a single line log entry. You see messages like above in the file server log. Using one line entry instead of multi line announcements makes it possible to write a small perl tool to parse information from a single line. If you get many file server messages per day, it quicker to look at the single line entries too.

      [ja-srv1; sh file;  Foo Bar foo@site.com;]
      [ja-srv1; send xxx-file.txt; Foo Bar foo@site.com;]
                |
                Server's request keywords (you may have multiple servers)    

[wish list]

(*) MIME multipart message's mime headers may need some adjustments.

(*) I rely on simple regexp to send out base64 or gzip files. The natural extension would be to use file size threshold: if file is bigger than N bytes, send it out with gzip. And further: if file is more than NN bytes, send it out as multi part MIME.

(*) In fact there is a slight mime type errors: .zip files should be send as application/zip. If you have experience with the mime types, please contact me and help me to sort out proper mime headers.

Required settings

PMSRC must point to the source directory of procmail code. This subroutine will include many pm-jasrv-*.rc modules and other files from there.

Please test the File Server in your environment before you start using it for every day. For example I had some weird local problem where PATH had /usr/contrib/bin/ where gzip was supposed to be, but in spite of my tries procmail didn't find it along the path. Don't ask why. I now use absolute binary name:

      GZIP = /usr/contrib/bin/gzip    

In addition, if your messages are not sent to recipient, but you get daemon message:

      ... Recipient names must be specified    

That's because you have setting SENDMAIL="sendmail"; which is not enough. It must be

      SENDMAIL = "sendmail -oi -t"    

Usage example

This is my .procmailrc installation. Notice that the file server code is used only if you get "send" request. On the other hand, this double wrapping is not all necessary, you could as well rely on the File server's capability to detect SEND request.

      PMSRC   = $HOME/pm      # directory where the procmail rc files are
      RC_FSRV = $PMSRC/pm-jasrv.rc

      mySavedLOGFILE = $LOGFILE   # record file server actions elsewhere
      LOGFILE        = $PMSRC/pm-jasrv.log

      #   Listen "send" requests.
      :0
      *   ^Subject: +send\>
      {
          JA_SRV_FILE_DIR = $HOME/fsrv      # Where to get the files
          JA_SRV_LOG      = $HOME/fsrv.log  # Write log here
          INCLUDERC       = $RC_FSRV        # Use file server now
      }

      LOGFILE = $mySavedLOGFILE    


Pm-jasrv-req.rc – server request check, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of the MPFS file server. Check if file server request is on the JA_SRV_SUBJECT and do case or incasensitive check.

To Dry run this module use following skeleton. Substitute keywods as needed to reflect your system setup:

      % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all     \
        PMSRC=$HOME/txt JA_SRV_CMD_STRING=send                    \
        JA_SRV_SUBJECT="send newbie_article.rtf noconv"           \
        txt/pm-jasrv-req.rc < ~/test.mail    

Input

  • JA_SRV_F_CMD_CASE_SENSITIVE; if "yes" then server request is case sensitive.
  • JA_SRV_FORMAIL_FROM. the email From field

Output

  • stat, set to "ok" if request is accepted

Pm-jasrv-send.rc – server request check, subroutine for File Server

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine is part of the MPFS file server. Send the requested file. You can dry-run test this module with following command: a) make sure that $HOME/test conatins any simple email message b) define FORMAIL if it isnot found from path.

      % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all     \
        PMSRC=$HOME/txt JA_SRV_LOG=/dev/null                      \
        FORMAIL=/opt/local/bin/formail                            \
        file=$HOME/test FILE=test WORD=WORD JA_SRV_FROM=foo@bar   \
        SENDMAIL="tee -a $HOME/test.send" txt/pm-jasrv-send.rc < ~/test    

Note:

The MIME headers here selected previously were:

      Content-type: application/octet-stream
      Content-transfer-encoding: x-gzip64    

But Defining own CTE such as x-gzip64 is strongly discouraged by the MIME RFC's. Most e-mail clients would be at a loss on how to handle these. Many would just bomb out and not even give you the opportunity to save it to a file. A more correct MIME type is this, which is now used:

      Content-type: application/x-gzip
      Content-transfer-encoding: base64    

Input

o FILE is the filename(chdir to directory is already done) `file' is _absolute_ filename `WORD' is next word from subject line after FILE word. o JA_SRV_CMD_STRING is flag o JA_SRV_F_SUBJ_NOTIFY is flag

Output

  • FILE_ERROR is set to "yes" if file is not found.

Pm-jastore.rc – Store messagee to inbox or gzip inbox

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This subroutine stores the message to file pointed by MBOX. This subroutine is meant to be used with the the other general purpose includerc files. This makes it possible to have a centralized file storage handling for all your rc files.

Regular user doesn't get much out of this rc unless he mixes both gz and regular files in his .procmailrc

R e p e a t: This module is basis for general purpose procmail rc plug-ins to strre message to mailbox pointed by some rc configuration variable. Normal user can simply say in his .procmailrc:

      :0:
      mail.private    

Required settings

(none)

Call arguments (variables to set before calling)

MBOX must have been set to point to message storage. MBOX_SUFFIX is extension added to MBOX. Default is none. MBOX_MH if "yes" then deliver to MH mailbox with `MBOX_MH_CMD' which is "rcvstore" by default.

  • message is delivered to MH mailbox using MBOX_MH_CMD

otherwise

  • If MBOX is some.mbox the message is stored as is.
  • If MBOX is some.mbox.gz the message is gzipped to folder.
  • If MBOX is some-dir/. then deliver as individual files

Example usage

      $RC_MBOX   = $PMSRC/pm-jastore.rc

      :0
      * condition
      {
          MBOX = $HOME/Mail/spool/junk.mbox   INCLUDERC = $RC_MBOX
      }    


Pm-jasubject.rc – Subject field cleaner and canonicalizer (Re:)

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

NOTE: If you receive RFC 2047 encoded Subject headers like "Subject: ?ISO-8859-1?Q?=C4hnlichkeiten_von_=DCbungen?", you must first decode it before using this subroutine. Feed the message to pm-jamime-decode.rc first.

There are many different Email programs out there that add their own reply characters to the subject field. The most sad programs come usually from PC platform. Eg. Microsoft has gained a lot of bad reputation due to it's own standards.

  • MS Explorer can use localized reply strings, Eg Vs: or vast: seems to be Finnish Vastaus.
  • MS product Outlook (??) can be configured similarly. I have received swedish Sv: -Svar for Svaring (eng: reply)
  • MS mail uses FW: in forwarded mails.
  • Intelligent MUAs try to keep count of replies with Re2: or Re[2]
  • Japanese MUA Denshin 8 Go V321.1b7 has sent Re^2:
  • Some mua uses Re>
  • Lotus notes (in French version) uses Ref:
  • Some MS product sends UQ:
  • XXX uses -reply
  • Forwarding schemes: (fwd) [fwd] <fwd> fw: [FWD: [FWD:]]
  • Subject references: -subj subj- subj:

There already is a de facto standard where message should contain only single Re: if message has been replied to (no matter how many times). This makes it possible to do efficient message threading by only using Subject and date fields. And grepping same subjects is lot easier than from this horrible mess. Note that all text is on one line, the subject has been broken only for visual reasons:

      Subject: re- Re^2: Re[32]: FW: Re: Re(15) Sv: Re[9]: -reply
               (fwd) [fwd] <fwd> fw: [FWD:  [FWD:]]
               -subj subj: subj: subj-
               test    

This recipe standardizes any subject (like above) that has been replied to, to de facto format below. That is: "Any number of 'Re:' will be converted to single 'Re:' and any number of 'Fwd:' will be converted to single 'Fwd:'"

       Subject: Re: test (fwd)    

About In-Reply-To header

If there is In-Reply-to header in the message, but there is not Re: in the subject line, one is added automatically. Some broken Mailers forget to add the Re: to the Subject line.

Variable JA_SUBJECT_SAVE

This is by default yes which causes the original subject to be saved under header field X-Old-Subject. If you don't want that extra header generated, set this variable to no

Variable JA_SUBJECT_FWD_KILL

This is by default yes, which will kill extra forwarding indication words like (fwd) [fwd] <fwd> <f>. If you set this to no, then all the forwarding words are preserved. The de facto forward format is:

      Subject: This subject (fwd)    

Code note

This subroutine's intention is to make Subject more expressive by deleting redundant information. A simplistic approach has been taken where Subject consists of list of words whose each attribute can be either ok or delete. No attempt has been made to determine the structure of the Subject. You can see the algorithm better from an example:

      Re: New subject (was Re: Old subject)    

That should be treated syntactically like "New subject" and forgetting anything between parenthesis. This is however not respected and not even tried. The rule applied here is "One Re: is tolerated", so the subject won't change. It doesn't matter where "Re:" is.

But here the subject is changed. The rule applied is: Delete all unwanted words and then add one Re: to the beginning if OLD content had any Reply indications

          Re: New subject (was Re: Old subject)
      --> Re: New subject (was Old subject)    

IMPORTANT notice

Please check that your SHELL variable setting in ~/procmailrc is sh derivate, /bin/sh or /bin/bash. This module won't work with other shells.

Awk usage note

awk is a small, effective and much smaller than perl for little tasks. See the verbose log and make sure your awk understands VAR="value" passing syntax. Change it to nawk or gawk if they work better than your standard awk.

      AWK = "gawk"        # you may need this, try also gawk    

Customizations

Let's say Polish M$Outlook uses ODP: instead of standard re: and you want to handle that too: Then set:

      JA_SUBJECT_KILL = "odp:"            # NOTE: all lowercase
      JA_SUBJECT_SAVE = "no"
      INCLUDERC       = $PMSRC/pm-jasubject.rc    

You ca use JA_SUBJECT_KILL to delete any additional words from the subject line. E.g. if you have good news-reader, you don't need the mailing list prefixes that some mailing lists add to the beginning

      Subject: [LIST-xxx] the subject here    

to remove that list prefix, you simply match it

      JA_SUBJECT_KILL = "(list-xxx|list-yyy)"    

Important: The regexp must be all lowercase, because when match happens, the words have been converted to lowercase.

Example usage

You need nothing special, just include this recipe before you save message to folder.

      INCLUDERC = $PMSRC/pm-jasubject.rc    

Debugging

You can dry-run test this module with following command and watching output. Substitute variables as they are in your system. You feed the content of entire example mail where the Subject that needs correction is found.

      % procmail SHELL=/bin/sh AWK=gawk VERBOSE=on LOGABSTRACT=all \
        DEFAULT=/dev/null LOGFILE=$(tty) \
        JA_SUBJECT_KILL="(ace-users)" \
        PMSRC=/path/to/install/dir \
        /path/to/pm-jasubject.rc  \
        < ~/test.mail    

Thank you

Thanks to Tony.Lam@Eng.Sun.Com for his creative improvement suggestions and sending code that this recipe didn't catch at first.


Pm-jatime.rc – "hh:mm:ss" time parser from variable INPUT

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This includerc parses date from variable INPUT which has string

      "hh:mm:ss"    

Example input

      "Thu, 13 Nov 1997 11:43:23 +0200"    

Returned values

      hh      = 2 digits
      mm      = 2 digits
      ss      = 2 digits    

Variable ERROR is set to "yes" if it couldn't recognize the INPUT and couldn't parse all hh, mm, ss variables.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there.

Call arguments (variables to set before calling)

      INPUT = string-to-parse    

The INPUT can be anything as long as it contains NN:NN:NN

Usage example

Get the time of received message. The From_ header will always have the standard time stamp.

      PMSRC           = $HOME/pm
      RC_DATE_TIME    = $PMSRC/pm-jatime.rc

      :0 c
      *  ^From +\/.*
      {
          INPUT = $MATCH
          #  Turn off the logging while executing this part

          VERBOSE=off   INCLUDERC = $RC_DATE_TIME   VERBOSE=on

          :0
          * ERROR ?? yes
          {
             # Should not ever happen, you have broken From_
          }
      }    


Pm-jaube1.rc – Jari's UBE filter. Subroutine 1

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Documentation

This file is part of the "pm-jaube.rc". This subroutine is called when likely UBE message has been triggered.

Required settings

PMSRC must point to source directory of procmail code. This recipe file will include

  • pm-jastore.rc

Pm-jaube-keywords.rc – Bare bones word list based UBE filter

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your UBE (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked.

Now, if 50-70 % hit rate is good enough for your starting point, go ahead and read more. This file is supposed to be the last resort, if you really do not have any better tool to analyze messages.

Overview of features

  • Word and phrase based matching
  • 50-70 % success rate. 90 % never achieved. That's a guarantee.
  • Extremely fast and a dream to CPU resources. Implemented in pure procmail and you can almost hear the humming sound of its regular expression engine shredding UBE messages to pieces.

Description

Are you sure you want use this word list based checking?

Think twice before you use this subroutine. It knows nothing about the content your mail. "It's all UBE unless proven otherwise" is the motto. The brutal search tracks words and phrases to find an indication of mass posting and traces of Unsolicited Bulk Email (UBE aka spam). Repeat: Read the first paragraph again before you consider putting this file into action. This filter WILL PASS through unwanted mail and it WILL catch good mail. This is rule based matching, so I suppose you know where you're putting your head with this. Ahem. Alerted? Good.

The Story

There was a man and mail account. The account had limited space, couldn't install any other programs because disk quota would have exceeded. System administrators weren't' interested in installing anything. The Mail server ran behind firewall and had OS that was never heard of - it couldn't run other programs. Or if it could, the Bad system administrator was too scared to install extra programs to the host MTA ran. No joy – no means to stop incoming UBE – Right?

Wrong. There was procmail. The Bad system adminitrator didn't mention that ~/.procmailrc was honored - just the the external programs we a no-no-no (Technical: the MDA host mounted user disks; the server ran on separate host and couldn't use any of the user compiled programs. Statically linked ones filled up the man's disk space).

First line of defense, any defense would do. So, this rule based file was born. Nothing else was installed in that account and the happy word list based matching routine kept chewing mail, mail, mail. And the system administrator was happy - he nurtured the MTA host's CPU resources and noticed nothing alarming. All ticked like clockwork.

Life began again. After 1000 mail bombards a day, the account was usable again.

Motivation

If you can, use the Bayesian filters and forget all rule based ones, word and phrase matching based ones; all static filters. On the other hand, if you want quick solution, even imperfect, until you have time to learn and setup other tools, this subroutine may be of interest.

The best part. You can carry this single file anywhere where procmail lives. No other files are needed. Setup couldn't be simpler.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address is usually forged. Do not increase the network traffic. Instead save the messages to folders and periodically check their contents. It's not nice to be forced to apologize about bounces to a wrong destination.

Code Note

Procmail is picky about the whitespace in continuing lines, make sure there is not a single spaces left after the continuation backslash. Use good editors or external programs to get rid of the white spaces. In Emacs you would add this line to your ~/.emacs startup file: "(add-hook 'write-file-hooks 'delete-trailing-whitespace)"

      :0
      * ^Subject:.*(regexp\
              |and-more\
              |and-more\
              )
      {
          # Process it
      }    

Why are the regexps put into this file and not to a separate regexp file? Good question. It is possible to check message's content with external process, like grep, to see if any matches are found. This kind of methodology is covered in Procmail Tips section "Using grep with file lists to mach messages" at <http://pm-tips.sf.net>. The reason why all the regexp are maintained inside this file is:

  • Simplicity. One file - no extra configuration files or regexp databases.
  • Self standing. Does not call external processes, so it's a little faster than possible grep and fgrep solution.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_KEYWORD_HEADER, if set, then the results are put to messages headers. By default this variable is not defined to save from external formail process call. Suggestion: "X-Spam-JaubeKwd"; without trailing colon.

Return values

  • ERROR_STATUS is set to word "Bad" otherwise empty.
  • ERROR is set to short descriptive word that indicate which rule was matched. Values: Header-FromKeywords, Header-SubjectKeywords and Body-Keywords
  • ERROR_MATCH is set to some words that happened to trigger UBE catch rule.

Usage example

      PMSRC     = "/path/to/procmail/lib"
      #   Exclude these addresses from tests
      VALID_FROM = "(my@address.example.com|word@here.example.com)"

      :0
      *$ ! ^From:.*$VALID_FROM
      *  !  FROM_DAEMON
      {
          INCLUDERC = $PMSRC/pm-jaube-keywords.rc

          #  Variable "ERROR" is set if message was UBE

          :0 :
          * ! ERROR ?? ^^^^
          junk.ube.spool
      }    

File layout

The layout of this file is managed by Emacs packages tinyprocmal.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-spamprobe.rc – Interface to Annoyance Filter program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ mkdir $HOME/.annoyance
      $ DB=$HOME/.annoyance/dict.bin; DB2=$HOME/.annoyance/fdict.bin
      $ annoyance-filter --mail single.msg --prune --write $DB
      $ annoyance-filter --phrasemax 2 \
        --read  $DB \
        --junk dir/to/bad/messages \
        --prune --write $DB
      $ annoyance-filter -v --read $DB --prune --fwrite $DB2    

To check message:

      $ annoyance-filter --read $DB --test mail.msg
      $ annoyance-filter --fread $DB2 -v --class mail.msg    

Overview of features

Description

There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program annoyance-filter, which must already have been installed.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If annoyance-filter program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_ANNOYANCE_PRG = /usr/bin/spamprobe    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_ANNOYANCE_PRG, path to the program [required].
  • JA_UBE_ANNOYANCE_SPAM_DB, path to the dictionary database [required]. E.g. $HOME/.annoyance/dict.db.
  • JA_UBE_ANNOYANCE_SPAM_DB_OPT, type of dictionary to read. Default is "--read", but this could be fast dictionary option "--fread".
  • JA_UBE_ANNOYANCE_HEADER, the header name where the results are put. If not defined, no header is added. Defaults to X-Spam-Annoyance-Status
  • JA_UBE_ANNOYANCE_FORCE, if set to yes then call program no matter what. Normally if there already is X-Spam-Annoyance-Status header, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to the return value of the program.

Usage example

      PMSRC                = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_ANNOYANCE_PRG     = "/usr/bin/nice -n 5 /usr/bin/annoyance-filter"
      JA_UBE_ANNOYANCE_SPAM_DB = $HOME/.annoyance/dict.db
      INCLUDERC                = $PMSRC/pm-jaube-prg-spamprobe.rc

      #   The ERROR will contains word "yes" if message was spam

      :0 :
      * ERROR ?? yes
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-bmf.rc – Interface to Bayesian Mail Filter program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ ls spam/*.mail | xargs -n 1 bmf -s # feed individual messages
      $ ls good/*.mail | xargs -n 1 bmf -n # feed individual messages    

To test

      $  bmf -p < test.mail | less    

Overview of features

  • Implements interface to http://www.sf.net/projects/bmf "Bayesian Mail Filter" project. The called binary is "bmf" hence the name of this subroutine. Bmf program uses well know statistical analysis which is much more reliable than any hand made procmail scripts could ever achieve.
  • Variable ERROR is set if the message was UBE.
  • Results are available in headers X-Spam-bmf-Status and X-Spam-bmf-Flag for further analysis.

Description

There are several bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection.

For serious discussion of strenghts of the different programs, refer to a very good article "Spam Filters" by Sam Holden at 2004-08-16 <http://freshmeat.net/articles/view/964>. The article evaluated throughly following programs:

  • Bayesian Mail Filter (bayesian)
  • Bogofilter (bayesian)
  • dbacl (bayesian; multiple wordlists)
  • Quick Spam Filter (bayesian)
  • SpamAssassin (perl matching + bayesian)
  • SpamProbe (bayesian)
  • SPASTIC (procmail recipes)

This subroutine implements call interface to bmf program. Why whould you need it? Because unfortunately bmf by default use exactly the same headers as spamasassin and the two cannot co-operate together: bmf would overwrite existing spamassasin headers. This subroutine takes care of saving previous headers and move bmf results to their own X-Spam-bmf-* headers.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If bmf program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_BMF_PRG = "/usr/bin/bmf"    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_BMF_PRG, path to program
  • JA_UBE_BMF_HEADER_PREFIX, the header name where the results are put. If not defined, no headers are added. Default value is X-Spam-bmf.
  • JA_UBE_BMF_FORCE, if set to yes then call program no matter what. Normally if there already are X-Spam-bmf-* headers, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to short ube trigger recipe reason. Contains content of X-Spam-bmf-Status header which you can check for values
  • ERROR_MATCH contains detailed content of X-Spam-bmf-Status header.

If headers were enabled, they will contain:

      X-Spam-bmf-Status: Yes, hits=1.000000 required=0.900000, tests=bmf
      X-Spam-bmf-Flag: YES    

Usage example

      PMSRC            = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_BMF_PRG   = "/usr/bin/nice -n 5 /usr/bin/bmf"
      INCLUDERC        = $PMSRC/pm-jaube-prg-bmf.rc

      #   The ERROR will contains word "yes" if it program classified
      #   the message into "bad" category.

      :0 :
      * ERROR ?? yes
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-bogofilter – Interface to bogofilter program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $  rm -f ~/.bogofilter/*.db         # delete database
      $  bogofilter -B -n good.msg ...
      $  bogofilter -B -s spam.msg ...    

Overview of features

  • Implements interface to http://www.sf.net/projects/bogofilter project.
  • variable ERROR is set if message was likely spam.
  • Results are available by default in header X-Spam-Bogofilter-Status.

Description

There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program bogofilter, which must already have been installed.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If bogofilter program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_BOGOFILTER_PRG = /usr/bin/bogofilter    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_BOGOFILTER_PRG, path to the program
  • JA_UBE_BOGOFILTER_HEADER_NEW, the header name where the results are put. If not defined, no header is added. Defaults to X-Spam-Bogofilter-Status
  • JA_UBE_BOGOFILTER_FORCE, if set to yes then call program no matter what. Normally if there already is X-Spam-* header, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to the return value of program if message was spam.
  • ERROR_INFO, is set if case is "unsure".

Usage example

      PMSRC                  = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_BOGOFILTER_PRG  = "/usr/bin/nice -n 5 /usr/bin/bogogilter"
      INCLUDERC              = $PMSRC/pm-jaube-prg-bogofilter.rc

      #   The ERROR will contains reason if program classified
      #   the message into "bad" category.

      :0 :
      * ! ERROR ?? ^^^^
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-bsfilter.rc – Interface to Bsfilter program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ bsfilter --add-clean good.msg ...
      $ bsfilter --add-spam  spam.msg ...    

Overview of features

Description

There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program bsfilter, which must already have been installed.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If bsfilter program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_BSFILTER_PRG = /usr/bin/bsfilter    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_BSFILTER_PRG, path to the program.
  • JA_UBE_BSFILTER_HEADER, the header prefix name where the results are put. If not defined, no header is added. Defaults to X-Spam-Bsfilter-
  • JA_UBE_BSFILTER_FORCE, if set to yes then call program no matter what. Normally if there already is X-Spam-Bsfilter- header, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to the return value of bsfilter program.

Usage example

      PMSRC                  = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_BSFILTER_PRG    = "/usr/bin/nice -n 5 /usr/bin/bsfilter"
      INCLUDERC              = $PMSRC/pm-jaube-prg-bsfilter.rc

      #   The ERROR will contains word "yes" if message was spam

      :0 :
      * ERROR ?? yes
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-ifile – Interface to ifile program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ rm ~/.idata                       # delete database
      $ echo herbalife | ifile -i spam    # initialize database
      $ ifile -h -i good good.msg ...
      $ ifile -h -i spam spam.msg ...    

Overview of features

  • Implements interface to http://freshmeat.net/projects/ifile project.
  • variable ERROR is set to the result of ifile check. This usually holds the "folder" name the ifile was trained at the time. E.g. if the folder used for training Unsolicited Bulk Email was "ifile -i spam", then the return value is "spam".
  • Results are available by default in header X-Spamifile.

Description

There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program ifile, which must already have been installed.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If ifile program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_IFILE_PRG = /usr/bin/ifile    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_IFILE_PRG, path to the program
  • JA_UBE_IFILE_HEADER, the header name where the results are put. If not defined, no header is added. Defaults to X-Spam-Ifile-Status
  • JA_UBE_IFILE_FORCE, if set to yes then call program no matter what. Normally if there already is header, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to the return value of ifile program.

If header output is enabled, it will contain the folder name ifile thinks the message belongs to. Assuming that trained folders used for messages were spam and good, then the headers read:

      X-Spam-Ifile-Status: spam
      X-Spam-Ifile-Status: good    

Usage example

      PMSRC                  = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_IFILE_PRG       = "/usr/bin/nice -n 5 /usr/bin/ifile"
      INCLUDERC              = $PMSRC/pm-jaube-prg-ifile.rc

      #   The ERROR will contains reason if program classified
      #   the message into "bad" category.

      :0 :
      * ! ERROR ?? ^^^^
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-runall.rc – Interface to all Bayesian filter programs

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Overview of features

  • To detect spam reliably, run all Bayesian programs one by one to see if any of them classifies the message as spam.
  • Programs supported: bogofilter, spamprobe, Bayesian Mail Filter, Annoyance Filter, Bsfilter, Spamoracle and Spamassassin.

Description

There are several bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. This module is a meta package which will call all other individual modules that interface to these Bayesian programs. The use is simple: define programs that are available in your system and which you have trained (Bayesian programs need to be trained before use), and this this module will query how those programs would classify the message.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc
  • pm-jaube-prg-spamprobe.rc
  • pm-jaube-prg-spamoracle.rc
  • pm-jaube-prg-annoyance-filter.rc
  • pm-jaube-prg-bsfilter.rc
  • pm-jaube-prg-bmf.rc

Call arguments (variables to set before calling)

To activate Bayesian program(s), define path to them. Default value for all these variables is "" i.e. is is supposed that no programs have been installed or trained.

  • JA_UBE_BOGOFILTER_PRG, path to bogofilter program.
  • JA_UBE_SPAMPROBE_PRG, Path to spamprobe program
  • JA_UBE_BMF_PRG, Path to Bayesian Mail Filter bmf program.
  • JA_UBE_SPAMASSASSIN_PRG, path to spamassassin program. If daemon version is available, set this to spamc program.
  • JA_UBE_SPAMORACLE_PRG, path to spamoracle program.
  • JA_UBE_ANNOYANCE_PRG, path to annoyance-filter program. You must also set JA_UBE_ANNOYANCE_SPAM_DB to fast dictionary database location.
  • JA_UBE_BSFILTER_PRG, path to bsfilter program.

Optional variables to set:

  • JA_UBE_BOGOFILTER_OPT. Default is "-p" passthrough. Option "-e" will report exit code to procmail.
  • JA_UBE_SPAMASSASSIN_OPT. Default is "".
  • JA_UBE_SPAMASSASSIN_MAX_SIZE. Default is 256000 (256k). Spamassassin is a Perl program, which is slow at startup, so checking e.g. long attachements consumes lot of resources. Keep this value relatively small.

Important notes

All headers are canonicalized to X-Spam-<PROGRAM>- so e.g. in bogofilter's case, the default X-Bogocity header is changed to value X-Spam-Bogofilter-Status and so on. Summaries like below can then be generated:

      $ egrep -i '(Subject|From|^X-Spam.*Status)' *.mbox    

Return values

  • ERROR variable's first word is set to program that classified the spam: bogofilter, bmf (Bayesian Mail Filter), spamassassin etc. It is followed by semicolon ";" and detailed return status from the program.
  • ERROR_INFO is set only in bogofilter's case if it thinks the message is neither spam nor ham ("Unsure").

Usage example

      PMSRC                 = $HOME/procmail # procmail recipe dir

      # ... other checks, mailing lists, work mail etc.

      #   bogofilter and Bayesian Mail Filter available and trained. Use them.

      JA_UBE_BOGOFILTER_PRG = "/bin/nice -n 5 /bin/bogofilter"
      JA_UBE_BMF_PRG        = "/bin/nice -n 5 /bin/bmf"

      #   Call the "umbrella" module, which will take care of
      #   all the details.

      INCLUDERC             = $PMSRC/pm-jaube-prg-runall.rc

      #   ERROR is set if message was spam. The "()\/" logs reason.

      :0 :
      * ERROR ?? ^()\/.+
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-spamassassin – Interface to spamassassin program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ rm -f ~/.spamassassin/bayes*
      $ sa-learn $opt --local --no-rebuild --ham  good.msg ...
      $ sa-learn $opt --local --no-rebuild --spam spam.msg ...
      $ sa-learn --rebuild    

Overview of features

  • Implements interface to http://www.spamassassin.org/ project.
  • variable ERROR is set if message was spam.
  • Results are available in default headers (X-Spam-*)

Description

There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program spamassassin, which must already have been installed.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If spamassassin program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_SPAMASSASSIN_PRG = /usr/bin/spamassassin    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_SPAMASSASSIN_PRG, path to the program
  • JA_UBE_SPAMASSASSIN_MIN_SIZE, minumum message size. Default is 100 bytes.
  • JA_UBE_SPAMASSASSIN_MAX_SIZE, maximum message size. Default is 256 000 bytes (about 256k).
  • JA_UBE_SPAMASSASSIN_FORCE, if set to yes then call program no matter what. Normally if there already is X-Spam-* header, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to the return value of program if message was spam.
  • ERROR_INFO, is set if case is "unsure".

Usage example

      PMSRC                   = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/nice -n 5 /usr/bin/bogofilter"
      INCLUDERC               = $PMSRC/pm-jaube-prg-spamassassin.rc

      #   The ERROR will contains reason if program classified
      #   the message into "bad" category.

      :0 :
      * ! ERROR ?? ^^^^
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-spamoracle.rc – Interface to Spamoracle program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ spamoracle add -v -spam good.msg ...  # feed individual messages
      $ spamoracle add -v -good good.msg ...  # feed individual messages    

To test

      $  spamoracle test mail.msg | less    

Overview of features

  • Implements interface to http://freshmeat.net/projects/spamoracle OCaml language based Bayesian Mail program.
  • Variable ERROR is set to "yes" if the message was UBE.
  • Results are available in headers X-Spam-Spamoracle-Status, X-Spam-Spamoracle-Score, X-Spam-Spamoracle-Details and X-Spam-Spamoracle-Attachment for further analysis.

Description

There are several bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection.

Using Spamoracle as sole spam protection is inefficient, because version version 1.4 (2004-09-29) does not accept messages from stdin. Becaus of this message has to be written to a temporary file before calling Spamoracle. Later the temporary file must be removed with rm. All these three shell calls are needed for each message. If you have other detection programs, call them first to identify unsolicited Bulk Email.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If spamoracle program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_SPAMORACLE_PRG = /usr/bin/spamoracle    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_SPAMORACLE_PRG, path to program
  • JA_UBE_SPAMORACLE_HEADER_PREFIX, the header name where the results are put. If not defined, no headers are added. Default value is X-Spam-Spamoracle'.
  • JA_UBE_SPAMORACLE_FORCE, if set to yes then call program no matter what. Normally if there already are X-Spam-Spamoracle- headers, it is assumed that the message has already been checked and no new checking is needed.
  • JA_UBE_SPAMORACLE_REGEXP, regexp to match for spam probability. Defaul value will match probabbility of 0.8 with 5 interesting words. The match is tried agains X-Spam-Spamoracle-Score header.

Return values

  • ERROR, value "yes" if JA_UBE_SPAMORACLE_REGEXP matched.
  • ERROR_MATCH contains detailed content of X-Spam-Spamoracle-Score header.

If headers were enabled, they will contain these values. The score's values are spam probability 0.0 - 1.0 and the degree of similarity 0-15 of the message with the spam messages in the corpus.

      X-Spam-Spamoracle-Status: yes
      X-Spam-Spamoracle-Score: 1.00 -- 15
      X-Spam-Spamoracle-Details: refid:98 $$$$:98 surfing:98 asp:95 click:93
        cable:92 instantly:90 https:88 internet:87 www:86 U4:85 isn't:14 month:81
        com:75 surf:75
      X-Spam-Spamoracle-Attachments: cset="GB2312" type="application/octet-stream"
        name="Guangwen4.zip"    

Usage example

      PMSRC            = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_SPAMORACLE_PRG   = "/usr/bin/nice -n 5 /usr/bin/bmf"
      INCLUDERC               = $PMSRC/pm-jaube-prg-spamoracle.rc

      #   The ERROR will contains word "yes" if it program classified
      #   the message into "bad" category.

      :0 :
      * ERROR ?? yes
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube-prg-spamprobe.rc – Interface to Spamprobe program

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last.

YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST!

To train:

      $ spamprobe -8 good good.msg ...
      $ spamprobe -8 spam spam.msg ...    

Make sure there are no stale lock files, or the spamprobe and this subroutine will hang infinitely:

      $ rm -f ~/.spamprobe/lock    

Overview of features

Description

There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program spamprobe, which must already have been installed.

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas – you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents.

Required settings

If spamprobe program is available, define this variable in your ~/.procmailrc. Use absolute path to make the external shell quick; it'll save server load considerably.

      JA_UBE_SPAMPROBE_PRG = /usr/bin/spamprobe    

If you do not have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available.

Required settings

None. No dependencies to other procmail modules.

Call arguments (variables to set before calling)

  • JA_UBE_SPAMPROBE_PRG, path to the program.
  • JA_UBE_SPAMPROBE_HEADER, the header name where the results are put. If not defined, no header is added. Defaults to X-Spam-Spamprobe-Status
  • JA_UBE_SPAMPROBE_FORCE, if set to yes then call program no matter what. Normally if there already is X-Spam-Spamprobe-Status header, it is assumed that the message has already been checked and no new checking is needed.

Return values

  • ERROR, is set to the return value of spamprobe program.

Usage example

      PMSRC                  = $HOME/procmail # procmail recipe dir

      <other checks, mailing lists, work mail etc.>

      JA_UBE_SPAMPROBE_PRG   = "/usr/bin/nice -n 5 /usr/bin/spamprobe"
      INCLUDERC              = $PMSRC/pm-jaube-prg-spamprobe.rc

      #   The ERROR will contains word "yes" if message was spam

      :0 :
      * ERROR ?? yes
      junk.mbox    

File layout

The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-jaube.rc – Unsolicited Bulk Email (UBE) filter.

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Warning

Put all your UBE (aka spam) filters towards the end of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked.

Are you sure you want to use procmail for UBE?

If you think you can put this recipe as a first line of defence to your mail, you will disappoint. Checking UBE with procmail's rule based means does not work that way. The good messages must be sorted first (like your mailing lists and your important work or friend message) and only then what's left to process can be scanned by static rule based tools, like this procmail module. There are much more better tools that are based on statistical analysis of messages. You really should consider using one or combination of Bayesian tools: Spamassassin, bogofilter, spamprobe, Bayesian Mail Filter, ifile etc.

Repeat: procmail rules are not the tool to UBE control. The pattern matching rules can never keep up with the spammers. That said, if you:

  • Can bare a 70-80 % UBE detection rate.
  • Can bare 10 % false hits; you need to check you UBE folder regularly for messaged that did not belong there.
  • Have an account that does not get large number of UBE messages.
  • Or if procmail is all you have in the system.

only then consider this module or any other procmail based spam filters in that respect. So, please don't set your expectations high. Spend good time with the configuration variables and check there returned result in variable ERROR carefully. Good luck.

Overview of features

  • Requires procmail 3.11pre7+
  • You don't need external files: site block lists, the heuristics nail most of the UBE messages. Just plug in this module and you have UBE shield active.
  • Header based filtering: Minimum headers, Pegasus bulk mail, X-uidl validity check, bogus From-To combination,
  • Address based filtering: Numeric address, Invalid address (eg. me@myMarketing.global), UBE-like(friend,remove request.)
  • Text filtering: no html accepted, common advertising slogans, unnecessary many capitalized words, HTML message body detection,
  • And many more check that just not were listed here.

Remember: this is not 100% and there will always be some mishits, so don't just junk messages to /dev/null.

Description

Originally Daniel Smith posted his spam.rc, where he had gathered many tips and heuristics to filter UBE email. This filter here expresses work of many procmail users. Original filters were modified, some rules were left out that catched false email messages and made the package look a bit more general so that it could be included via INCLUDERC in the standard way.

Thanks to Daniel and others, the UBE bomb days can be reduced, when this filter is active. Some UBE messages may still lurk into the mailbox, but that's the problem with all static rule based tools.

Logging the events

A good strategy to follow incoming mail is to log the vital parts like Date, From, Subect to some log file and then a reason what happened to a message. The ~/Mail/mail.log might look like:

      1997-12-08 work@example.com  Extra Holiday $$$$$
          [jaube; Marketing-Big-ExitCode; LEGAL, MONEY-MAKING PHENOMENON]
      1997-12-09 Denizen logger@example.com  [RePol] hiding
      1997-12-09 david X dx@example.com  Re: Send list to incoming folder
      1997-12-09 david X dx@example.com  Re: Send list to incoming folder
      1997-12-09 OMC manager <em>omcman@example.fi</em> "Environments updated"
          [my; work-localenv]
      1997-12-09 doodle@example.org  Re: Gnus (Emacs Newsreader) FAQ
          [my; emacs;   Re: Gnus (Emacs Newsreader) FAQ ]    

First a UBE message that was identified and saved to folder. Next 3 messages were filed to mailing-list folders and there was no [] action displayed for them (left out due to high volume of these messages). Second Last was internal work message. Lastly someone asked somthign about Emacs.

The basic incoming message log recipe could be like this. Variable TODAY is $YYYY-$MM-$DD whose values are set after calling pm-jadate.rc. The LISTS is user set variable to exclude mailing lists whose activity is not important. Variables FROM and SUBJECT are fields read the message's headers.

      BIFF      = $HOME/Mail/mail.log
      INCLUDERC = $PMSRC/pm-jadate.rc
      ...

      :0 hwic:
      *$ ! $LISTS
      |echo "$TODAY $FROM $FSUBJECT" >> $BIFF    

Here is small perl script to print summary of trapped UBE messages from a log like above. It gives nice overview which recipes catch most of the UBE messages.

      perl -ne '/jaube; (\S+)/; $s{$1}++;                         \
           END {  $s = (map{$x += $_; $_= $x} values %s)[-1];     \
                  $i = int $s{$_}/$s *100;                        \
                  for (keys %s) { printf "$s{$_} $i $_\n" }       \
               }'                                                 \
           mail.log |                                             \
           sort -nr    

Here is sample results during two month period There are total of 3248 UBE messages catched.

      count  %  type
      ------------------------------------------
        554 17  Marketing-CountBigLetterWords
        457 14  Marketing
        422 12  Marketing-SelectedBigLetterWords
        349 10  AddrBogus-ToFrom
        263  8  FromReceived-Mismatch
        223  6  NoDirectAddress-ToCc
        216  6  HdrForgedPegasus
        164  5  AddrBogus-To
        151  4  MessageId
        102  3  BodyHtml
        73   2  Received-IPError
        63   1  Identical-FromTo
        53   1  AddrInvalid
        15   0  From-nslookup
        9    0  HdrReceivedTime
        7    0  HdrX-UIDL
        4    0  Marketing-headers    

About bouncing message back

The general consensus is, that you should not send bounces. The UBE sender is not there, because the address is usually forged. Do not increase the network traffic. Instead save the messages to folders and periodically check their contents. It's not nice to be forced to apologize if you bounced message to a wrong destination. DON'T BOUNCE. Forget all recipe examples that use HOST and EXITCODE and be a good Net citizen.

Required settings

PMSRC must point to source directory of procmail code. This recipe file will include

  • pm-javar.rc
  • pm-janslookup.rc
  • pm-jaaddr.rc

Call arguments (variables to set before calling)

Only handful of the most important variables are described here. You really should read all the comments placed in the "user configured section" in this procmail module's code. Most of the defaults should work out of the box.

  • JA_UBE_VALID_ADDR, your email addresses or other valid from addresses that will say "this is mail addressed directly to you".
  • JA_UBE_HDR, If non-empty, a new header is added which tells which recipe was triggered. The header is not added to message, if there is nothing to report; i.e. message passed all tests.
  • Various flags: Some of the ube detecting recipes give more false hits than nail real ube. Experiment with yourself and turn on or off the recipes that work for the kind of ube messages you receive.
  • JA_UBE_MAX_BIG_WORDS, the maximum count of big letter words in the message that is tolerated. The current count 5 is rather conservative and it is suggested you to increase it to prevent trapping too many false hits. Alternatively update JA_UBE_CAPS_OK to include accepted words.
  • JA_UBE_APPARENTLY_TO_MAX, how many Apparently-To headers are tolerated. Default is 3.
  • JA_UBE_MAX_HTML_TAGS, maximum count of html tags allowed in the body.
  • JA_UBE_ATTACHMENT_ILLEGAL_KILL, if set to "yes" (default), then illegal attachment from body is ripped off. This is brute way to truncate the message abruptly to save mailbox space. You still see the headers for tracking, but the body is gone. The regexp to test is set in JA_UBE_ATTACHMENT_ILLEGAL_REGEXP.
  • JA_UBE_ATTACHMENT_SUSPECT_KILL, if set to "yes" (default "no"), kill suspectible characters in attachement filename. The regexp to test is set in JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP.
  • JA_UBE_CHARSET_LEGAL, if set, accept only these character. The default value detect messages with 7bit only (english speaking. For foreign language you may want to set this something like $CHAR_7BIT_SET$CHAR_LIST_FINLAD for Finnish. See pm-javar.rc for available character sets.

Return values

  • ERROR_STATUS, status word of checks. Value "Good" or "Bad"
  • ERROR, is set to short ube trigger recipe reason
  • ERROR_MATCH, is set to some MATCH that happened while triggering UBE message.

Alternatively you check content of header JA_UBE_HDR which contains results of the above variables. Possible values for ERROR are:

      AddrAOLinvalid
      AddrBogus-From
      AddrInvalid-From
      AddrInvalid-To
      AddrNumeric
      AddrNumericDomain
      AddrUbeLike
      BodyAttachment-FileIllegalAdditional
      BodyAttachment-FileIllegalMatch
      BodyAttachment-FileIllegalOther
      BodyAttachment-FileSuspect
      BodyCharacters-Illegal
      BodyHtml-NonMime
      BodyHtml-script
      BodyHtmlBase64
      BodyHtmlImage
      BodyHtmlTags
      BodyMimeCharset-Illegal
      EnvelopeFrom-Invalid
      From-nslookup
      FromReceived-Mismatch
      HdrForgedPegasus
      HdrReceived
      HdrReceivedTime
      HdrX-Distribution
      HdrX-UIDL
      Header-ApparentlyTo
      HeaderCharacters-Illegal
      HeaderMimeCharset-Illegal
      Html-base64
      Identical-FromTo
      Marketing-Body
      Marketing-CountBigLetterWords
      Marketing-SelectedBigLetterWords
      Marketing-Subject
      Marketing-SubjectGreeting
      MegaSpammer
      MessageId-Invalid
      MessageId-Empty
      NoDirectAddress-ToCc
      NotEnoughHeaders
      Received-IPError
      VirusBody
      VirusHeader    

Usage example

      # - All legimate messages should already been handled and
          saved before this recipe.
      # - Activate the filter only for messages that are not from
      #   daemon and not from valid senders: like from "my" domain
      #   and mailing lists and from somewhere else.

      VALID_FROM = "(my@address.example.com|word@here.example.com)"

      :0
      *$ ! ^From:.*$VALID_FROM
      *$ ! FROM_DAEMON
      {

          #   Do not add extra headers. This saves external shell call
          #   (formail). Also do not try to kill the message content,
          #   again saving one external call (awk). With these, the
          #   recipe is faster and more CPU friendly.

          PM_JA_UBE_HDR                  = ""
          JA_UBE_ATTACHMENT_ILLEGAL_KILL = "no"

          INCLUDERC = $PMSRC/pm-jaube.rc

          #   Variable "ERROR" is set if message was UBE, record error
          #   to log file with "()\/"

          :0 :
          * ERROR ?? ()\/[a-z].*
          {
              #  Don't save those *.exe, *.zip UBE attachements
              :0
              *  ERROR ?? attacment.*file
              /dev/null

              :0 :
              spam.mbox
          }
      }    

There may be UBE messages that fool FROM_DAEMON test, so you could also use something more finer check. The standard daemon error message almost always has sentence "Transcript of session follows" in the body. This recipe says: "Unless proven otherwise, I don't believe this is daemon message even if it looked like that". Add More "2^1" checks to raise score for other valid daemon cases.

      *   -1^0       ^FROM_DAEMON
      * !  2^1  B ?? Transcript of session follows
      {
          # ... Now call UBE checker
      }    

File layout

The layout of this file is managed by Emacs packages tinyprocmal.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/


Pm-javac.rc – Procmail: Vacation framework recipe (id-cache)

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

Framework for all programs that need to reply to messages only once. Usually known as "vacation" feature. If you cahnge th cache file, you can attach this recipe to any messages that you want to deal with only once.

Required settings

PMSRC must point to source directory of procmail code. This subroutine will include

  • pm-javar.rc

Call arguments (variables to set before calling)

  • JA_VAC, To activate vacation, set value to "yes"
  • JA_VAC_RC, When new message-id is found, run this includerc
  • JA_VAC_ID_CACHE, Remember to clear this file when you start the vacation.

Usage example

To turn on the vacation feature, create ~/.vac file and recipe below activates vacation. If the vacation is not active, then cache file is removed. (automatic cleanup). The VERBOSE is also turned off when you're on vacation; so that your procmail log will not get filled.

So when you go to vacation, you 'touch ~/.vac' and update ~/vacation.msg. When you come back, you 'rm ~/.vac'. That's it.

IMPORTANT: If you are subscribed to mailing lists, be sure to file messages from those services first and put the vacation recipe only after the list or bot messages. Also add sufficent "!" conditions in order not to reply to other "bot" service messages.

      JA_VAC_ID_CACHE = $HOME/.pm-vac.cache

      :0
      *$ ? $IS_EXIST $HOME/.vac
      {
          VERBOSE     = off
          JA_VAC      = "yes"
          JA_VAC_RC   = $PMSRC/pm-myvac.rc        # my vacation recipe
          INCLUDERC   = $PMSRC/pm-javac.rc        # framework
      }
      :0 E                                        # else
      * ? $IS_EXIST $JA_VAC_ID_CACHE
      {
          dummy = `$RM -f $JA_VAC_ID_CACHE`
      }    

Here is example of pm-myvac.rc recipe

      #  Change subject

      :0 fhw
      * ^Subject: *\/[^ ].*
      | $FORMAIL -I "Subject: vacation (was: $MATCH)"

      :0 fb           # put message to body
      | $CAT $HOME/.vacation.msg

      :0              # Send it
      | $SENDMAIL    


Pm-javar.rc – Global variable definitions

File id

Copyright © 1997-2009 Jari Aalto

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at <http://www.gnu.org/copyleft/gpl.html>.

Description

This file defines common variables that you can use in the recipe's condition line. Procmail does not know about escape sequences like \t or \n and it is therefore much more readable to use variables as substitute for common regular expression atoms. Pay attention that the line starts with "*$ ", where "$" expands the variables: In this file, the variable names represent the well known Perl regular expression names, so that $s is alost like Perl expression \s (whitespace) and $S is almost equivalent to \S (non-whitespace). Similarly, $d is \d (digit) and $D resembled \D (non-digit).

      :0
      *$ $s+something+$s+$d+$a+    

The equivalent without variables (you don't see the tabs and spaces here):

      :0
      #  Space + tab
      * [         ]something[     ][0-9]+[a-z]+    

In addition all system dependent variables are defined in this module. For example if you have Gnu awk, it is strongly suggest that you set:

      AWK = "/path/to/gawk"  # in Linux, this would be /usr/bin/awk    

You can define these variables before or after the module, just make sure the binaries reflect your operating system's paths. In general, if you "port" your setup to several system, dont' include absolute paths. In the other hand, if your setup is in the same place using absolute paths will speed up executions by a factor of 3 or more. (depending on how long your PATH is)

Standard variables defined

See pm-tips.txt file for full explanation or look at the source code.

      SPC WSPC NSPC SPCL       # Whitespace, Non Whitespace, W+linefeed
      \s \d \D \w \W and \a \A # perl equivalents    

Special variable JA_FROM_DAEMON

In order to boost procmail and to save extra CPU cycles, this module defines variable JA_FROM_DAEMON that caches the information of ^FROM_DAEMON. You can refer to JA_FROM_DAEMON as you would to big brother FROM_DAEMON. This has the advantage that procmail has already computed the result and the variable JA_FROM_DAEMON is used as a cache, thus avoiding repeated FROM_DAEMON regexp tests, which are expensive. Variable JA_FROM_DAEMON_match contains "" or the result of matched daemon text.

      *$ $JA_FROM_DAEMON    

or the familiar

      *$ ! $JA_FROM_DAEMON    

Instead of using the regexp parsing with

      * ^FROM_DAEMON    

and

      * ! ^FROM_DAEMON    

Special variable JA_FROM_MAILER

Works like JA_FROM_DAEMON variable but in respect to FROM_MAILER. The matches text is in JA_FROM_MAILER_MATCH

Usage example

For your .procmailrc, you can simply put this, because you want to load the variables at startup

      PMSRC     = "/path/to/install/location/of/this/library"
      INCLUDERC = $PMSRC/pm-javar.rc    

If you're developing your own modules that use these variables put these lines at the beginning. ~/.procmailrc. It checks if WSPC variable does not include a space --> load the variable definitions. If the variable is already defined, the file is not loaded. The test line is something alike #ifdef – #endif in C/C++ language or a conditional "import" command in other languages.

      :0
      * ! WSPC ?? [ ]
      {
          INCLUDERC = $PMSRC/pm-javar.rc
      }    

Defined modules

After this file loads, you can refer to any module with $RC_JA_MODULE. E.g. to call email spit module in your code you would use following. See at the end of this file for all defined module names.

      INCLUDERC = $RC_JA_UBE    


Html date: 2008-09-20 14:59
procmail-lib-2009.1202/doc/manual/index-toc.html000066400000000000000000001552641130547513300212240ustar00rootroot00000000000000 Navigation
Document id
Pm-jaaddr.rc -- extract 'foo@some.com' email address from variable INPUT
Pm-jabup.rc -- Keeep N arriving message backup in separate directory
Pm-jacookie1.rc -- Generate unique id from INPUT variable.
Pm-jacookie.rc -- Handle cookie (unique id) confirmations
Pm-jacron.rc -- Procmail: Run cron once a day
Pm-jadaemon.rc -- Handle DAEMON messages by changing subject
Pm-jadate1.rc -- 'Tue, 31 Dec 1997' date parser from variable INPUT
Pm-jadate2.rc -- 'YYYY-MM-DD' ISO date parser from variable INPUT
Pm-jadate3.rc -- 'Tue Nov 25 19:32:57' date parser from variable INPUT
Pm-jadate4.rc -- make RFC 'Mon, 1 Dec 1997 17:41:09' and parse values
Pm-jadate5.rc -- 'Fri Jun 19 18:51:56 1998' date parser from var INPUT
Pm-jadate.rc -- Read date from the message hdrs: From_, Receved:
Pm-jadup.rc -- Procmail: Handle duplicates; store to separate folder
Pm-jaempty.rc -- check if message body is empty
Pm-jafrom.rc -- get message's best FROM field without calling `formail'
Pm-jafwd.rc -- Controlling forwarding remotedly
Pm-jalist.rc -- Subroutine to detect mailing LIST from message.
Pm-jamime-decode.rc -- decode MIME body contents; quoted-printable, base64
Pm-jamime-kill.rc -- General MIME attachment killer (vcards, html)
Pm-jamime.rc -- subroutine to read mime boundary etc. variables
Pm-jamime-recode.rc -- re-encode MIME Header: Subject, From as quoted-printable
Pm-jamime-save.rc -- save message's MIME attachement (one file) to a file
Pm-janetmind.rc -- handle http://minder.netmind.com/ messages
Pm-janslookup.rc -- run nslookup on variable INPUT
Pm-jaorig.rc -- Extract embedded original message (simple recipe)
Pm-japing.rc -- reply shortly to message "Subject: ping"; account ok
Pm-japop3.rc -- Remotedly download messages by mail command request
Pm-jarandf.rc -- pick (rand)om line from (f)ile
Pm-jasrv-check.rc -- check FILE validity, subroutine for File Server
Pm-jasrv-daemon.rc -- server request check, subroutine for File Server
Pm-jasrv-err.rc -- send message, subroutine for File Server
Pm-jasrv-from.rc -- compose reply, subroutine for File Server
Pm-jasrv-msg.rc -- send message, subroutine for File Server
Pm-jasrv-multi.rc -- send multipart MIME message, subroutine for FileSrv
Pm-jasrv.rc -- MIME capable Procmail File server
Pm-jasrv-req.rc -- server request check, subroutine for File Server
Pm-jasrv-send.rc -- server request check, subroutine for File Server
Pm-jastore.rc -- Store messagee to inbox or gzip inbox
Pm-jasubject.rc -- Subject field cleaner and canonicalizer (Re:)
Pm-jatime.rc -- "hh:mm:ss" time parser from variable INPUT
Pm-jaube1.rc -- Jari's UBE filter. Subroutine 1
Pm-jaube-keywords.rc -- Bare bones word list based UBE filter
Pm-jaube-prg-spamprobe.rc -- Interface to Annoyance Filter program
Pm-jaube-prg-bmf.rc -- Interface to Bayesian Mail Filter program
Pm-jaube-prg-bogofilter -- Interface to bogofilter program
Pm-jaube-prg-bsfilter.rc -- Interface to Bsfilter program
Pm-jaube-prg-ifile -- Interface to ifile program
Pm-jaube-prg-runall.rc -- Interface to all Bayesian filter programs
Pm-jaube-prg-spamassassin -- Interface to spamassassin program
Pm-jaube-prg-spamoracle.rc -- Interface to Spamoracle program
Pm-jaube-prg-spamprobe.rc -- Interface to Spamprobe program
Pm-jaube.rc -- Unsolicited Bulk Email (UBE) filter.
Pm-javac.rc -- Procmail: Vacation framework recipe (id-cache)
Pm-javar.rc -- Global variable definitions
procmail-lib-2009.1202/doc/manual/index.html000066400000000000000000000005331130547513300204250ustar00rootroot00000000000000 procmail-lib-2009.1202/doc/manual/index.src000066400000000000000000000052751130547513300202600ustar00rootroot00000000000000Document id #T2HTML-TITLE Procmail Module library documentation #T2HTML-METAKEYWORDS Procmail, library, Spam, UBE #T2HTML-OPTION --name-uniq #T2HTML-OPTION --html-frame #T2HTML-OPTION --css-code-bg #T2HTML-OPTION --css-code-note #T2HTML-OPTION Note: #T2HTML-OPTION --simple Copyright (C) 1997-2010 Jari Aalto License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). This page documents of part of the files included in Procmail Module Library project. Each modules is can be used as a plug-in. Some can be used as subroutines to your own programs and some are self containing recipes. There is no user or site specific settings in these modules. An attempt to minimize the use of external processes was the design goal. The modules try to use pure procmail way as much as possible e.g. to get date and directly from message without calling expensive shell `date'. It is important to remember that procmail is run on every incoming message and every CPU tick spent counts. Document control This document has been automatically generated from the procmail files with 2 small perl programs in the following manner: % perl -S ripdoc.pl `ls pm-ja*.rc|sort` > pm-lib.raw % perl -S t2html.pl \ --html-frame \ --base http://freshmeat.net/projects/procmail-lib \ --button-previous http://freshmeat.net/projects/procmail-lib \ --title "Procmail module documentation" \ --author "Jari Aalto" \ --meta-keywords "procmail, sendmail, programming, library" \ --meta-description "Procmail plug-in module documentation" \ --name-uniq \ --Out \ pm-lib.txt The perl program assume that the documentation sections have been written in Technical Text Format. The perl program `ripdoc.pl' can be found at CPAN entry http://www.cpan.org/modules/by-authors/id/J/JA/JARIAALTO/ and `t2html.pl' is available at project #URL. procmail-lib-2009.1202/doc/manual/index.txt000066400000000000000000007234561130547513300203200ustar00rootroot00000000000000Document id #T2HTML-TITLE Procmail Module library documentation #T2HTML-METAKEYWORDS Procmail, library, Spam, UBE #T2HTML-OPTION --name-uniq #T2HTML-OPTION --html-frame #T2HTML-OPTION --css-code-bg #T2HTML-OPTION --css-code-note #T2HTML-OPTION Note: #T2HTML-OPTION --simple Copyright (C) 1997-2010 Jari Aalto License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). This page documents of part of the files included in Procmail Module Library project. Each modules is can be used as a plug-in. Some can be used as subroutines to your own programs and some are self containing recipes. There is no user or site specific settings in these modules. An attempt to minimize the use of external processes was the design goal. The modules try to use pure procmail way as much as possible e.g. to get date and directly from message without calling expensive shell `date'. It is important to remember that procmail is run on every incoming message and every CPU tick spent counts. Document control This document has been automatically generated from the procmail files with 2 small perl programs in the following manner: % perl -S ripdoc.pl `ls pm-ja*.rc|sort` > pm-lib.raw % perl -S t2html.pl \ --html-frame \ --base http://freshmeat.net/projects/procmail-lib \ --button-previous http://freshmeat.net/projects/procmail-lib \ --title "Procmail module documentation" \ --author "Jari Aalto" \ --meta-keywords "procmail, sendmail, programming, library" \ --meta-description "Procmail plug-in module documentation" \ --name-uniq \ --Out \ pm-lib.txt The perl program assume that the documentation sections have been written in Technical Text Format. The perl program `ripdoc.pl' can be found at CPAN entry http://www.cpan.org/modules/by-authors/id/J/JA/JARIAALTO/ and `t2html.pl' is available at project #URL. Pm-jaaddr.rc -- extract 'foo@some.com' email address from variable INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc extracts the various components of email address from variable `INPUT'. You can do quite a lot interesting things with your email address. One of the tricks that you could use if you don't have sendmail plus addressing capabilities, is that you put the additional infomation to the RFC comment. Eg. If you read and followup to posts in usenet games groups, you could use: From: (John Doe+usenet.games) Or if your email address's localpart (that's characters before @) already signify your First and surname, you don't need to repeat it in comment. However, place special marker "+" to mark additional information part for your procmail recipes: From: (+usenet.games) The use of RFC comment should work everywhere because RFC requires that comments are preserved along with the address information. If you would have sendmail plus addressing capabilities you would have used: From: (John Doe) The idea is that the list infomation is readily available from the email. The following recipe will derive the plus information and use it directly as a mailbox where to drop the message. If The Editor: Emacs, means anything to you, you can program it to generate the appropriate From headers automatically when you send mail from Gnus Mail/Newsreader MUA. Drop me a message if you need an example how a piece of Emacs lisp code makes those magic RFC plus addresses in the background while you compose the body of the message. RC_EMAIL = $PMSRC/pm-jaaddr.rc TOME = "(login1|login2)" :0 *$ ^TO\/.*$TOME.* { INPUT = $MATCH INCLUDERC = $RC_EMAIL PLUS = $COMMENT_PLUS # If COMMENT_PLUS was defined, we found "+" # address which contain "usenet.games". Save it to # folder. :0 : * PLUS ?? [a-z] $PLUS } Notes 1998-05 David Hunt also mentioned that "you need to remember that some MTAs, (qmail for one, and soon vmail) use a dash ( - ) as the subaddress delimiter. So you'll want to allow for that in your code". For this reason the email part accepts both "-" and "+". The RFC comment however accepts only "+" and "--". Example input "From: foo+procmail@this.site.com (Mr. foo)" traditional "From: foo-procmail@this.site.com (Mr. foo)" new styled NOTE: M$SOFT mailers tend to send idiotic smart quotes "'Mr. foo'" and this recipe ignores these two quotes ["'] as if message had only the standard ["] Returned values ADDRESS "foo+procmail@this.site.com" containing the email address without <> ACCOUNT "foo+procmail" all characters before @ ACCOUNT1 "foo" characters before plus: account1+account2@site Note, if there is no "+", this is same as ACCOUNT. ACCOUNT2 "procmail" _only_ set if plus found: account1+account2@site SITE "this.site.com" all characters after @ DOMAIN "site.com" the main domain, preceding words in site are considered subdomain (local) addresses. sub.sub.domain.net SUB "this.site" all the sub-domain names without the NET part. SUB1 "site" The first subdomain counted from the _RIGHT_ after NET SUB2 "this" Second subdomain. SUB3 "" Third subdomain. SUB4 "" Fourth subdomain. NET "com" last characters after last period ( net,com,edu ...) COMMENT Anything unside parenthesis (Mr. Foo) or if no parentheses found, then anything between quotes "Mr. Foo" COMMENT_PLUS Anything after the "+" in the comment, like "Mr Foo+mail.usenet" --> "mail.usenet" Note: some MTA's don't allow + character, so use alternatively '--': "Mr Foo--mail.usenet" --> "mail.usenet" Additionally there is variables DOT1 DOT2, which behave like ACCOUNT1 and ACCOUNT2, but in respect to dotted firstname.surname type address: john.doe@site.com ACCOUNT1 = john.doe ACCOUNT2 = DOT1 = john DOT2 = doe If there is plus, the ACCOUNT2 is defined john.doe+foo@site.com ACCOUNT1 = john.doe ACCOUNT2 = foo DOT1 = john (in respect to ACCOUNT1) DOT2 = doe (in respect to ACCOUNT1) Variable ERROR is set to "yes" if INPUT wasn't recognized or parsing the address failed. Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. Call arguments (variables to set before calling) INPUT = string-to-parse Usage example Read From field and address from it. This is lot faster than using external `formail' call. PMSRC = $HOME/pm RC_ADDR = $PMSRC/pm-jaaddr.rc :0 * ^From:\/.*@.* { INPUT = $MATCH # Turn off the logging while executing this part VERBOSE="off" INCLUDERC = $RC_ADDR VERBOSE="on" :0 * ERROR ?? yes { # Hmm, no std email address found. Any other ideas? } } Pm-jabup.rc -- Keeep N arriving message backup in separate directory File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details . Description Preserve last N arriving messages in a separate sub-directory. This should be your safety-belt recipe that you put to the beginning of your .procmailrc. Procmail saves the backup files with names like: msg.rcG msg.scG msg.3YS1, msg.4YS1, msg.VYS1, msg.fYS1 to the backup directory. Note: this recipe will alawys call shell commands for each message you recive. That is needed because cleaning of the backup directory. If you receive only small number of messages per day, the performance drop of your .procmailrc is not crucial. But if you store many messages per day, then the shell calls may be a performance problem. In that case, consider moving the cleanup to the pm-jacron.rc module (The cleanup is run only once a day, not for every message) John Gianni send his simple bsckup script to Jari, who packaged and generalized the code. The code is reused with John's permission and maintaining responsibility was transferred to Jari Required settings (none) Call arguments (variables to set before calling) o JA_BUP_MAX, How many messages to keep at maximum. 32 is default o JA_BUP_DIR, Where to store the messages. $HOME/Mail/bup by default o JA_BUP_FILES, regexp to match the saved files. Procmail default. o JA_BUP_CHECK_DIR. Once you have verified that this recipe works, that directories are ok, please set this flag to "no" to prevent running unnecessary `test' command for each email. Usage example You only want to keep backup of messages that are not from mailing lists. You may want to use TO_ macro to detect addresses better, this example matches against all headers LISTS = "(procmail|list-1|list-2)" JA_BUP_DIR = $HOME/Mail/backup/. # Create the path too JA_BUP_MAX = 42 # this should be enough :0 *$ ! $LISTS { INCLUDERC = $PMSRC/pm-jabup.rc } If you get many messages, please don't use this module. Instead see pm-jacron.rc where similar backup work is done better. Pm-jacookie1.rc -- Generate unique id from INPUT variable. File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description When given a string, this subroutine returns a unique number representing a string, a cookie. Required settings (none) Call arguments (variables to set before calling) o INPUT, String from which the magic-cookie is calculated o JA_COOKIE_CMD: shell command to read INPUT and return decimal or hex cookie string as one continuous block of characters. It decaults to HP-UX `cksum', but your system may have `md5' or `chksum' Return values o Variable OUTPUT will contain the cookie. Example usage INPUT = "foo@site.com" JA_COOKIE_CMD = "md5" # or chksum INCLUDERC = $PMSRC/pm-jacookie1.rc cookie = $OUTPUT Pm-jacookie.rc -- Handle cookie (unique id) confirmations File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with program. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Visit Overview of features o Each user must register himself to cookie cache before he is considered "known" o Unless user return the generated cookie string; which is typically a decimal or hex number, he is not considered as known and should not have access to services you provide. o Can be used as a "doorbell" spam/UBE shield Description This recipe handles generating the cookie to new users, comparing the returned cookie against the original one and passing known users through if they already had returned their cookie. When you run automatised scripts, eg. to manage mailing lists where users can subscribe and unsubscribe, you have better to install safety measure so that someone can not subscribe his enemy to 30 mailing lists. The *cookie* is any continuous block of random characters that is sent to person who wanted to use the service. He must send back the *cookie* before the service starts an action, like subscribe. If someone forges the From address to pretend to be someone else and then subscribes as-beeing-someone-else to a mailing list, the cookie protects this from happening. The cookie is sent to someone-else, and he must return the cookie before the "subscribe" service is activated. Obviously this someone-else will not be interested in sending back the cookie and thus the forgery fails. Isn't that simple, but efective protection against misuse? Should I use this as Challenge-Response Spam shield? Unsolicited Bulk Email aka Spam is crawling from every possible domain thinkable, so you might think that a challenge-response policy could be deployed to regular email communication as well. The idea would be that unknown people are requested to "join" to a white list, before discussion is initiated with them. Bulk email shotguns do not reply to challenges (here: cookies), so confirmations are not returned. Individual people that want to talk, *may* want to return the cookies. Sounds like a perfect Unsolicited Bulk Email shield? No more non-invited mail? Wrong. Don't use this module for that. The whole idea of challenge-response is flawed and causes trouble for every person who tries to contact. Imagine for 10 people using C-R systems; they would all need to authenticate themselves. Who is going to believe that he is not replying to a spammer who is collecting email addresses? And what about automatic messages that might be received -- there is no artificial intelligence to deparate "human" messages from automatically generated messages, so challenges just increase the overall mail traffic. Every C-R system doubles the mail traffic and becomes spam problem by itself. In short, don't use this module for implementing a C-R system to block regular mail to you. How it works By default the cookie generated uses CRC 32 `cksum', but if you have md5, you should use it. The cookie is generated from the reply address and immediately stored to cookie database file with entry DATE FROM-a COOKIE-a DATE FROM-b COOKIE-b If this was a new user or an old user, who has not registered his cookie yet, then original message is sent back to the sender with instructions: "please place the magic string to Subject line and resent the message." When cookie is returned back, a new line to the database is added, simply by adding a duplicate entry. The file now looks like this: DATE FROM-a COOKIE-a DATE FROM-b COOKIE-b DATE FROM-a COOKIE-a When there is two or more same entries, like FROM-a, the address is supposed to be known and person behind it "cleared". Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jadate.rc o pm-jacookie1.rc o pm-jastore.rc Call arguments (variables to set before calling) o JA_COOKIE_SEND, flag. Default is "yes". Set to "no" if you want to take full control of the message returned to user. You can check variable `ERROR' and use `key' which holds the unique `cookie' o JA_COOKIE_CACHE, cache to determine if this is new user or not. o JA_COOKIE_AUTO_KEY, flag. If set to "yes"; the cookie is initially put to the Subject when the message is bounched back. Receiver only has to press "r" to reply to send the cookie and message back (convenient). You set this flag to "no" when you want to avoid accidnebts eg. when receiver is about to subscribe to a mailing lists: he has to manually insert the cookie into subject. But keep flag to "yes" if you use this module to get your friends registered easily. o JA_COOKIE_KEYS, the cookie database. Email address and person's access cookie. o JA_COOKIE_RC, dubroutine to generate the cookie id from INPUT. By default uses CRC 32. o JA_COOKIE, the string from which the cookie will be generated. If you already have the return addres for the sender derived, you should assing a value to this to save unnecessary formail call. Returned values ERROR will contain the efective action when this recipe file ends o "new-user", This is first message from sender. o "known-user", message has email that has been "cleared" ie. cookie had been returned and user registered. o "key-mismatch", This is at least second message from sender. But he dind't send the confirmation in this message. `key' is an internal variable in this recipe file and will hold the cookie id in case of "new-user" and "key-mismatch". You may want to use it if you generate your own reply. Example usage for UBE shield This is what I use to prevent unknown people from sending me UBE. It takes a bit extra, but they can easily return the message. Fill in the missing variables, this won't work out of the box for you. WORK = "(domain1|domain2|domain3)" LISTS = "(procmail|list-2|list-3|list-4)" VALID = "(postmaster|abuse|$LISTS|$WORK)" RC_COOKIE = $PMSRC/pm-jacookie.rc UBE_SPOOL = $HOME/Mail/junk.ube.spool # Save spam here :0 *$ ! From:.*$VALID *$ ! ^FROM_DAEMON { JA_COOKIE_SEND = "yes" # Activate it INCLUDERC = $RC_COOKIE :0 : * ! ERROR ?? known-user $UBE_SPOOL # ... Past this point: it was user in whitelist, so the # recipes after this block will take care of it } Example usage for subscriptions $RC_COOKIE = $PMSRC/pm-jacookie.rc ...Mailing lists handled here... ...Your work messages filed here.. TO = `formail -rt -zxTo:` # We need this elswhere JA_COOKIE_TO = $TO # For List-X all subscribe requests must # be confirmaed * ^TO_()list-x * ^Subject: +subscribe\> { JA_COOKIE_SEND = "no" INCLUDERC = $RC_COOKIE :0 * ERROR ?? known-user { # User sent the subsribe request again, allow joining # immediately. } :0 E { # Because the Send was set to "no"; we're in charge # to send a reply to the user. # ...generate suitable message with formail -rt } } # End of example Pm-jacron.rc -- Procmail: Run cron once a day File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at Description Framework for all cron tasks that can be run once a day. This is a wrapper recipe to your cron task list: when the day changes, you cron includerc is called. Required settings PMSRC must point to source directory of procmail code. This recipe will include o pm-javar.rc o pm-jadate.rc Call arguments (variables to set before calling) o JA_CRON_RUN_FLAG, You _must_ define this flag file. o JA_CRON_DATE_FILE, File where the date information, last cron run, is kept. Defaults to $HOME/.yymmdd o JA_CRON_RC, your includerc which is run when cron triggers. A file `JA_CRON_RUN_FLAG' which defaults to ~/.yymmdd.run is created when your includerc, that contains list of cron tasks, is run. If new mail arrives while your cron recipes are still running, you should prevent invoking the cron again by checking if this file exists. When all the cron tasks have been run, this flag file is removed. Remember to use "w" flag in your cron recipes where necessary to serialize the work. Return values (none) Usage example Save backups to separate directory, but do cleaning only once a day We do not keep backups from mailing list messages LISTS = "(procmail|list-1|list-2)" BACKUP_DIR = "$HOME/Mail/backup/." # Store backups: separate files to directory :0 c: *$ ! $LISTS $BACKUP_DIR # Run JA_CRON_RC once a day. It contains all daily cron tasks CRON_RC = $PMSRC/pm-jacron.rc # the framework JA_CRON_RC = $PMSRC/pm-mycron.rc # the tasks to do JA_CRON_RUN_FLAG = $HOME/.cron-running # define this! # Do not enter here if message arrived at the same day when # the cron is already running. The CRON_RC takes care # of deleting the file when cron has finished. :0 *$ ! ? $IS_EXIST $JA_CRON_RUN_FLAG { INCLUDERC = $CRON_RC } The *pm-jacron.rc* file may contain anything. For example to clean the backup directory; you add these statements there # rm dummy: if ls doesn't return files, make sure rm has # at least one argument. # # ls -t: list files; newest first # # sed: chop $max newest files from the listing, leaving the # old ones max = 32 :0 hwic | cd $BACKUP_DIR && $RM -f dummy `ls -t msg.* | $SED -e 1,${max}d` # End of file pm-mycron.rc Pm-jadaemon.rc -- Handle DAEMON messages by changing subject File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description When you send a message to a address that had delivery troubles, you get a DAEMON message back explaining the error problem. I usually want to save these daemon mesaages to a different folder and check the folder from time to time. A typical daemon message is like this (shortened) From: Mail Delivery Subsystem Subject: Warning: could not send message for past 4 hours The original message was received at... ----- Transcript of session follows ----- Deferred: Connection timed out ----- Original message follows ----- [YOUR MESSAGE AS YOU SENT IT WITH HEADERS] Well, when I read the subjects, I do not like the standard error messages, but I also like to know to which address the delivery failed and what was the original subject. This small recipe changes the daemon message's Subject to Subject BRIEF-ERROR-REASON, SENT-TO-ADDRESS, ORIGINAL-SUBJECT and from that you can immediately tell if you should be worried Eg. if SENT-TO-ADDRESS was your friend's, then you want to take actions immediately, but if it were your complaint to UBE message to postmaster, you don't want to bother reading that daemon message. Here are some real examples: fatal errors,postmaster,ABUSE (Was: Super Cool Site!) Host unknown,postmaster,ABUSE (Was: A-Credit Information) undeliverable,postmaster,Could you investigate this spam Warning-Returned,friend,Have you looked at this Required settings PMSRC must point to source directory of procmail code. This subroutine needs scrips o pm-javar.rc Call arguments (variables to set before calling) o `JA_DAEMON_SAVE'. This is by default `yes' which causes the original subject to be saved under header field `X-Old-Daemon-Subject'. If you don't want that extra header generated, set this variable to `no' o `JA_DAEMON_REGEXP', which messages to trigger Return values o Variable ERROR will be set to "yes" if daemon message was handled otherwise; value is "no" Usage example Just add this recipe somewhere in your .procmailrc. The place where you would put this daemon message trapper subroutine is crucial: think carefylly how you order your recipes. One suggested order could be: backup important messages, cron-subroutine, handle duplicates, DAEMON MESSAGES, plus addressed message, server message (file server, ping responder...), MAILING LISTS, send possible vacation replies only after all above, apply kill file, detect mime, save private messages and las FILTER UBE. PMSRC = $HOME/pm RC_DAEMON = $PMSRC/pm-jadaemon.rc DAEMON_MBOX = $HOME/Mail/junk.daemon.mbox ... INCLUDERC = $RC_DAEMON :0 : # If that was a daemon message, save it * ERROR ?? yes $DAEMON_MBOX Pm-jadate1.rc -- 'Tue, 31 Dec 1997' date parser from variable INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc parses date from variable `INPUT' which has string "Week, Daynbr Month Year" Example input "Tue, 31 Dec 1997" -- without comma "Tue 31 Dec 1997" -- with comma Returned values YYYY = 4 digits YY = 2 digits MON = 3 characters MM = 2 digits DAY = 3 characters DD = 2 digits hh = 2 digits If available mm = 2 digits If available ss = 2 digits If available TZ = 5 characters If available Variable ERROR is set to `yes' if it couldn't recognize the INPUT and couldn't parse the basic YYYY, YY, MM, DD variables. Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. Call arguments (variables to set before calling) INPUT = string-to-parse The INPUT can have anything after "Week, dayNbr Month Year", or before it: you can pass a string like "Thu, 13 Nov 1997 11:43:23 +0200". Usage example The first *Received* header will tell when the message was received by your mailserver. We parse the date and avoid calling expensive `date' command. PMSRC = $HOME/pm RC_DATE_WDMY = $PMSRC/pm-jadate1.rc #Week-Day-Month-Year parser # Get time from first header, it ends like this: # # Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200 :0 *$ ^Received:.*;$s+\/...,$s+$d.* { INPUT = $MATCH # Turn off the logging while executing this part VERBOSE=off INCLUDERC = $RC_DATE_WDMY VERBOSE=on :0 * ERROR ?? yes { # Use some other way to get the time or shout loudly } } Pm-jadate2.rc -- 'YYYY-MM-DD' ISO date parser from variable INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc parses date in format "YYYY-MM-DD hh:mm:ss" like `1997-12-01' and sets following variables whenever called YYYY = 4 digits YY = 2 digits MON = 3 characters MM = 2 digits DD = 2 digits hh = 2 digits If avaliable mm = 2 digits If avaliable ss = 2 digits If avaliable Variable ERROR is set to `yes' if it couldn't recognize the INPUT and couldn't parse the basic YYYY, YY, MM, DD variables. Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. Call arguments (variables to set before calling) INPUT = string-to-parse Last string in INPUT that matches number sequence `NNNN-NN-NN' is parsed. Usage example PMSRC = $HOME/pm RC_DATE_ISO = $PMSRC/pm-jadate2.rc # ISO date parser INPUT = "This is 1800-10-11, a very old date" # Turn off the logging while executing this part VERBOSE="off" INCLUDERC=$RC_DATE_ISO VERBOSE="on" Pm-jadate3.rc -- 'Tue Nov 25 19:32:57' date parser from variable INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc parses date from variable INPUT which has string "Week, Month dayNbr hh:mm:ss yyyy", Example Tue Nov 25 19:32:57 1997 Returned values YYYY = 4 digits YY = 2 digits MON = 3 characters MM = 2 digits DAY = 3 characters DD = 2 digits hh = 2 digits mm = 2 digits ss = 2 sigits Variable ERROR is set to "yes" if it couldn't recognize the INPUT. Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. Call arguments (variables to set before calling) INPUT = string-to-parse Usage example The first *Received* header will tell when the message was received by the mailserver. Parse the date and avoid calling expensive `date' command. PMSRC = $HOME/pm RC_DATE_WMDT = $PMSRC/pm-jadate4.rc #Week-Month-Day-Time parser # Get time from X-From-Line: Which was added by my MDA # X-From-Line: procmail-request@informatik.rwth-aachen.de \ # Tue Nov 25 19:32:57 1997 :0 c *$ ^X-From-Line:\/.* { INPUT = $MATCH # Turn off the logging while executing subroutine VERBOSE=off INCLUDERC = $RC_DATE_WMDT VERBOSE=on :0 * ERROR ?? yes { # Use some other way to get the time or shout loudly } } Pm-jadate4.rc -- make RFC 'Mon, 1 Dec 1997 17:41:09' and parse values File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine calls shell command date once and prses the values. This should be your last resort if you haven't got the date values by any other means. This subroutine assumes that the DATE command knows the following % specifier formats (HP-UX) Y NNNN year h MON month d NN day a WEEK Like "Mon" H NN hour M NN min S NN sec Returned values DATE = RFC date in format "Mon, 1 Dec 1997 17:41:09" This is same as what you would see in From_ YYYY = 4 digits YY = 2 digits MON = 3 characters MM = 2 digits DAY = 3 characters DD = 2 digits hh = 2 digits mm = 2 digits ss = 2 sigits Variable ERROR is set to "yes" if values couldn't be set Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jadate1.rc Call arguments (variables to set before calling) (none) Usage example The First Received line will tell when the message was received by the MDA. If thata fails, then get date from the system. If you send test messages to # yourself, you don't usually put From_ header in it and thus there is # no date information in 'dry run' tests. # Get time from first eader, which is always same in my system # Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200 INCLUDERC = $PMSRC/pm-javar.rc # to get $s $d definitions TODAY # Clear it :0 *$ ^Received:.*;$s+\/...,$s+$d.* { INPUT = $MATCH INCLUDERC = $PMSRC/pm-jadate1.rc TODAY = "$YYYY-$MM-$DD" } # Check that variable did get set, if not then we have to call # another date subroutine: Call shell then to find out date # # You could also do this with ':0 E', but this is more # educational :0 *$ ! $TODAY^0 { INCLUDERC = $PMSRC/pm-jadate4.rc # Get date from Shell then TODAY = $YYYY-$MM-$DD } Pm-jadate5.rc -- 'Fri Jun 19 18:51:56 1998' date parser from var INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc parses date from variable INPUT which has string "WeekDay Month dayNbr Year" Example input "Fri Jun 19 18:51:56 1998" -- without comma "Fri, Jun 19 18:51:56 1998" -- with comma Returned values YYYY = 4 digits YY = 2 digits MON = 3 characters MM = 2 digits DAY = 3 characters DD = 2 digits hh = 2 digits If available mm = 2 digits If available ss = 2 digits If available TZ = 5 characters If available Variable ERROR is set to "yes" if it couldn't recognize the INPUT and couldn't parse the basic YYYY,YY,MM,DD variables. Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. Call arguments (variables to set before calling) INPUT = string-to-parse The INPUT can have anything after "Week, dayNbr Month Year", or before it: you can pass a string like "Fri Jun 19 18:51:56 1998 11:43:23 +0200". Usage example The first *Received* header will tell when the message was received by your mailserver. We parse the date and avoid calling expensive `date' command. PMSRC = $HOME/pm RC_DATE_WDMY = $PMSRC/pm-jadate5.rc #Week-Day-Month-Year parser # Get time from first header, it ends like this: :0 *$ ()\/From .* { INPUT = $MATCH # Turn off the logging while executing this part VERBOSE=off INCLUDERC = $RC_DATE_WDMY VERBOSE=on :0 * ERROR ?? yes { # Use some other way to get the time or shout loudly } } Pm-jadate.rc -- Read date from the message hdrs: From_, Receved: File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This recipe will scan several headers to find the date string. When suitable header is found and the parsing has succeeded, the return variables are set. The Date values reflects the arrive time of the message; not the sending time. If nothing works, a shell call `date' is used as a last resort. Returned values YYYY = 4 digits YY = 2 digits MON = 3 characters MM = 2 digits DAY = 3 characters DD = 2 digits hh = 2 digits if available mm = 2 digits if available ss = 2 digits if available Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jadate1.rc o pm-jadate3.rc o pm-jadate4.rc Call arguments (variables to set before calling) (none) Usage example INCLUDERC = $PMSRC/pm-jadate.rc # now we have all date variables that we need # $TODAY = $YYYY-$MM-$DD Pm-jadup.rc -- Procmail: Handle duplicates; store to separate folder File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This recipe stores duplicate messages to separate folder Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jastore.rc Call arguments (variables to set before calling) o JA_ID_CACHE, Where to keep the Message-Id cache. o JA_ID_CACHE_SIZE, how big cache, defualt is 8192 o JA_ID_MBOX, where to store duplicate messages when delivering message to duplicate mbox. o JA_ID_IGNORE, if set to "yes", then ignore duplicate check Return values o Variable ERROR is set to "yes" if duplicate message was trapped, otherwise value is "no" Usage Example For simple usage, just put this somewhere after backup recipes RC_DUP = $PMSRC/pm-jadup.rc ... INCLUDERC = $RC_DUP When you are testing messages, you send them over and over to .procmailrc; which means that same message should not be trapped by duplicate check. You can call `procmail' with option "-a test" which will set pseudo variable `$1'. The recipe below sets flag `JA_ID_IGNORE' to "yes" if test is on going and the duplicate filter should be bypassed. RC_DUP = $PMSRC/pm-jadup.rc ARG = $1 # Copy pseudo variable to $ARG :0 * ARG ?? test { JA_ID_IGNORE = "yes" } # Some microsoft product is known to send same message ids # over and over. If we detect one, tunr off the duplicate test, # because it would trash every message. # :0 * ! ^X-msmail * ! ^Message-ID: * { JA_ID_IGNORE = "yes" } # Run this command every time a duplicate message is found. # It writes a small log entry to MY_LOG INCLUDERC = $RC_DUP :0 hwic: * ERROR ?? yes | echo " [duplicate]" >> $BIFF Pm-jaempty.rc -- check if message body is empty File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This simple includerc will define variable BODY_EMPTY to "yes" or "no" when called like this You can file empty messages to separate folder based on this value INCLUDERC = $PMSRC/pm-jaempty.rc :0 * BODY_EMPTY ?? yes the-empty-mail-folder This is more designed to be part of other modules. If you just want to check for empty message, a simpler recipe like this might be better: INCLUDERC = $PMSRC/pm-javar.rc :0 B: # if body has only whitespace characters *$ ! $NSPC the-empty-mail-folder Required settings (none) Pm-jafrom.rc -- get message's best FROM field without calling `formail' File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc extracts the most likely FROM address from the message. The order of the search is Reply-to, From_, Sender, From and if none found, then as a last resort, call `formail'. You would usually use the returned value for logging purposes. Avoiding extra formail call could be usefull if you receive lot of messages per day. Example input (none) Returned values OUTPUT, containing the derived FROM field Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. You nee procmail 3.11pre7 in order to use this subroutine. (due to formail -z switch) Call arguments (variables to set before calling) (none) Usage example INCLUDERC = $PMSRC/pm-jafrom.rc FROM = $OUTPUT # now we have the 'best' FROM field Pm-jafwd.rc -- Controlling forwarding remotedly File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Overview of features o Requires latest procmail (formail -z switch) o You can send forward-on and forward-off control messages via email to control the forwarding in remote site. Description This includerc makes it possible to control your message forwarding via simple remote email message. Thanks to Era Eriksson and Timothy J Luoma who gave the initial idea to this forwarding module in the procmail mailing list 1997-10-07. Activating the forwarding by hand If you want to activate the forwarding from the local site where this module is, then you could simply write the forward address to the file pointed by *JA_FWD_FILE* which is `~/.forward-address' by default. % echo Me@somewhere.com > ~/.forward-address and when you no longer need forwarding, then remove that file. But really, this module is not used for that purpose, because it is lot easier to write :0 ! Me@somewhere.com as a first statement in your .procmailrc when you want to forward your mail to another account. Activating the forwarding by remote email Suppose you're on the road and suddenly realize that you want your mail forwarded to the current account, then you send following control message Subject: forward-on password new-address@bar.com To: my-account@bar.com From: onTheRoad@some.com That message is is enough to get the mail forwarded to the address new-address@bar.com This script will respond to address From that the current forwarding is now pointing to address "new-address@bar.com". Deactivating forwarding by remote email The message is very similar, but the Subject header says Subject: forward-off password And no other fields are checked. Not even Reply-To. In this case the confirmation message is sent directly back to From address. Activating forwarding via body message If for some reason you have no control over the headers of email, eg when you send GSM-Mail message from your phone to your account: EMAIL foo@bar.com FORWARD-ON PASSWORD new-address@bar.com The email message looks like this: From: GenEmail Date: Thu Sep 17, 11:42am +0200 To: "'Foo.Bar'" Subject: Message 03384874987 FORWARD-ON PASSWORD new-address@bar.com Instead of looking at the `Subject' field, you can get this module to look at the first words in the body field. See variable `JA_FWD_CONTROL_FIELD' which you want to set to "body". Restricting the control message aceptance If you only have persistent accounts, then you should set the *JA_FWD_FROM_MUST_MATCH* to match those addresses that you have. The following setting says that only control messages sent from these addresses are accepted. Nobody else can't change your forwarding settings. JA_FWD_FROM_MUST_MATCH = ".*(acc1@a.com|acc2@b.com)" Hm, that's not a bullet proof, because someone may in theory forge the From address. You probably should also set this variable to point to accounts where the mail can be legally forwarded to. Then, even if the imposter forges the From address; he can't get the email forwarded anywhere else than to the valid locations. JA_FWD_TO_MUST_MATCH = $JA_FWD_FROM_MUST_MATCH Consider also setting *JA_FWD_PASSWORD_CASE* to Procmail flag `D' which causes your control word "forward-on" and password to be case sensitive. Diagnostics If you don't receive confirmation message, then your control message was ill formed or you're not in the *JA_FWD_FROM_MUST_MATCH* list. There is no notification sent on failure, so that no attacker can draw conclusions. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc Installation You should preset all necessary variables prior adding the includerc command to your .procmailrc. Here is one simple setup #JA_FWD_SENDMAIL = "tee $HOME/test.mail" # Uncomment if testing JA_FWD_COPY = no # no copies stored while forwarding JA_FWD_PASSWORD_CASE= "D" # case sensitive JA_FWD_PASSWORD = "MyMagicString" JA_FWD_FROM = $FROM # This is already known. INCLUDERC = $PMSRC/pm-jafwd.rc Comments from the author Please realise that when you set the forwarding from a remote site, be very carefull when you type in the forward address or your mail ends up to somebody else's mailbox. Also I recommend that you keep *JA_FWD_COPY* to *yes* so that your local account always keep the copy of forwarded message. A step further would conventionally encrypt(1)'ing your forwarded messages. This way even your top secret messages would be mostly safe even if they end up to someone else's mailbox. File layout tinybm.el/&tags and tinytab.el for the 4 tab text placement. Pm-jalist.rc -- Subroutine to detect mailing LIST from message. File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine tries to detect and derive the mailing list name as it appears in some of the known methods that ezlm, smarlist, listserv, majordomo etc. normally use. After this subroutine has been applied to message the variable `LIST' contains the mailing list name. Subroutine adaptively finds new new mailing lists from the messages. The alternative to subscribing to many mailing lists is to read them from web archives. Even better way is to use NNTP server at http://www.gmane.org which allows you to post as you would to a regular newsgroup. Consider using the NNTP interface and you may save you from receiving lot of messages that can already be found from Gmane's server. Quick start If you just want to jump in and use this module and you noteice that some list isn't trapped, please set o JA_LIST_HEADER_REGEXP to match the From: field If you want to make some list more unique, like if name "Alert" was detected as a list name, please set o JA_LIST_MAKE_UNIQUE to match the list name, like "Alert". After that the list name will be converted to HOST-LIST format. Sendmail plus type method for list subscription If you can use sendmail type PLUS addressing capabilities, you may not be interested in this module, because you have an alternative way to handle mailing list messages. The extra information after "+" is available to procmail scripts via `$ARG' pseudo variable when procmail is the LDA. Let's suppose you want to subscribe to procmail mailing list and want to save all messages to folder list.procmail, then you'd subscribe with address: login+list.procmail@site.com If your email host doe snot provide the plus addressing then it the traditiona approach have been to add a piece of recipe to `~/.procmailrc' to catch each list. But that's manual work for every list. When you use this subroutine, you no longer need to write separate mailing list recipes to your `~/.procmailrc' every time you subscribe to a new mailing list. The detection of a new list will happen automatically. What you need to know before using this module There is lot of heuristics going on in this module and one thing that you must note: If 'To:' domain is same as `From/Sender:/Reply-to:' domain then it is considered a mailing list message. This causes certain messages to be treated as mailing list messages. The module can't possibly know that the following is not from mailing list, because it doesn't know "what is mailing list", only "how it probably looks like it". This is definitedly categorized as mailing list message, because `From' and even `Reply-to' has the same domain `foo.bar.net' as in `To'. To: support@foo.bar.net From: message@foo.bar.net Reply-to: support@foo.bar.net Subject: Vmail See message to Eric You must prevent checking messages like this by surrounding call to this subroutine with a check statement: # Do not check these messages noList = "From.*(foo.bar.net|support.my.com)" :0 *$ ! $noList { INCLUDERC = $RC_LIST # ... save messsag by examining variable LIST (which see) } Ask for help If you find mailing lists that this subroutine does not detect, but which could have been detected by looking the headers in standard way, please send a email to maintainer. There may be cases where it is impossible to detect the mailing list and in those cases you just has to carve a new entry to your `~/.procmailrc'. When you keep your procmail log running, you may see message *** potential list *** Which is an indication that some new recipe could be added to to this subroutine to detect that mailing list. If the message you received _was_ from a mailing list, please send all the headers to the maintainer so that support can be added. Further reading You can search for mailing list that interests you at: http://www.lsoft.com/lists/listref.html Python based mailing list manager; the mailman: http://www.list.org/ Code note: Errors-To Bill Houle sent interesting headers which caused to add more heuristic than was feasible to solve the list detection. From the below headers it is practically impossible to derive the original list name. So, the list name is artificially constructed by combining Reply-To's LOGIN with Errors-To field's first host name Reply-To: news@doodle.foo.net Errors-To: bounced@doodle.foo.net The list name formed is "news-doodle". So, If you happen to see an odd name like this which doesn't remind the original list name, it may be due to poor headers that have no clue about the real name. No problem, check below how you would convert this name to better mailbox name. Required settings PMSRC must point to source directory of procmail code. This subroutine will followign extra module, which must have been installed. o pm-javar.rc Variable JA_LIST_FROM_TO_IGNORE This is regexp of sender addresses to ignore so that the if To and From are identical, it is not considered a list messages. This is typical for system generated messages that take form: From: root@host (Cron Daemon) To: root@host Variable JA_LIST_SAVE If set to "yes" then the list name information detected is saved to separate header. The `LIST_DETECTED' is the original grabbed word from the headers and the 'LIST' is the final name after possible list name conversions. According to RFC the X- can be user for user headers. X-List-Detected: $LIST_DETECTED mapped to $LIST Variable JA_LIST_KILL_POSTFIX If grabbed `LIST' match this regexp at the end of list name, then the postfix match will be removed. It is traditional that many list names are like list1-info, list2-beta, list3-L and ut would be preferable to see names like list1, list2 and list3. The default value will ditch "-(info|beta|L)". Variable JA_LIST_KILL_PREFIX Just like the postfix variable. If this string is matched at the beginning of the LIST, it is removed. Variable JA_LIST_DISREGARD_EMAIL In some cases this list detection recipe "thinks" that the address picked is the list sender. You may have a dedicated address where all you mailing list mails arrive and you have named it like mailing-list@me.here.at, which will effectively trigger: Ah, you have -list in email address, so this message must be from mailing list name 'mailing'. Of course it is not and you have to disallow the heuristics to make such assumption by defining a regexp that rejects a possible choice. For the above example, you would define: JA_LIST_DISREGARD_EMAIL = "posting-list@me.here.at" If you have several such addresses, just add them to the variable separating with normal regular expression "|" OR statement. Variable JA_LIST_HEADER_REGEXP This is *optional* variable, which you can set to match regexp of the mailing list domain address if it slipped through the tests in this module. There are some lists that send messages that don't carry enough information in headers to determine their list status. If you narrow the group by setting JA_LIST_HEADER_REGEXP, then for example lists like these, that identify themselves only through two headers, can be found: Reply-To: dispatch-faq@cnet.com From: CNET Digital Dispatch For that list you would set JA_LIST_HEADER_REGEXP = "(@cnet\.com)" Don't worry. all the other list detection recipes has already been tried, so this is last test that are carried out and variable JA_LIST_HEADER_REGEXP helps eliminating possible mishist You don't need set this variable to include all mailing list domains. Only to those ones that were not trapped. The default value for this is: "(amazon\.com|bookpool\.com)" Variable JA_LIST_MAKE_UNIQUE If you're subscribed to many mailing lists, that simply tell that they are *news* or *newsletter*, it will be impossible to differiantiate A *news* from B *news*. This variable holds regular expression that, if matched, prepend the first host name to the beginning of list name, thus making the list unique: news@some.com --> some-news news@here.com --> here-news The default value matches lists that contain word *news*, but you may need to set this to more matches. Variable JA_LIST_CONVERSION Note: before using this feature, make sure your `LINEBUF' is big enough, say 4096 or otherwise the variable's content is truncated. Many times the grabbed `LIST' name is not what you would like to use for your mailbox name. You want to make the name perhaps more shorter, more descriptive or categorize the messages according to hierarchy. Let's say that you have subscribed to following mailing lists: LIST LIST name Description of mailing list (as grabbed) you want ------------------------------------------------------------- jde java.jde Java Development Env java java.lang Java programming FLAMENCO flamenco Flamenco music tango-l tango Argentine Tango dancing tm-en-help tm-en Emacs TM mime package mailing list w3-beta w3 Emacs WWW mailing list First, remember that the variable `JA_LIST_KILL_POSTFIX' is first applied, so the actual `LIST' appears as follows: jde, java, FLAMENCO, tango, tm-en, w3 Ok, now we apply the conversion table by defining it as follows. The grabbed LIST name is first, then comes space(s), new name _and_ terminating colon. Repeat this for each list you want to convert. LIST CONVERSION[,LIST CONVERSION ...] This gives us table below: notice that entries tango-l, w3-beta were not included, because the `JA_LIST_KILL_POSTFIX' already got rid of the postfixes. Also note how the uppercase match FLAMENCO is converted to more suitable lowercase mailbox name. After you have set up this variable you can start saving messages to folders. JA_LIST_CONVERSION = "\ jde java.jde,\ java java.lang,\ FLAMENCO flamenco,\ " The list conversion is done with pure procmail means, so it is very fast. It also means that the conversion is limited to FROM-STRING TO-STRING syntax. No wild cards or regular expressions are allowed. If you consider using an external process, like `sed' or `perl' to convert the grabbed list name to something else (when `JA_LIST_CONVERSION' method was not enough); think again. For each incoming mailing list message you launch external process. It is not unusual to receive 700 messages from various mailing lists a day, it can be imagined how much load any external process would add to the server. Use the grabbed mailing list name and `JA_LIST_CONVERSION' table if you care about system load. If you have many mailing lists that use uppercase names, it may be tedious to add each mailing list name to `JA_LIST_CONVERSION'. Possible alternative is to use very efficient `tr' program to convert characters to lowercase. Again; think twice, because any extra process could be avoided if `JA_LIST_CONVERSION' was used. :0 * ! LIST ?? ^^^^ { :0 D # still uppercase list name? * LIST ?? [A-Z] { LIST = `echo $LIST | tr A-Z a-z` } :0 : list.$LIST } List name is not always the same One important thing to keep in mind is that when mailing list manager sends out list messages, the headers may change. This means that the list name grabbed previously changes too. This is unfortunate, but it sometimes happens. Let's see an example. I was previously receiving messages from Cygwin mailing list named `gnu-win32' To: , "Foo Bar" However, one day that same list was grabbed under name "cygwin", due to new header Mailing-List: contact cygwin-help@sourceware.cygnus.com; run by ezmlm Now I had two list names that both should be going to the same mailbox. No worries, just add new entry to the translate table to convert the new list name to mailbox name: JA_LIST_CONVERSION = "\ gnu-win32 cygwin32,\ cygwin cygwin32,\ " Example: basic installation Here is recipe to save all your mailing list to separate folders. If you subscribe to new lists or unsubscribe to lists, you don't need to change anything. The grabbed list name will appear in variable `LIST' RC_LIST = $PMSRC/pm-jalist.rc # name the subroutine ... # Handle all mailing lists with one subroutine and recipe # following it. Set also JA_LIST_CONVERSION before # calling this subroutine to cnvert the found list names. INCLUDERC = $RC_LIST imap = # Kill var. Set to "/" to enable :0 # if list name was grabbed * LIST ?? [a-z] { dummy = "Saving mailing list: $LIST" :0 w: ${imap+".INBOX."}list.$LIST$imap } What's that IMAP thing there, you may wonder. Normally procmail delivers to standard mailbox, so the name is something like '$MAILDIR/list.abc'. For IMAP, the delivery must happen using principle "one file, one message", so procmail must deliver to a directory. That's what the added `$imap' is there for. It is also customary that IMAP folders are prefixed with ".INBOX", so the actual name becomes `$MAILDIR/.INBOX.list.abc'. For IMAP there should also be proper `MAILDIR=$HOME/Maildir' setting. Pm-jamime-decode.rc -- decode MIME body contents; quoted-printable, base64 File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Documentation The original father of the decoding scheme used here was presented by Peter Galbraith in procmail mailing list somewhere at the end of 1997. This subroutine supposes that the header has MIME header Content-Type: text/plain and performs quoted-printable or base64 decoding on the whole message. Note, that if you receive messages that have many mime attachments, then this recipe is not suitable for it. Procmail is *not* designed to handle mime attachments and this recipe only applies to whole _body_. The `pm-jamime-*.rc' is really stretching the limits and any serious works hould be delegated to appropriate Perl MIME modules. There is a Perl MIME module which will allow you to manipulate MIME body parts rather elegantly. See http://www.perl.com/CPAN-local/authors/Eryq/ for MIME-tools. Se also mimedecode at ftp://ftp.dde.dk/pub/mimedecode.c which in included in Debian Linux. Notes Perl or python is not used, because both are CPU intensive. It would be too expansive for accounts or environments receiving hundreds of mails per day (like from several mailing lists). RFC 2047 gives possiblity to use MIME iso-8859-1 extensions for mail headers. Subject: Re: [PIC]: RSA =?iso-8859-1?Q?encryption=B7=B7?= Subject: =?iso-8859-1?Q?=5BEE=5D:TV_&_video_IC=B4s_!!?= There is also base64 possibility (although rare): Subject: =?iso-8859-1?B?zvLi5fI6ICAgICAgTVBMQUIzLjQw?= In worst possible case there is even multiple ISO encoded strings in subject. Yes, this is valid, the continued line includes spaces at front to keep it with original just like in `Received:' headers. This subroutine will not touch headers that have multiple ISO tags - procmail is too limited for that. Subject: AW: Re: AW: neue =3D?ISO-8859-1?Q?M=3DF6glichkeiten_=3D28was_=3D=C4hn?=3D =3D?ISO-8859-1?Q?lichkeiten_von_=3DDCbungen=3D29?=3D Required settings Variable `PMSRC' must point to source directory of procmail code. This subroutine will include o pm-javar.rc, pm-jamime.rc o Programs `$MIME_BIN', `$MIME_BIN_QP' and `$MIME_BIN_64' must have been installed (see pm-javar.rc). Call arguments (variables to set before calling) o `JA_MIME_DECODE_TREAT_SUBJECT', default "yes". Decode Subject header by removing mime. o `JA_MIME_DECODE_TREAT_FROM', default "no". Decode From header by removing mime. o `JA_MIME_DECODE_TREAT_BODY', default "no". Decode body of message by removing quoted-printable from a message that contains only one part. Messages with multiple parts are not handled. Return values o `PM_JAMIME_COMPLEX_SUBJECT' is set to "yes" if Subject header contains ISO encoding several times, it cannot be handled by this module. This flag is set to indicate that some other program shoudl handle the message. Examples Instead of testing the existence of text/plain in the body, you can force decoding by settings JA_MIME_DECODE_REGEXP to ".*". RC_MIME_DECODE = $PMSRC/pm-jamime-decode.rc :0 * condition { JA_MIME_DECODE_REGEXP = ".*" } INCLUDERC = $RC_MIME_DECODE # call subroutine. Pm-jamime-kill.rc -- General MIME attachment killer (vcards, html) File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description Note: If you think this module can do miracles, it cannot. MIME messages are very complex in structure and all this module can do is to detect *simple* attachements. It cannot be used as - all purpose - all detecting - MIME attachement killer. But the part it can do, is done efficiently, because most of the things are accomplished using procmail and resource friendly `awk'. There are meny programs that add additional information to the messages. Microsoft's mail program is one which may include a 7k application/ms-tnef attachment to the end of message. Many other programs may do the same. This was the idea in 1997 when this module was written; to get rid of the extra cruft which should not land in the mailbox. This recipe works like this: If email's structure is --boundary message-text (maybe quoted-printable) --boundary some-unwanted-mime-attachment --boundary then the attachment is killed from the body. The message-text part is also decoded if it was quoted printable. This leaves clean text with no MIME anywhere. MIME headers have will be modified as needed due to conversion from multi part and possibly quoted printable to plain text and the final message looks like: message But if email's structure is anything else, like if there were 3 mime sections: --boundary message-text (maybe quoted-printable) --boundary some-attachment --boundary some-unwanted-mime-attachment --boundary then the "unwanted" part is emptyed by replacing with one empty line. The message structure stays the same, but the killed "some-unwanted-mime-attachment" part is labelled as text/plain so that the MUA (Mail User Agent; the email reader program) can decode the MIME message correctly. Applications for other mime attachments The following cases are ncluded on in this module. You need to separately the behavior before this module will start working. o Lotus Notes attachment. o Microsoft Express attachement. It sends a copy of message in HTML format. o Mozilla's Netscape attachement. It sends a copy of message in HTML. o `Vcard' attachments. o Openmail attachment. It sends 10-20 line base64 attachments WINMAIL.DAT. Example of lotus notes attachment Subject: message From: foo@bar.com X-Lotus-FromDomain: XXX COMPANIES Mime-Version: 1.0 Boundary="0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw" Content-Type: multipart/mixed; Boundary="0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw" --0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw Content-type: application/octet-stream; name="PIC10898.PCX" Content-transfer-encoding: base64 eJ8+IjsQAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcA b3NvZnQgTWFpbC5Ob3RlADEIAQ2ABAACAAAAAgACAAEEkAYAyAEAAAEAAAAQ --0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw-- Example of MS Explorer's ms-tnef message Subject: message From: foo@bar.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="---- =_NextPart_000_01BD04D4.A5AC6B00" Lines: 158 ------ =_NextPart_000_01BD04D4.A5AC6B00 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable ------ =_NextPart_000_01BD04D4.A5AC6B00 Content-Type: application/ms-tnef Content-Transfer-Encoding: base64 eJ8+IjsQAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcA b3NvZnQgTWFpbC5Ob3RlADEIAQ2ABAACAAAAAgACAAEEkAYAyAEAAAEAAAAQ ------ =_NextPart_000_01BD04D4.A5AC6B00-- Example of MS Express's HTML message MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_003A_01BD16E2.C97E27B0" X-Mailer: Microsoft Outlook Express 4.72.2106.4 X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2106.4 This is a multi-part message in MIME format. ------=_NextPart_000_003A_01BD16E2.C97E27B0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable ------=_NextPart_000_003A_01BD16E2.C97E27B0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable ------=_NextPart_000_003A_01BD16E2.C97E27B0-- Example of Netscape's HTML attachment X-Mailer: Mozilla 4.04 [en] (X11; U; Linux 2.0.33 i686) MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="------------69D9D579CF587DC8BB26C49C" --------------69D9D579CF587DC8BB26C49C Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit --------------69D9D579CF587DC8BB26C49C Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7bit --------------69D9D579CF587DC8BB26C49C-- Example of Netscape's vcard attachment. Content-Type: text/x-vcard; charset=us-ascii; name="vcard.vcf" Content-Transfer-Encoding: 7bit Content-Description: Card for Laird Nelson Content-Disposition: attachment; filename="vcard.vcf" begin: vcard fn: Laird Nelson n: Nelson;Laird org: Perot Systems Corporation email;internet: ljnelson@unix.amherst.edu title: Software Engineer tel;work: (617) 303-5059 tel;fax: (617) 303-5293 tel;home: (978) 741-3126 note;quoted-printable:Information is for reference only;=0D=0A= please do not abuse it. x-mozilla-cpt: ;0 x-mozilla-html: TRUE version: 2.1 end: vcard Required settings To handle base64 encoded messages, package called `metamail' must have been installed to system. It provides program `mimencode' which is used through variable $MIME_BIN (see pm-javar.rc). Variable $PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jamime.rc Call arguments (variables to set before calling) First of all, this is primarily a framework recipe to kill any kind of attachment. If you do not set `JA_MIME_TYPE' before calling this recipe, recipe will try to determine the right value by itself. If the automatic detection fails you _need_ to preset the value of `JA_MIME_TYPE' beforehand. o `JA_MIME_TYPE' is a case sensitive AWK *REGEXP*. Always use *lowercase* letters in this regexp because the line is lowercased before match is made. This regexp determines if the kill recipe is applied to the message or not. Value is set for MS explorer, MS express, Netscape and Lotus Notes etc. messages by default. o `JA_MIME_KILL_RE', additional *REGEXP* to kill lines from the message. Value is case sensitive awk regexp and by default matches Lotus notes tag: name="XXX.PCX". o `JA_MIME_EXTRA_HEADER', name of header added to the message if the MIME portion was killed. Default value is "X-Mime-Type-Killed". It may be possible that some messages are malformed and that they do not contain proper "boundary" definition string in the header. There have been messages that have text/html attachments, but no proper Mime headers. For those cases there is additional variable that will kill all text up till matching line regardless of message content. o `JA_MIME_KILL2_RE' is set to "text/html|application/ms-tnef". Update this to match attchements you receive. Set variable to "" if you don't want to change the body of non-compliant MIME message. That variable is the last resort if the standard MIME detection failed. There must have been some problem in the sender's MUA that composed message. It's dangerous, so make sure you don't set it lightly. Possible conflict with your awk If you see an error message in the log file saying that awk failed: procmail: Executing awk, ... procmail: Error while writing to "awk" procmail: Rescue of unfiltered data succeeded it means that the system's standard `awk' doesn't support the variable passing syntax. Do the following test: % awk '{print VAR; exit}' VAR="value" /etc/passwd It should print "value". If not, then see if you have `nawk' or `gawk' in the system. They should understand the variable passing syntax. The only change needed is to define variable AWK somewhere at the top of `~/.procmailrc'. AWK = "gawk" # Better than standard "awk" Warnings You should know that the variable `JA_MIME_KILL_RE' is used to wipe any lines that match that regexp. This is due to MIME structure where continuing header lines exist in the body: ------=_NextPart_000_003A_01BD16E2.C97E27B0 Content-Type: text/plain; charset="iso-8859-1" << kill this line too If you want to be absolutely sure that anything valuable won't be accidentally killed (like a code line in programming language scripts), you should set this variable to nonsense value that newer matches: JA_MIME_KILL_RE = "match_it_never_I_hope" Usage example: Customizing the attachment killing Suppose you receive new `application/ms' type attachment that the default settings doesn't cover. This is a new mime type and you have to instruct this module to kill it. Add this and similar tests for other mime types: myCustomMimeType = "application/ms" # must be all lowercase :0 *$ $myCustomMimeType { PM_JA_MIME_TYPE = $myCustomMimeType } INCLUDERC = $PMSRC/pm-jamime-kill.rc Usage example To kill text/html or pdf, postscript and others add something like this to `~/.procmailrc'. It demonstrates how the correct MIME types are detected: # ..................................................... # 1) Uncomment following line if your standard "awk" is broken # AWK = "gawk" # ..................................................... # 2) Set correct value for attachment killing :0 * ^X-Lotus-FromDomain: { # Kill Lotus notes .pcx attachments JA_MIME_TYPE = "application/octet-stream" } :0 * H ?? ^From:.*foo@example.com * B ?? ^Content-Type:.*text/html { # Kill html attachments JA_MIME_TYPE = "text/html" } # ..................................................... # 3) Call module INCLUDERC = $PMSRC/pm-jamime-kill.rc Pm-jamime.rc -- subroutine to read mime boundary etc. variables File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Documentation This includerc reads MIME boundary string from the message if it exists. The boundary string is typically found from Content-Type header. Mime-Version: 1.0 Content-Type: multipart/mixed; boundary=9i9nmIyA2yEADZbW In addition it will define few other mime variables. See the returned values. You use these variables later in your MIME message processing. Mime Notes 1998-07-28 Brett Glass reported in PM-L that there was security exploit in long attachment filenames: http://www.xray.mpe.mpg.de/mailing-lists/procmail/1998-07/msg00248.html And here is the url to the matter: http://www.sjmercury.com/business/microsoft/docs/security0728.htm When you use this module to detect mime messages, you can check the filename length with recipe: # Recipe after calling $RC_MIME, this module, re = ".........." # regexp with 10 matches too_long = "$re$re$re$re" # allow 40 characters maximum :0 *$ $SUPREME^0 MIME_H_ATTACHMENT ?? $re *$ $SUPREME^0 MIME_B_ATTACHMENT ?? $re { dummy = "** Dangerously long mime attachment filename" dummy = "** $MIME_H_ATTACHMENT $MIME_B_ATTACHMENT" :0 : /var/spool/mail/MimeDanger } Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc Call arguments (variables to set before calling) (none) Return values o Variable MIME is set to "yes" or "no" if messages has mime version string o MIME_VER contains the mime version string from the header. o MIME_TYPE contains the Content-Type from the header. o MIME_CTE contains Content-Transfer-Encoding from the header. o MIME_H_QP is "yes" if Content-Transfer-Encoding: quoted-printable is in the header. o MIME_B_QP is "yes" if Content-Transfer-Encoding: quoted-printable is found from the body. o MIME_BOUNDARY contains the boundary string, which is used to differentiate mime sections in the body. o MIME_BOUNDARY_COUNT is the number of boundary strings found from the body. The value is 3 if there is two mime sections, and 4 if 3 etc. MIME_BOUNDARY_COUNT -1 = count of sections. o MIME_H_ATTACHMENT, contains the filename if there was attachement filename in the header. Content-Disposition: attachment; filename="..." o MIME_B_ATTACHMENT. `body' file attachment. Note however that this is the match of first string in the body. There may be several attachments. MIME_B_ATTACHMENT_FILE_COUNT tells you how many filenames are in the body. Usage example INCLUDERC = $PMSRC/pm-jamime.rc Pm-jamime-recode.rc -- re-encode MIME Header: Subject, From as quoted-printable File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Documentation This subroutine supposes that message has been handled by 'pm-jamime-decode.rc'. The purpose is to restore *Subject* and *From* headers back to quoted printable format so that messages can be savely saved through IMAP system which may not handle 8-bit messages. If message is stored directly to mailbox and the used Mail user Agent has no problems with dealing 8-bit characters, this module is not needed. An example where this subroutine could be applied: o Feed message to `pm-jamime-decode.rc' o Feed message `pm-jasubject.rc' (to clean multiple Re: Re: Fwd ..) o Restore From/Subject encodings with `pm-jamime-recode.rc' o Save message to mailbox Notes Perl or python is not used, because both are CPU intensive. It would be too expansive for accounts or environments receiving hundreds of mails per day (like from several mailing lists). Required settings Variable `PMSRC' must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jamime.rc o Program `$MIME_BIN_QP_E' must have been installed (see pm-javar.rc). o pm-jamine-decode.rc must have been called and message must contain headers `X-Mime-Header-Decoded-*' Call arguments (variables to set before calling) o `JA_MIME_RECODE_TREAT_SUBJECT', default "yes". Decode Subject header by removing mime. o `JA_MIME_RECODE_TREAT_FROM', default "no". Decode From header by removing mime. Return values (none) Examples To fix Subject header and then make it 7bit clean again. Note, this may not be exactly what you want. The pm-jamime-decode.rc file does a little more than From/Header handling (also modifies message body). Read documentation of each file before using following example INCLUDERC = $PMSRC/pm-jasubject.rc INCLUDERC = $PMSRC/pm-jamime-decode.rc INCLUDERC = $PMSRC/pm-jamime-recode.rc Pm-jamime-save.rc -- save message's MIME attachement (one file) to a file File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Documentation This module saves _one_ simple file attachment (MIME) from he message. The message must define following MIME headers. If "filename=" does not exists, then the message is ignored. Mime-Version: Content-Type: Content-Disposition: attachment; filename="file.txt" The last line can also be in separate line, provided that it is indented according to standard rules: Mime-Version: Content-Type: Content-Disposition: attachment; filename="file.txt" Procmail is not very suitable for saving MIME attachments and you should not think that this the right tool for you. If you receive anything more than 1 attachment, this recipe does nothing, because that's out of our league and you need some more heavy weight mime tools. E.g. Perl CPAN has MIME libraries. _Note_: when the attachment is in the body, it is simply written to a disk and the location in message is replaced with test: Extracted to file:/users/foo/junk/.file.txt. The existing mime headers that surround the attachment are lect untouched, so don't try to press your Mail Agent's MIME buttons at that point. There is no such file in that spot if you set `JA_MIME_SAVE_DEL' to `yes'. Required settings PMSRC must point to source directory of procmail code. This subroutine includes library: o pm-javar.rc o pm-jamime.rc o pm-jamime-decode.rc o pm-jadate.rc (which will call other pm-jadate*.rc files) Call arguments (variables to set before calling) o `JA_MIME_SAVE_DIR', point this to directory where you want to store attachments. o `JA_MIME_SAVE_DECODE', set this to "yes", if you want that attachment is decoded before written to disk. This usually opens quoted printable or base64 encoding. o `JA_MIME_SAVE_DEL', set this to "yes", if you want to remove the attachment from the body of the message after it has been filed. Be vary careful if you use this option. If you keep backup cache of incoming mail, then you might try "yes". o `JA_MIME_SAVE_OVERWRITE', set this to "yes" if it's okay to overwrite to an existing filename found from attachment. If you get periodic attachments always with same name, then you would want to set this to yes. Core dump note Because procmail uses LINEBUF when filtering messages, a core dump may happen if the attachment being filtered is bigger than the LINEBUF. The current setting accepts 524K attachments, but if you expect to get bigger than that, you want to increase `JA_MIME_SAVE_LINEBUF'. Possible conflict with your awk Awk is used because it is much more system load friendly than perl. If you see an error message in the log file saying that awk failed: procmail: Executing awk, ... procmail: Error while writing to "awk" procmail: Rescue of unfiltered data succeeded it means that the system's standard awk doesn't support the variable passing syntax. To verify that this is the case, run following test: % awk '{print VAR; exit}' VAR="value" /etc/passwd The proper awk should print "value". If not, then see if you have `nawk' or `gawk' in your system, which should understand the variable passing syntax. To change the AWK, you need to set following variable somewhere at the top of your *.procmailrc* AWK = "gawk" # if that works better than standard "awk" Return values (none) Pm-janetmind.rc -- handle http://minder.netmind.com/ messages File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description ** THIS MODULE IS OBSOLETE. THE NETMIND SERVICE NO LONGER EXISTS ** http://minder.netmind.com/ ...Netmind, or The URL-minder is a free, automatic Web-surfing robot that keeps track of changes to Web pages that are important to you. When the URL-minder detects changes in any of the Web pages you have registered, it sends you e-mail. an effective way to test if the address is known to Internet. You could use this information to see if some automated reply to a address can be sent. In another words, if you're interested in some URL; say an FAQ page and any updates to them, you can tell Netmind to monitor the page changes for you and it send a message back every time page changes. This recipe "pretty formats" the announcement sent by Netmind by stripping the message to bare minimum. You usually aren't interested in 4k message which includes "Note from our sponsors", "Try the free online demo" etc. The things saved from the announcement message are: o The changed url, which is moved to subject o Cancellation url pointer o url to the lists of your monitored urls o your id number [Note] Please let Netmind send you one "pure" message first so that you have a huch what it originally looks like. Then plug int his module and see how the original message is reduced. [Thank you] The Doctor What 1998-03-12 send me a patch, where a)body message is more informative b) URL is now included in the body for auto-click browsers c) mime headers were removed. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o If you se variable JA_NETMIND_SUBJECT to "yes", then the changed url http pointer is put to subject line. Usage example INCLUDERC = $PMSRC/pm-janetmind.rc # reformat the message :0: # drop to folder * netmind url.mbox Pm-janslookup.rc -- run nslookup on variable INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine runs `nslookup' on given INPUT address. This may be an effective way to test if the address is known to Internet. You could use this information to determine if some automated reply to a address can be sent. The know truth is that you can't validate whole email address to_someone@foo.com but you can validate "foo.com"; that's the closest you get. [Warning: If you don't use cache feature...] Do not however use this module to regularly check _all_ incoming from addresses with this subroutine for possible bogus UBE addresses, because calling nslookup o may be slow, building to connection and querying the results may take several seconds. (some times, usually it's quote fast) o consumes quite a lot resources. You can however check _some_ messages that are likely UBE to verify your doubts. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jaaddr.rc Call arguments (variables to set before calling) o INPUT, the address (only strict domain part) which is checked. Eg. "this.domain.com". See examples for more. If this string contains "@" character, then additional subroutine pm-jaaddr.rc is called to extraxt the domain name INPUT = "John Doe " --> INPUT = "site.com" o JA_NSLOOKUP_CACHE, filename. If exists, cache is used and updated. o JA_NSLOOKUP_FORCE, if "yes", then cache is not used but a forced nslookup is performed. o JA_NSLOOKUP_OPT, is currently empty, but you could see if you you want to use "-querytype=MX". However this option may give you response: "No mail exchanger (MX) records available", which is flagged as nslookup failure. o JA_NSLOOKUP_SERVER, optional, the server to user for nslookup If the cache file can be read: o Each entry has format "address.com ns-error". The error indication is added to the line if the nslookup failed when address was checked. Otherwise line contains "address.com". o The cache is always checked first. If there is no entry matching the current address, only then is nslookup called and new entry added to cache. Return values o Variable ERROR will be set to "yes" if nslookup failed or to "no" if nslookup succeeded. It can also contain "maybe" if nslookup returned "No address (A) records available" o ERROR_MATCH contains one line lookup failure reason. Following conditions trigger "maybe" and no "ns-error" is written into the cache. o "No address (A) records available for xxx" Usage example If you are going to check some header field, like From:, please explode the content with pm-jaaddr.rc first. Suppose you have string: "From: foo@ingrid.sps.mot.com (Yoshiaki foo)" You have to derive the address from string and pass the site name: Read From: field and address from it. PMSRC = $HOME/pm RC_NSLOOKUP = $PMSRC/pm-janslookup.rc # name the subroutine :0 * MAYBE_UBE ?? yes * ^From:\/.* { INPUT = $MATCH INCLUDERC = $RC_NSLOOKUP # to nslookup :0 * ERROR ?? yes { # Hm, nslookup failed, can't send anything back to this # address } } Second example, check if the address is reachable before sending reply INPUT = `$FORMAIL -rt -x To:` INCLUDERC = $RC_NSLOOKUP :0 * ERROR ?? no { # okay, at least site address seems to be reachable } Pm-jaorig.rc -- Extract embedded original message (simple recipe) File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Documentation This subroutine digs embedded message from the body and replaces current message with it. Copy the message to folder before calling this subroutine if you need original. NOTE: This is _simple_ tool and the sole purpose is to derive simple embedded messages. Write full fledged perl script if you want better extracting features. The used AWK inside this procmail recipe will fail to find 30% of the cases, mostly due to non-standard way of including the message. The recognized formats are as follows. Anything that differs from these are ignored or incorrectly parsed. o Message is embedded left flushed "as is". With full headers or Minimum of `From:' `Subject' `Received' o The embedded message is quoted with `>' with optional _one_ space. Where you would use this module If you're subscribed to mailing lists that regularly sent copies of original message to the list, like forwarding spam to SPAM-L mailing list at http://bounce.to/dmuth, then you'd like to extract the original embedded message which you can then feed to your UBE filter to test if the shield holds. subscribe SPAM-L This recipe takes simplistic approach and tries it's best to extract embedded message. Idea for this recipe comes from Era Eriksson's posting "recipe to turn list postings back into original spam" 1998-06-25 in Procmail mailing list. o Body must contain headers o Remove all `>' quotations. o extract everything to the end of message. (There are no means to get rid of the attached signatures that ot forwarding poster or list server may have attached. How the message is extracted When this recipe ends, the current message has been modified so that it _is_ _the_ _original_ _message_. Like if you would receive: HEADER-1 # The poster body-1 # his comments HEADER-2 # The original embedded message body-2 body-1 # And poster's signature or mailing list footer The message now looks like HEADER-2 body-2 body-1 And you can save this as original message or feed it to your UBE filter and test if it detects it. Code note: procmail or awk core dump For some reason procmail kept dumping core I write the code in more nicer format like below, but if I made it compact, then it didn't dump core. Go figure. I'm not pleased that I had to sacrafice clarity, but there was no other way. [The good style] [The forced compact style] if () if () { statement } { statement } I have no explanation why this happens, the same AWK code would work just fine most of the cases and then came this message `x' and caused dumping the code, if I feed some other message, I didn't get core dump. Total mystery to me. Don't let the log message fool you, this had nothing to do regexp "^[> ]*From:.*[a-zA-Z]". If I deletd one line from AWK script, it worked ok, if I added it back the core dump happened with that message `x' procmail: Assigning "pfx=[> ]*" procmail: No match on "^[> ]*From:.*[a-zA-Z]" Segmentation fault (core dumped) Required settings PMSRC must point to source directory of procmail includerc code. This subroutine needs module(s): o pm-javar.rc Call arguments (variables to set before calling) (none) Usage Example Let's assume that you want to feed all forwarded UBE that is posted to spam-l mailing list to your filter and see if it needs improving by checking the logs later. The forwarded UBE to the list is labelled "SPAM:" in the subject line. $RC_LIST = $PMSRC/pm-jalist.rc # mailing list detector $RC_ORIG = $PMSRC/pm-jaorig.rc # extract original $RC_UBE = $PMSRC/pm-jaube.rc # UBE filter ... INCLUDERC = $RC_LIST # defines variable `LIST' :0 * ! LIST ^^^^ { :0 # spam-l mailing list * LIST ?? spam * Subject: +SPAM: { INCLUDERC = $RC_ORIG # Change it to UBE message # Ok, next feed it to filter, set some variables first # Log = Short log; What filters were applied to message # mbx = If message was trapped, save it here JA_UBE_LOG = "$PMSRC/pm-ube.log" JA_UBE_MBOX = "junk.ube.ok.mbox" INCLUDERC = $RC_UBE :0 : # If comes here, filter failed junk.ube.nok.mbx } :0 : # save normal list messages list.$LIST } Pm-japing.rc -- reply shortly to message "Subject: ping"; account ok File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description When I'm on remote site and I don't seem to get throught with telnet or even with Unix ping(1), I want to know if the at least the mail server is up. I can send a ping message and the auto responder will reply immediately. Sometimes, when you send a message to a person, it would be nice, if you could test that the destination address is valid, before sending a message to a black hole. If the receiver had ping service running; like this, then you would know that you spelled the the right address. (after wondering two weeks; why you don't get response). Nowadays `finger(1)' command seems to be blocked many times. This recipe answers to simple ping message like this: To: you@site.com Subject: ping Recipe sends a short message back to the sender. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jastore.rc Call arguments (variables to set before calling) (see Usage) Usage example JA_PING_MBOX = $HOME/Mail/spool/ping.spool INCLUDERC = $PMSRC/pm-japing.rc Pm-japop3.rc -- Remotedly download messages by mail command request File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description Ahem, that `pop3' is just to draw your attention. This module has nothing to do with pop3. The idea may resemble it though. This module listens pop3 requests, and when it gets one, it sends the whole mailbox content as separate forwarded messages to the account from where you sent the request. This is kinda "empty my mailbox in account X and send the messages to account Y" You might have permanent forwarding on in account X, but if that is your secondary account, you can ask what messages has been arrived there with this recipe. After you have configured your magic pop3 command, which is your password, simply send a message to account X, and this module initiates emptying the mailbox. Here is an example: Subject: pOp3-send [mailbox] [kill] o `mailbox', is optional folder name which you want to process. it is $DEFAULT if not given in subject. Use *absolute* path if you specify one. o if word `kill' is found, the mailbox will be emptied after forwarding. If the word is not found, messages are preserved. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-japop3.rc # Phew! We include ourself, we are recursive. Call arguments (variables to set before calling) o `JA_POP3_SUBJECT_CMD' is your personal access command string. If this is the first word in the subject line, forwarding starts. This string is case sensitive. o `JA_POP3_TMP' is the file where mailbox is moved before starting to forward the messages. Do not put to point to your $HOME, becaus that may exceed the quota. o `JA_POP3_TO_MUST_MATCH' must contain regexp that match the email addresses where the pop3 messages are allowed to send. BE SURE TO DEFINE this. If you have account X,Y,Z where you want to receive pop3 messages, set this regexp to match those site's email addresses. o `JA_POP3_LOGFILE' is the log where you can see how the forked procmail processes send each pop3 mail. You may want to set this to different location than your default `$LOGFILE'. Return value `STATUS' will contain mailbox name if valid pop3 request was received. You may wish to save the pop3 requests to separate folder. See example below. Example usage You install this same setup for each site where you have account. This is the account X, from where you want to empty the mailboxes. RC_POP3 = $PMSRC/pm-japop3.rc .. somewhere in your .procmailrc .. JA_POP3_SUBJECT_CMD = myPoPcmd INCLUDERC = $RC_POP3 # Save all pop3 requests to folder :0 : * STATUS ?? [a-z] mail.pop3-req.mbox In account Y, from where you send the pop3 requests. Following code stores The received messages to separate folder # The MATCH will contain the host name from where the messages # were moved :0 : *$ X-Loop-Fwd:.*\.rc +\/$NSPC+ mail.fwd.$MATCH.mbox Pm-jarandf.rc -- pick (rand)om line from (f)ile File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description Return random line or a line from a file. This subroutine uses shell command `awk' and possibly `wc' to be as small burden to the system as possible. Required settings You must have awk that supports VAR=value assignment syntax outside the code block: that is, in the input line. I know no awk that would not have this feature, but at least you know now what it takes. % awk '{print VAR; exit;}' VAR=1 /etc/passwd Try using GNU awk, if your standard awk didn't print 1 in above test. (Put this line to the top of your .procmailrc) AWK = "gawk" Call arguments (variables to set before calling) If intend to call this subroutine many times, then please calculate the number of lines beforehand and pass it to this subroutine. If the MAX is not set, then `wc' is called every time to find your the line count. o FILE, from what file to select. Make sure this exists; existence is not checked here. o [MAX] optional, number of lines in the FILE. Returned value variable LINE Example usage # Select random line from a file $RC_RANDF = $PMSRC/pm-jarand.rc $COOKIE = $HOME/txt/cookie.lst ...somewhere.. MAX=20 FILE=$COOKIE INCLUDERC=$RC_RANDF # LINE contains randomly read line Pm-jasrv-check.rc -- check FILE validity, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of the TPFS or MPFS file server. Check FILE for nonvalid filenames or other access problems. Input o JA_SRV_F_FILE_CASE_SENSITIVE, flag o FILE, filename to check. possibly converted to lowercase. Output o stat, set to "ok" if filename is acceptable. Otherwise contains brief error reason; Pm-jasrv-daemon.rc -- server request check, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of the MPFS file server. Handle BOUNCES to mail server messages, eg if delivery failed due to maximum byte limit. 552 ... Message is too large; 100000 bytes max Input (none) This recipe examines headers and body to see if it's daemon bounce. Output o stat, set to "daemon" if message was handled. Pm-jasrv-err.rc -- send message, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This module is part of the MPFS file server. Ssnd error notice: file didn't exist. Input o FILE, file or command that did ot exist. Output o fld, additional field to be added to the saved mbox log message Pm-jasrv-from.rc -- compose reply, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of the MPFS file server. Compose headers for reply message using `formail' -rt. Here is dry run example to test this module % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all \ FORMAIL=/opt/local/bin/formail \ JA_SRV_FORMAIL_FROM=me@here \ JA_SRV_CONTENT_TYPE=content-type \ JA_SRV_XLOOP=xloop \ $HOME/pm/pm-jasrv-from.rc \ < $HOME/any-sample.email Input o JA_SRV_FORMAIL_FROM, JA_SRV_XLOOP o JA_SRV_CONTENT_TYPE Output (none) Pm-jasrv-msg.rc -- send message, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of the TPFS or MPFS file server. Run $CODE and return resutls to to user. Subroutine is meant to be used for informational messages. Input o code, code to run in shell o stat, status message for user Pm-jasrv-multi.rc -- send multipart MIME message, subroutine for FileSrv File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of MPFS file server. Send out FILE as multipart MIME message. The message will always be base64 encoded before sending. Input o JA_SRV_MIME_MULTI_SEND, command to feed the composed and message which will handle sending it as multipart MIME. o JA_SRV_MULTIPART_THRESHOLD is the hunk size for slitting mail. o FILE, only filename part. Included in MIME headers. o file, absolute path to send Pm-jasrv.rc -- MIME capable Procmail File server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This is the MPFS (Mime Procmail File Server) and it can send MIME compliant messages with command "send [WORD1] [WORD2]" Usually only the ITEM arg is used, and the rest of the words are for special uses like password and preventing file encoding. A typical request looks like: Subject: send help # ask for file named 'help' Overview of features o MIME types gzip and text/plain are supported. o .gz .zip etc. files are sent out as base64 attachments o .gz .tar.gz files that exceed 100K are sent out as MIME multiparts o requires procmail 3.11+ and MATCH operator \/ o requires `mmencode' and `gzip' executables to be present in PATH. Install: server file directory You have to create a directory for the server where the files are kept. Usually I don't put the files there, but whenever I want to make a file available, I draw a hard or softlink to the real file. % mkdir $HOME/pm-server # Repeat this as needed for files you want to put available % cd $HOME/pm-server % ln -s $HOME/txt/interesting-file.txt interesting-file.txt You define the server directory by setting JA_SRV_FILE_DIR = $HOME/pm-server The short server log is written to file pointed by this variable: JA_SRV_LOG = $HOME/pm-server.log The incoming "send" requests are stored to mailbox pointed by following variable. The default value is /dev/null, but you may want to set it to ~/Mail/spool/log.srv.spool which can be used read as a newsgroup by Emacs Gnus [In Gnus create newsgroup with `G` `m' `nnml' `log.srv'] JA_SRV_MSG_MBOX Install: special files Tweak this variable to commands you want to allow shell to execute in server's directory. This tells when "ls" means command instead of file JA_SRV_SH_COMMAND = "^(ls|what)$" That means that request like this: Subject: send ls # run "ls" command and return results Be sure that the commands exist in your system. See man pages for more if you want to know what these commands do. Commands cannot take switches currently for security reasons. E.g. if you want to give access to "ls -la" listing, put a file "ls-la.txt" available in the directory, user can get it with "send ls-la.txt" ls -- list directory file -- print file type information. what -- prints all @(#) tags from files ident -- print all $ $ tags from files Install: file `help' Users want to get a help file with message "send help" and the `help' is just a file in your server directory. Be sure to supply it prior to any other files. You can always draw a link to a file if you don't want to name it that way (e.g. if you keep several server help files in a RCS tree) # draw symlink to `help' % ln -s $HOME/txt/srv-public-hlp.txt $HOME/server/help Basic usage in details The server accepts command in format "send [CMD|PASSWORD]" Where ITEM can be any name as long as it starts with [^ .]. The regexp says: Anything goes as long as FILE does _not_ start with space or period. This gives you quite a much freedom to construct filenames. if you want to hand out file: .procmailrc You can't. Instead make a link to point to plain "procmailrc" without the leading period. There is also additional checks against possible security threat "../" like below; user can't request such file. ../../../gotcha or dir/../../gotcha The filename cannot contain special characters like [*?<>{}()]. Advanced usage [conversions] If some of your files are big, it makes sense to send them in compressed base64 format; which in MIME world is called content-type gzip. You can set a regexp to enforce encoding for your big files before they are sent to user. The following setting will send all text files in compressed format to user. JA_SRV_XGZIP_REGEXP = "\.txt" When the message is composed a header is inserted into the message telling how the message is to be decoded, in case user doesn't have decent MUA that can handle the MIME type: X-comment: To decode, cat msg| mmencode -u| gzip -d > test.txt [noconv and gz] The `WORD1' parameter after the `FILE' is optional and user can override base64 encoding and request plain file if he uses word "noconv". Subject: send [noconv|gzip] However, there are files where `noconv' must not be obeyed, like the compressed packages that you have put available in .zip, .gz, .tar.gz or .tgz (GNU tar) format. Following variable controls when file is always sent as base64: JA_SRV_BASE64_ALWAYS If the `WORD1' is "gz" or "gzip", then the gzip is explicitly requested, This may be desirable, because some of the text files in the server directory may be big and some accounts don't accept big messages. A typical bounce looks like: 552 ... Message is too large; 100000 bytes max 554 Service unavailable These kind of file server bounce messages are handled in separate module which notifies the user that his account didn't accept the sent file. [case sensitivity] By default the request word ("send") and ITEM (filename) are not case sensitive, unless you set these flags: JA_SRV_F_CMD_CASE_SENSITIVE = "yes" JA_SRV_F_FILE_CASE_SENSITIVE = "yes" If values are "no", then these are identical commands: Subject: Send Help Subject SEND HELP Multi part mime messages If you want to deliver big files, you better be sure not to send them as a big file. That blocks the connection between every host along the path that the big file is transferred. The solution is to use MIME multi parts that can be assembled back in the receiving MUA. (In case you don't have multi part assembler receive Perl script to do it). MIME multiparts are sent out if o Filename matches JA_SRV_BASE64_ALWAYS, typically tar.gz, zip o Filesize is bigger than JA_SRV_MULTIPART_THRESHOLD, where default chunk size is 100K. When a file meets these criteria, it is read to the `BODY' of message and base64 encoded. This all happens in memory, so watch procmail logs to see if any problems with very big files. (>30Meg). Next, if the base64 conversion succeeded, the composed is handed to JA_SRV_MIME_MULTI_SEND Which does the actual delivery and splitting. The default program used is `splitmail'. Make sure you have it or substitute the program with some equivalent one. Stopping server Sometimes you're making rearrangements in you file directory or doing some other maintenance and you are unable to respond to `send' requests. You can stop the server by setting JA_SRV_IN_USE = "no" And when you want to enable the server again; just comment out the statement or assign `yes'. [The default is `yes']. When this variable is set to `no', the server sends a message from following variable as a response to any "send" request. JA_SRV_IN_USE_NO_MSG Using password to validate file requests You should be aware that this file server's implementation is public in nature. Anyone who asks for a file is allowed to get it. But it would be good if you could limit the access to documents with some simple way, like if you set up two file servers (see next chapter) where one is public and the other is interesting only to group of people. You can define a string that must be found in Subject field by setting the following variable JA_SRV_PASSWORD = ".*" # default The default value will match anything in the subject, thus making the server public. But if you set it like this JA_SRV_PASSWORD ".*123" Then string "123" must be there somewhere in the line, like here Subject: send 123 Yes, "123" is actually a CMD definition, but it doesn't matter because there is no CMD 123. Subject now matches password and the server can be accessed. Of course the following is valid too. Subject: send noconv 123 If the password was wrong, server won't tell it. The message just lands to your mailbox in that case and you can investigate who tried to access the restricted server. Changing server's command string (multiple servers) The default command string is "send", but you can change it and thus create multiple services. Here is one example, where you have set up two file servers where each has its own directory. # The public server JA_SRV_CMD_STRING = "send" JA_SRV_FILE_DIR = $HOME/server/public INCLUDERC = $HOME/procmail/pm-jasrv.rc # Company server, only interests fellow workers. # Here "xyz-send" is just magic server request string. # Notice case sensitivity settings. JA_SRV_F_CMD_CASE_SENSITIVE = "yes" JA_SRV_CMD_STRING = "xyz-send" JA_SRV_PASSWORD = ".*12qw" JA_SRV_FILE_DIR = $HOME/server/public/xyz-dir INCLUDERC = $HOME/procmail/pm-jasrv.rc Notes from the author [basic Mime type note] All basic files that you send must be US-ASCII, 7bit. At least that is the default MIME type used. See `JA_SRV_CONTENT_TYPE'. I once received following message back ----- Transcript of session follows ----- 554 ... Cannot send 8-bit data to 7-bit destination 501 ... Data format error because in the previous releases, the MIME type headers were not in the message saying that the content really was plain 7bit ascii. [Sending the file as is] Note, that the file is included "as is" without any extra *start-of-file* or *end-of-file* tags. This is possible, because the file is sent in MIME format. [Using one line log entry] It may look very spartan to print a single line log entry. You see messages like above in the file server log. Using one line entry instead of multi line announcements makes it possible to write a small perl tool to parse information from a single line. If you get many file server messages per day, it quicker to look at the single line entries too. [ja-srv1; sh file; Foo Bar ;] [ja-srv1; send xxx-file.txt; Foo Bar ;] | Server's request keywords (you may have multiple servers) [wish list] (*) MIME multipart message's mime headers may need some adjustments. (*) I rely on simple regexp to send out base64 or gzip files. The natural extension would be to use file size threshold: if file is bigger than N bytes, send it out with gzip. And further: if file is more than NN bytes, send it out as multi part MIME. (*) In fact there is a slight mime type errors: .zip files should be send as application/zip. If you have experience with the mime types, please contact me and help me to sort out proper mime headers. Required settings PMSRC must point to the source directory of procmail code. This subroutine will include many pm-jasrv-*.rc modules and other files from there. Please test the File Server in your environment before you start using it for every day. For example I had some weird local problem where PATH had /usr/contrib/bin/ where gzip was supposed to be, but in spite of my tries procmail didn't find it along the path. Don't ask why. I now use absolute binary name: GZIP = /usr/contrib/bin/gzip In addition, if your messages are not sent to recipient, but you get daemon message: ... Recipient names must be specified That's because you have setting SENDMAIL="sendmail"; which is not enough. It must be SENDMAIL = "sendmail -oi -t" Usage example This is my .procmailrc installation. Notice that the file server code is used only if you get "send" request. On the other hand, this double wrapping is not all necessary, you could as well rely on the File server's capability to detect SEND request. PMSRC = $HOME/pm # directory where the procmail rc files are RC_FSRV = $PMSRC/pm-jasrv.rc mySavedLOGFILE = $LOGFILE # record file server actions elsewhere LOGFILE = $PMSRC/pm-jasrv.log # Listen "send" requests. :0 * ^Subject: +send\> { JA_SRV_FILE_DIR = $HOME/fsrv # Where to get the files JA_SRV_LOG = $HOME/fsrv.log # Write log here INCLUDERC = $RC_FSRV # Use file server now } LOGFILE = $mySavedLOGFILE Pm-jasrv-req.rc -- server request check, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of the MPFS file server. Check if file server request is on the JA_SRV_SUBJECT and do case or incasensitive check. To Dry run this module use following skeleton. Substitute keywods as needed to reflect your system setup: % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all \ PMSRC=$HOME/txt JA_SRV_CMD_STRING=send \ JA_SRV_SUBJECT="send newbie_article.rtf noconv" \ txt/pm-jasrv-req.rc < ~/test.mail Input o JA_SRV_F_CMD_CASE_SENSITIVE; if "yes" then server request is case sensitive. o JA_SRV_FORMAIL_FROM. the email From field Output o stat, set to "ok" if request is accepted Pm-jasrv-send.rc -- server request check, subroutine for File Server File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine is part of the MPFS file server. Send the requested file. You can dry-run test this module with following command: a) make sure that $HOME/test conatins any simple email message b) define FORMAIL if it isnot found from path. % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all \ PMSRC=$HOME/txt JA_SRV_LOG=/dev/null \ FORMAIL=/opt/local/bin/formail \ file=$HOME/test FILE=test WORD=WORD JA_SRV_FROM=foo@bar \ SENDMAIL="tee -a $HOME/test.send" txt/pm-jasrv-send.rc < ~/test Note: The MIME headers here selected previously were: Content-type: application/octet-stream Content-transfer-encoding: x-gzip64 But Defining own CTE such as x-gzip64 is strongly discouraged by the MIME RFC's. Most e-mail clients would be at a loss on how to handle these. Many would just bomb out and not even give you the opportunity to save it to a file. A more correct MIME type is this, which is now used: Content-type: application/x-gzip Content-transfer-encoding: base64 Input o `FILE' is the filename(chdir to directory is already done) `file' is _absolute_ filename `WORD' is next word from subject line after FILE word. o JA_SRV_CMD_STRING is flag o JA_SRV_F_SUBJ_NOTIFY is flag Output o FILE_ERROR is set to "yes" if file is not found. Pm-jastore.rc -- Store messagee to inbox or gzip inbox File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This subroutine stores the message to file pointed by `MBOX'. This subroutine is meant to be used with the the other general purpose includerc files. This makes it possible to have a centralized file storage handling for all your rc files. Regular user doesn't get much out of this rc unless he mixes both .gz and regular files in his .procmailrc R e p e a t: This module is basis for general purpose procmail rc plug-ins to strre message to mailbox pointed by some rc configuration variable. Normal user can simply say in his .procmailrc: :0: mail.private Required settings (none) Call arguments (variables to set before calling) `MBOX' must have been set to point to message storage. `MBOX_SUFFIX' is extension added to MBOX. Default is none. `MBOX_MH' if "yes" then deliver to MH mailbox with `MBOX_MH_CMD' which is "rcvstore" by default. o message is delivered to MH mailbox using `MBOX_MH_CMD' otherwise o If MBOX is `some.mbox' the message is stored as is. o If MBOX is `some.mbox.gz' the message is gzipped to folder. o If MBOX is `some-dir/.' then deliver as individual files Example usage $RC_MBOX = $PMSRC/pm-jastore.rc :0 * condition { MBOX = $HOME/Mail/spool/junk.mbox INCLUDERC = $RC_MBOX } Pm-jasubject.rc -- Subject field cleaner and canonicalizer (Re:) File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description _NOTE:_ If you receive RFC 2047 encoded Subject headers like "Subject: =?ISO-8859-1?Q?=C4hnlichkeiten_von_=DCbungen?=", you must first decode it before using this subroutine. Feed the message to `pm-jamime-decode.rc' first. There are many different Email programs out there that add their own `reply' characters to the subject field. The most sad programs come usually from PC platform. Eg. Microsoft has gained a lot of bad reputation due to it's own standards. o MS Explorer can use localized reply strings, Eg `Vs:' or `vast:' seems to be Finnish `Vastaus'. o MS product Outlook (??) can be configured similarly. I have received swedish `Sv:' `-Svar' for `Svaring' (eng: reply) o MS mail uses `FW:' in forwarded mails. o Intelligent MUAs try to keep count of replies with `Re2:' or `Re[2]' o Japanese MUA Denshin 8 Go V321.1b7 has sent Re^2: o Some mua uses `Re>' o Lotus notes (in French version) uses `Ref:' o Some MS product sends `UQ:' o XXX uses `-reply' o Forwarding schemes: (fwd) [fwd] fw: [FWD: [FWD:]] o Subject references: -subj subj- subj: There already is a de facto standard where message should contain only single `Re:' if message has been replied to (no matter how many times). This makes it possible to do efficient message threading by only using Subject and date fields. And grepping same subjects is lot easier than from this horrible mess. Note that all text is on one line, the subject has been broken only for visual reasons: Subject: re- Re^2: Re[32]: FW: Re: Re(15) Sv: Re[9]: -reply (fwd) [fwd] fw: [FWD: [FWD:]] -subj subj: subj: subj- test This recipe standardizes any subject (like above) that has been replied to, to de facto format below. That is: "Any number of 'Re:' will be converted to *single* 'Re:' and any number of 'Fwd:' will be converted to *single* 'Fwd:'" Subject: Re: test (fwd) About In-Reply-To header If there is `In-Reply-to' header in the message, but there is not *Re:* in the subject line, one is added automatically. Some broken Mailers forget to add the *Re:* to the Subject line. Variable JA_SUBJECT_SAVE This is by default `yes' which causes the original subject to be saved under header field `X-Old-Subject'. If you don't want that extra header generated, set this variable to `no' Variable JA_SUBJECT_FWD_KILL This is by default `yes', which will kill extra forwarding indication words like (fwd) [fwd] . If you set this to `no', then all the forwarding words are preserved. The de facto forward format is: Subject: This subject (fwd) Code note This subroutine's intention is to make Subject more expressive by deleting redundant information. A simplistic approach has been taken where Subject consists of list of *words* whose each attribute can be either `ok' or `delete'. No attempt has been made to determine the structure of the Subject. You can see the algorithm better from an example: Re: New subject (was Re: Old subject) That should be treated syntactically like "New subject" and forgetting anything between parenthesis. This is however not respected and not even tried. The rule applied here is "One Re: is tolerated", so the subject won't change. It doesn't matter where "Re:" is. But here the subject is changed. The rule applied is: Delete all unwanted _words_ and then add one Re: to the beginning if OLD content had any Reply indications Re: New subject (was Re: Old subject) --> Re: New subject (was Old subject) IMPORTANT notice Please check that your `SHELL' variable setting in `~/procmailrc' is `sh' derivate, /bin/sh or /bin/bash. This module won't work with other shells. Awk usage note `awk' is a small, effective and much smaller than perl for little tasks. See the verbose log and make sure your awk understands VAR="value" passing syntax. Change it to `nawk' or `gawk' if they work better than your standard awk. AWK = "gawk" # you may need this, try also gawk Customizations Let's say Polish M$Outlook uses `ODP:' instead of standard `re:' and you want to handle that too: Then set: JA_SUBJECT_KILL = "odp:" # NOTE: all lowercase JA_SUBJECT_SAVE = "no" INCLUDERC = $PMSRC/pm-jasubject.rc You ca use `JA_SUBJECT_KILL' to delete any additional words from the subject line. E.g. if you have good news-reader, you don't need the mailing list prefixes that some mailing lists add to the beginning Subject: [LIST-xxx] the subject here to remove that list prefix, you simply match it JA_SUBJECT_KILL = "(list-xxx|list-yyy)" Important: The regexp must be _all_ lowercase, because when match happens, the words have been converted to lowercase. Example usage You need nothing special, just include this recipe before you save message to folder. INCLUDERC = $PMSRC/pm-jasubject.rc Debugging You can dry-run test this module with following command and watching output. Substitute variables as they are in your system. You feed the content of entire example mail where the Subject that needs correction is found. % procmail SHELL=/bin/sh AWK=gawk VERBOSE=on LOGABSTRACT=all \ DEFAULT=/dev/null LOGFILE=$(tty) \ JA_SUBJECT_KILL="(ace-users)" \ PMSRC=/path/to/install/dir \ /path/to/pm-jasubject.rc \ < ~/test.mail Thank you Thanks to for his creative improvement suggestions and sending code that this recipe didn't catch at first. Pm-jatime.rc -- "hh:mm:ss" time parser from variable INPUT File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This includerc parses date from variable INPUT which has string "hh:mm:ss" Example input "Thu, 13 Nov 1997 11:43:23 +0200" Returned values hh = 2 digits mm = 2 digits ss = 2 digits Variable ERROR is set to "yes" if it couldn't recognize the INPUT and couldn't parse all hh, mm, ss variables. Required settings PMSRC must point to source directory of procmail code. This subroutine will include pm-javar.rc from there. Call arguments (variables to set before calling) INPUT = string-to-parse The INPUT can be anything as long as it contains NN:NN:NN Usage example Get the time of received message. The From_ header will always have the standard time stamp. PMSRC = $HOME/pm RC_DATE_TIME = $PMSRC/pm-jatime.rc :0 c * ^From +\/.* { INPUT = $MATCH # Turn off the logging while executing this part VERBOSE=off INCLUDERC = $RC_DATE_TIME VERBOSE=on :0 * ERROR ?? yes { # Should not ever happen, you have broken From_ } } Pm-jaube1.rc -- Jari's UBE filter. Subroutine 1 File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Documentation This file is part of the "pm-jaube.rc". This subroutine is called when likely UBE message has been triggered. Required settings PMSRC must point to source directory of procmail code. This recipe file will include o pm-jastore.rc Pm-jaube-keywords.rc -- Bare bones word list based UBE filter File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your UBE (aka spam) filters towards the _end_ of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked. Now, if 50-70 % hit rate is good enough for your starting point, go ahead and read more. This file is supposed to be the last resort, if you really do not have any better tool to analyze messages. Overview of features o Word and phrase based matching o 50-70 % success rate. 90 % never achieved. That's a guarantee. o Extremely fast and a dream to CPU resources. Implemented in pure procmail and you can almost hear the humming sound of its regular expression engine shredding UBE messages to pieces. Description Are you sure you want use this word list based checking? Think twice before you use this subroutine. It knows nothing about the content your mail. "It's all UBE unless proven otherwise" is the motto. The brutal search tracks words and phrases to find an indication of mass posting and traces of Unsolicited Bulk Email (UBE aka spam). _Repeat:_ Read the first paragraph again before you consider putting this file into action. This filter WILL PASS through unwanted mail and it WILL catch good mail. This is rule based matching, so I suppose you know where you're putting your head with this. Ahem. Alerted? Good. The Story There was a man and mail account. The account had limited space, couldn't install any other programs because disk quota would have exceeded. System administrators weren't' interested in installing anything. The Mail server ran behind firewall and had OS that was never heard of - it couldn't run other programs. Or if it could, the Bad system administrator was too scared to install extra programs to the host MTA ran. No joy -- no means to stop incoming UBE -- Right? Wrong. There was procmail. The Bad system adminitrator didn't mention that `~/.procmailrc' was honored - just the the external programs we a no-no-no (Technical: the MDA host mounted user disks; the server ran on separate host and couldn't use any of the user compiled programs. Statically linked ones filled up the man's disk space). First line of defense, any defense would do. So, this rule based file was born. Nothing else was installed in that account and the happy word list based matching routine kept chewing mail, mail, mail. And the system administrator was happy - he nurtured the MTA host's CPU resources and noticed nothing alarming. All ticked like clockwork. Life began again. After 1000 mail bombards a day, the account was usable again. Motivation If you can, use the Bayesian filters and forget all rule based ones, word and phrase matching based ones; all static filters. On the other hand, if you want quick solution, even imperfect, until you have time to learn and setup other tools, this subroutine may be of interest. The best part. You can carry this single file anywhere where procmail lives. No other files are needed. Setup couldn't be simpler. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address is usually forged. Do not increase the network traffic. Instead save the messages to folders and periodically check their contents. It's not nice to be forced to apologize about bounces to a wrong destination. Code Note Procmail is picky about the whitespace in continuing lines, make sure there is _not_ a single spaces left after the continuation backslash. Use good editors or external programs to get rid of the white spaces. In Emacs you would add this line to your `~/.emacs' startup file: "(add-hook 'write-file-hooks 'delete-trailing-whitespace)" :0 * ^Subject:.*(regexp\ |and-more\ |and-more\ ) { # Process it } Why are the regexps put into this file and not to a separate regexp file? Good question. It is possible to check message's content with external process, like `grep', to see if any matches are found. This kind of methodology is covered in Procmail Tips section "Using grep with file lists to mach messages" at . The reason why all the regexp are maintained inside this file is: o Simplicity. One file - no extra configuration files or regexp databases. o Self standing. Does not call external processes, so it's a little faster than possible `grep' and `fgrep' solution. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o JA_UBE_KEYWORD_HEADER, if set, then the results are put to messages headers. By default this variable is not defined to save from external `formail' process call. Suggestion: "X-Spam-JaubeKwd"; without trailing colon. Return values o `ERROR_STATUS' is set to word "Bad" otherwise empty. o `ERROR' is set to short descriptive word that indicate which rule was matched. Values: *Header-FromKeywords*, *Header-SubjectKeywords* and *Body-Keywords* o `ERROR_MATCH' is set to some words that happened to trigger UBE catch rule. Usage example PMSRC = "/path/to/procmail/lib" # Exclude these addresses from tests VALID_FROM = "(my@address.example.com|word@here.example.com)" :0 *$ ! ^From:.*$VALID_FROM * ! FROM_DAEMON { INCLUDERC = $PMSRC/pm-jaube-keywords.rc # Variable "ERROR" is set if message was UBE :0 : * ! ERROR ?? ^^^^ junk.ube.spool } File layout The layout of this file is managed by Emacs packages tinyprocmal.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-spamprobe.rc -- Interface to Annoyance Filter program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ mkdir $HOME/.annoyance $ DB=$HOME/.annoyance/dict.bin; DB2=$HOME/.annoyance/fdict.bin $ annoyance-filter --mail single.msg --prune --write $DB $ annoyance-filter --phrasemax 2 \ --read $DB \ --junk dir/to/bad/messages \ --prune --write $DB $ annoyance-filter -v --read $DB --prune --fwrite $DB2 To check message: $ annoyance-filter --read $DB --test mail.msg $ annoyance-filter --fread $DB2 -v --class mail.msg Overview of features o Implements interface to http://sourceforge.net/projects/annoyancefilter/ project. See article "Training Annoyance Filter to combat spam" by Corrado Cau at http://www.newsforge.com/software/03/10/24/2046238.shtml?tid=74 o variable `ERROR' is set if the message was UBE. o Results are available by default in header `X-Spam-Annoyance-Status'. Description There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program `annoyance-filter', which must already have been installed. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `annoyance-filter' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_ANNOYANCE_PRG = /usr/bin/spamprobe If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o `JA_UBE_ANNOYANCE_PRG', path to the program [required]. o `JA_UBE_ANNOYANCE_SPAM_DB', path to the dictionary database [required]. E.g. `$HOME/.annoyance/dict.db'. o `JA_UBE_ANNOYANCE_SPAM_DB_OPT', type of dictionary to read. Default is "--read", but this could be fast dictionary option "--fread". o `JA_UBE_ANNOYANCE_HEADER', the header name where the results are put. If not defined, no header is added. Defaults to *X-Spam-Annoyance-Status* o `JA_UBE_ANNOYANCE_FORCE', if set to _yes_ then call program no matter what. Normally if there already is *X-Spam-Annoyance-Status* header, it is assumed that the message has already been checked and no new checking is needed. Return values o ERROR, is set to the return value of the program. Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_ANNOYANCE_PRG = "/usr/bin/nice -n 5 /usr/bin/annoyance-filter" JA_UBE_ANNOYANCE_SPAM_DB = $HOME/.annoyance/dict.db INCLUDERC = $PMSRC/pm-jaube-prg-spamprobe.rc # The ERROR will contains word "yes" if message was spam :0 : * ERROR ?? yes junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-bmf.rc -- Interface to Bayesian Mail Filter program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ ls spam/*.mail | xargs -n 1 bmf -s # feed individual messages $ ls good/*.mail | xargs -n 1 bmf -n # feed individual messages To test $ bmf -p < test.mail | less Overview of features o Implements interface to http://www.sf.net/projects/bmf "Bayesian Mail Filter" project. The called binary is "bmf" hence the name of this subroutine. Bmf program uses well know statistical analysis which is much more reliable than any hand made procmail scripts could ever achieve. o Variable `ERROR' is set if the message was UBE. o Results are available in headers `X-Spam-bmf-Status' and `X-Spam-bmf-Flag' for further analysis. Description There are several bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. For serious discussion of strenghts of the different programs, refer to a very good article "Spam Filters" by Sam Holden at 2004-08-16 . The article evaluated throughly following programs: o Bayesian Mail Filter (bayesian) o Bogofilter (bayesian) o dbacl (bayesian; multiple wordlists) o Quick Spam Filter (bayesian) o SpamAssassin (perl matching + bayesian) o SpamProbe (bayesian) o SPASTIC (procmail recipes) This subroutine implements call interface to `bmf' program. Why whould you need it? Because unfortunately `bmf' by default use exactly the same headers as spamasassin and the two cannot co-operate together: bmf would overwrite existing spamassasin headers. This subroutine takes care of saving previous headers and move `bmf' results to their own `X-Spam-bmf-*' headers. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `bmf' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_BMF_PRG = "/usr/bin/bmf" If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o JA_UBE_BMF_PRG, path to program o JA_UBE_BMF_HEADER_PREFIX, the header name where the results are put. If not defined, no headers are added. Default value is `X-Spam-bmf'. o JA_UBE_BMF_FORCE, if set to _yes_ then call program no matter what. Normally if there already are `X-Spam-bmf-*' headers, it is assumed that the message has already been checked and no new checking is needed. Return values o ERROR, is set to short ube trigger recipe reason. Contains content of `X-Spam-bmf-Status' header which you can check for values o ERROR_MATCH contains detailed content of `X-Spam-bmf-Status' header. If headers were enabled, they will contain: X-Spam-bmf-Status: Yes, hits=1.000000 required=0.900000, tests=bmf X-Spam-bmf-Flag: YES Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_BMF_PRG = "/usr/bin/nice -n 5 /usr/bin/bmf" INCLUDERC = $PMSRC/pm-jaube-prg-bmf.rc # The ERROR will contains word "yes" if it program classified # the message into "bad" category. :0 : * ERROR ?? yes junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-bogofilter -- Interface to bogofilter program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ rm -f ~/.bogofilter/*.db # delete database $ bogofilter -B -n good.msg ... $ bogofilter -B -s spam.msg ... Overview of features o Implements interface to http://www.sf.net/projects/bogofilter project. o variable `ERROR' is set if message was likely spam. o Results are available by default in header `X-Spam-Bogofilter-Status'. Description There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program `bogofilter', which must already have been installed. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `bogofilter' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_BOGOFILTER_PRG = /usr/bin/bogofilter If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o JA_UBE_BOGOFILTER_PRG, path to the program o JA_UBE_BOGOFILTER_HEADER_NEW, the header name where the results are put. If not defined, no header is added. Defaults to `X-Spam-Bogofilter-Status' o JA_UBE_BOGOFILTER_FORCE, if set to _yes_ then call program no matter what. Normally if there already is `X-Spam-*' header, it is assumed that the message has already been checked and no new checking is needed. Return values o ERROR, is set to the return value of program if message was spam. o ERROR_INFO, is set if case is "unsure". Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_BOGOFILTER_PRG = "/usr/bin/nice -n 5 /usr/bin/bogogilter" INCLUDERC = $PMSRC/pm-jaube-prg-bogofilter.rc # The ERROR will contains reason if program classified # the message into "bad" category. :0 : * ! ERROR ?? ^^^^ junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-bsfilter.rc -- Interface to Bsfilter program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ bsfilter --add-clean good.msg ... $ bsfilter --add-spam spam.msg ... Overview of features o Implements interface to project http://packages.debian.org/testing/mail/bsfilter o variable `ERROR' is set if the message was UBE. o Results are available by default in header `X-Spam-Bsfilter-Status'. Description There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program `bsfilter', which must already have been installed. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `bsfilter' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_BSFILTER_PRG = /usr/bin/bsfilter If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o `JA_UBE_BSFILTER_PRG', path to the program. o `JA_UBE_BSFILTER_HEADER', the header prefix name where the results are put. If not defined, no header is added. Defaults to *X-Spam-Bsfilter-* o `JA_UBE_BSFILTER_FORCE', if set to _yes_ then call program no matter what. Normally if there already is *X-Spam-Bsfilter-* header, it is assumed that the message has already been checked and no new checking is needed. Return values o `ERROR', is set to the return value of `bsfilter' program. Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_BSFILTER_PRG = "/usr/bin/nice -n 5 /usr/bin/bsfilter" INCLUDERC = $PMSRC/pm-jaube-prg-bsfilter.rc # The ERROR will contains word "yes" if message was spam :0 : * ERROR ?? yes junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-ifile -- Interface to ifile program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ rm ~/.idata # delete database $ echo herbalife | ifile -i spam # initialize database $ ifile -h -i good good.msg ... $ ifile -h -i spam spam.msg ... Overview of features o Implements interface to http://freshmeat.net/projects/ifile project. o variable `ERROR' is set to the result of ifile check. This usually holds the "folder" name the ifile was trained at the time. E.g. if the folder used for training Unsolicited Bulk Email was "ifile -i spam", then the return value is "spam". o Results are available by default in header `X-Spamifile'. Description There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program `ifile', which must already have been installed. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `ifile' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_IFILE_PRG = /usr/bin/ifile If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o JA_UBE_IFILE_PRG, path to the program o JA_UBE_IFILE_HEADER, the header name where the results are put. If not defined, no header is added. Defaults to `X-Spam-Ifile-Status' o JA_UBE_IFILE_FORCE, if set to _yes_ then call program no matter what. Normally if there already is header, it is assumed that the message has already been checked and no new checking is needed. Return values o ERROR, is set to the return value of `ifile' program. If header output is enabled, it will contain the folder name `ifile' thinks the message belongs to. Assuming that trained folders used for messages were *spam* and *good*, then the headers read: X-Spam-Ifile-Status: spam X-Spam-Ifile-Status: good Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_IFILE_PRG = "/usr/bin/nice -n 5 /usr/bin/ifile" INCLUDERC = $PMSRC/pm-jaube-prg-ifile.rc # The ERROR will contains reason if program classified # the message into "bad" category. :0 : * ! ERROR ?? ^^^^ junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-runall.rc -- Interface to all Bayesian filter programs File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Overview of features o To detect spam reliably, run all Bayesian programs one by one to see if any of them classifies the message as spam. o Programs supported: bogofilter, spamprobe, Bayesian Mail Filter, Annoyance Filter, Bsfilter, Spamoracle and Spamassassin. Description There are several bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. This module is a _meta_ _package_ which will call all other individual modules that interface to these Bayesian programs. The use is simple: define programs that are available in your system and which you have trained (Bayesian programs need to be trained before use), and this this module will query how those programs would classify the message. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc o pm-jaube-prg-spamprobe.rc o pm-jaube-prg-spamoracle.rc o pm-jaube-prg-annoyance-filter.rc o pm-jaube-prg-bsfilter.rc o pm-jaube-prg-bmf.rc Call arguments (variables to set before calling) To activate Bayesian program(s), define path to them. Default value for all these variables is "" i.e. is is supposed that no programs have been installed or trained. o `JA_UBE_BOGOFILTER_PRG', path to *bogofilter* program. o `JA_UBE_SPAMPROBE_PRG', Path to *spamprobe* program o `JA_UBE_BMF_PRG', Path to Bayesian Mail Filter *bmf* program. o `JA_UBE_SPAMASSASSIN_PRG', path to *spamassassin* program. If daemon version is available, set this to *spamc* program. o `JA_UBE_SPAMORACLE_PRG', path to *spamoracle* program. o `JA_UBE_ANNOYANCE_PRG', path to *annoyance-filter* program. You must also set `JA_UBE_ANNOYANCE_SPAM_DB' to fast dictionary database location. o `JA_UBE_BSFILTER_PRG', path to *bsfilter* program. Optional variables to set: o `JA_UBE_BOGOFILTER_OPT'. Default is "-p" passthrough. Option "-e" will report exit code to procmail. o `JA_UBE_SPAMASSASSIN_OPT'. Default is "". o `JA_UBE_SPAMASSASSIN_MAX_SIZE'. Default is 256000 (256k). Spamassassin is a Perl program, which is slow at startup, so checking e.g. long attachements consumes lot of resources. Keep this value relatively small. Important notes All headers are canonicalized to *X-Spam--* so e.g. in bogofilter's case, the default *X-Bogocity* header is changed to value *X-Spam-Bogofilter-Status* and so on. Summaries like below can then be generated: $ egrep -i '(Subject|From|^X-Spam.*Status)' *.mbox Return values o `ERROR' variable's first word is set to program that classified the spam: *bogofilter*, *bmf* (Bayesian Mail Filter), *spamassassin* etc. It is followed by semicolon ";" and detailed return status from the program. o `ERROR_INFO' is set only in bogofilter's case if it thinks the message is neither spam nor ham ("Unsure"). Usage example PMSRC = $HOME/procmail # procmail recipe dir # ... other checks, mailing lists, work mail etc. # bogofilter and Bayesian Mail Filter available and trained. Use them. JA_UBE_BOGOFILTER_PRG = "/bin/nice -n 5 /bin/bogofilter" JA_UBE_BMF_PRG = "/bin/nice -n 5 /bin/bmf" # Call the "umbrella" module, which will take care of # all the details. INCLUDERC = $PMSRC/pm-jaube-prg-runall.rc # ERROR is set if message was spam. The "()\/" logs reason. :0 : * ERROR ?? ^()\/.+ junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-spamassassin -- Interface to spamassassin program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ rm -f ~/.spamassassin/bayes* $ sa-learn $opt --local --no-rebuild --ham good.msg ... $ sa-learn $opt --local --no-rebuild --spam spam.msg ... $ sa-learn --rebuild Overview of features o Implements interface to http://www.spamassassin.org/ project. o variable `ERROR' is set if message was spam. o Results are available in default headers (X-Spam-*) Description There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program `spamassassin', which must already have been installed. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `spamassassin' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_SPAMASSASSIN_PRG = /usr/bin/spamassassin If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o JA_UBE_SPAMASSASSIN_PRG, path to the program o JA_UBE_SPAMASSASSIN_MIN_SIZE, minumum message size. Default is 100 bytes. o JA_UBE_SPAMASSASSIN_MAX_SIZE, maximum message size. Default is 256 000 bytes (about 256k). o JA_UBE_SPAMASSASSIN_FORCE, if set to _yes_ then call program no matter what. Normally if there already is `X-Spam-*' header, it is assumed that the message has already been checked and no new checking is needed. Return values o ERROR, is set to the return value of program if message was spam. o ERROR_INFO, is set if case is "unsure". Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/nice -n 5 /usr/bin/bogofilter" INCLUDERC = $PMSRC/pm-jaube-prg-spamassassin.rc # The ERROR will contains reason if program classified # the message into "bad" category. :0 : * ! ERROR ?? ^^^^ junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-spamoracle.rc -- Interface to Spamoracle program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ spamoracle add -v -spam good.msg ... # feed individual messages $ spamoracle add -v -good good.msg ... # feed individual messages To test $ spamoracle test mail.msg | less Overview of features o Implements interface to http://freshmeat.net/projects/spamoracle OCaml language based Bayesian Mail program. o Variable `ERROR' is set to "yes" if the message was UBE. o Results are available in headers `X-Spam-Spamoracle-Status', `X-Spam-Spamoracle-Score', `X-Spam-Spamoracle-Details' and `X-Spam-Spamoracle-Attachment' for further analysis. Description There are several bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. Using Spamoracle as sole spam protection is inefficient, because version version 1.4 (2004-09-29) does not accept messages from stdin. Becaus of this message has to be written to a temporary file before calling Spamoracle. Later the temporary file must be removed with `rm'. All these three shell calls are needed for each message. If you have other detection programs, call them first to identify unsolicited Bulk Email. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `spamoracle' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_SPAMORACLE_PRG = /usr/bin/spamoracle If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o `JA_UBE_SPAMORACLE_PRG', path to program o `JA_UBE_SPAMORACLE_HEADER_PREFIX', the header name where the results are put. If not defined, no headers are added. Default value is *X-Spam-Spamoracle'*. o `JA_UBE_SPAMORACLE_FORCE', if set to _yes_ then call program no matter what. Normally if there already are *X-Spam-Spamoracle-* headers, it is assumed that the message has already been checked and no new checking is needed. o `JA_UBE_SPAMORACLE_REGEXP', regexp to match for spam probability. Defaul value will match probabbility of 0.8 with 5 interesting words. The match is tried agains *X-Spam-Spamoracle-Score* header. Return values o `ERROR', value "yes" if `JA_UBE_SPAMORACLE_REGEXP' matched. o `ERROR_MATCH' contains detailed content of `X-Spam-Spamoracle-Score' header. If headers were enabled, they will contain these values. The score's values are spam probability 0.0 - 1.0 and the degree of similarity 0-15 of the message with the spam messages in the corpus. X-Spam-Spamoracle-Status: yes X-Spam-Spamoracle-Score: 1.00 -- 15 X-Spam-Spamoracle-Details: refid:98 $$$$:98 surfing:98 asp:95 click:93 cable:92 instantly:90 https:88 internet:87 www:86 U4:85 isn't:14 month:81 com:75 surf:75 X-Spam-Spamoracle-Attachments: cset="GB2312" type="application/octet-stream" name="Guangwen4.zip" Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_SPAMORACLE_PRG = "/usr/bin/nice -n 5 /usr/bin/bmf" INCLUDERC = $PMSRC/pm-jaube-prg-spamoracle.rc # The ERROR will contains word "yes" if it program classified # the message into "bad" category. :0 : * ERROR ?? yes junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube-prg-spamprobe.rc -- Interface to Spamprobe program File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your Unsolicited Bulk Emacil (aka spam) filters towards the end of your `~/.procmailrc'. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked last. YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE BAYESIAN PROGRAM FIRST! To train: $ spamprobe -8 good good.msg ... $ spamprobe -8 spam spam.msg ... Make sure there are no stale lock files, or the spamprobe and this subroutine will hang infinitely: $ rm -f ~/.spamprobe/lock Overview of features o Implements interface to http://freshmeat.net/projects/spamprobe/ project. o variable `ERROR' is set if the message was UBE. o Results are available by default in header `X-Spam-Spamprobe-Status'. Description There are several Bayesian based statistical analysis programs that study the message's tokens and then classify it into two categories: good or bad, or if you like, ham and spam. All the Bayesian programs are not the same, so if you want to achive magic 99.99% probability the only methodology to do that is to chain several programs in serially. There is no single program that can solve the UBE detection. This procmail subroutine implements call interface to program `spamprobe', which must already have been installed. About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address forged. Do not increase the network traffic; you will not do any good to anybody by bouncing messgas -- you just increase mail traffic even more. Instead save the messages to folders and periodically periodically check their contents. Required settings If `spamprobe' program is available, define this variable in your `~/.procmailrc'. Use absolute path to make the external shell quick; it'll save server load considerably. JA_UBE_SPAMPROBE_PRG = /usr/bin/spamprobe If you _do_ _not_ have program installed, do not leave the variable lying aroung, because it will keep this subroutine active. Calling a non existing program is not a good idea, so it better to empty the variable if the program is not available. Required settings None. No dependencies to other procmail modules. Call arguments (variables to set before calling) o `JA_UBE_SPAMPROBE_PRG', path to the program. o `JA_UBE_SPAMPROBE_HEADER', the header name where the results are put. If not defined, no header is added. Defaults to *X-Spam-Spamprobe-Status* o `JA_UBE_SPAMPROBE_FORCE', if set to _yes_ then call program no matter what. Normally if there already is *X-Spam-Spamprobe-Status* header, it is assumed that the message has already been checked and no new checking is needed. Return values o `ERROR', is set to the return value of `spamprobe' program. Usage example PMSRC = $HOME/procmail # procmail recipe dir JA_UBE_SPAMPROBE_PRG = "/usr/bin/nice -n 5 /usr/bin/spamprobe" INCLUDERC = $PMSRC/pm-jaube-prg-spamprobe.rc # The ERROR will contains word "yes" if message was spam :0 : * ERROR ?? yes junk.mbox File layout The layout of this file is managed by Emacs packages tinyprocmail.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-jaube.rc -- Unsolicited Bulk Email (UBE) filter. File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Warning Put all your UBE (aka spam) filters towards the _end_ of your ~/.procmailrc. The idea is that valid messages are filed first (mailing lists, your work and private mail, bounces) and only the uncategorized messages are checked. Are you sure you want to use procmail for UBE? If you think you can put this recipe as a first line of defence to your mail, you will disappoint. Checking UBE with procmail's rule based means does not work that way. The good messages must be sorted first (like your mailing lists and your important work or friend message) and only then what's left to process can be scanned by static rule based tools, like this procmail module. There are much more better tools that are based on statistical analysis of messages. You really should consider using one or combination of Bayesian tools: *Spamassassin*, *bogofilter*, *spamprobe*, *Bayesian* *Mail* *Filter*, *ifile* etc. _Repeat:_ procmail rules are not the tool to UBE control. The pattern matching rules can never keep up with the spammers. That said, if you: o Can bare a 70-80 % UBE detection rate. o Can bare 10 % false hits; you need to check you UBE folder regularly for messaged that did not belong there. o Have an account that does not get large number of UBE messages. o Or if procmail is all you have in the system. only then consider this module or any other procmail based spam filters in that respect. So, please don't set your expectations high. Spend good time with the configuration variables and check there returned result in variable `ERROR' carefully. Good luck. Overview of features o Requires procmail 3.11pre7+ o You don't need external files: site block lists, the heuristics nail most of the UBE messages. Just plug in this module and you have UBE shield active. o Header based filtering: Minimum headers, Pegasus bulk mail, X-uidl validity check, bogus From-To combination, o Address based filtering: Numeric address, Invalid address (eg. me@myMarketing.global), UBE-like(friend,remove request.) o Text filtering: no html accepted, common advertising slogans, unnecessary many capitalized words, HTML message body detection, o And many more check that just not were listed here. Remember: this is not 100% and there will always be some mishits, so don't just junk messages to `/dev/null'. Description Originally Daniel Smith posted his spam.rc, where he had gathered many tips and heuristics to filter UBE email. This filter here expresses work of many procmail users. Original filters were modified, some rules were left out that catched false email messages and made the package look a bit more general so that it could be included via `INCLUDERC' in the standard way. Thanks to Daniel and others, the UBE bomb days can be reduced, when this filter is active. Some UBE messages may still lurk into the mailbox, but that's the problem with all static rule based tools. Logging the events A good strategy to follow incoming mail is to log the vital parts like Date, From, Subect to some log file and then a reason what happened to a message. The `~/Mail/mail.log' might look like: 1997-12-08 work@example.com Extra Holiday $$$$$ [jaube; Marketing-Big-ExitCode; LEGAL, MONEY-MAKING PHENOMENON] 1997-12-09 Denizen [RePol] hiding 1997-12-09 david X Re: Send list to incoming folder 1997-12-09 david X Re: Send list to incoming folder 1997-12-09 OMC manager "Environments updated" [my; work-localenv] 1997-12-09 doodle@example.org Re: Gnus (Emacs Newsreader) FAQ [my; emacs; Re: Gnus (Emacs Newsreader) FAQ ] First a UBE message that was identified and saved to folder. Next 3 messages were filed to mailing-list folders and there was no [] action displayed for them (left out due to high volume of these messages). Second Last was internal work message. Lastly someone asked somthign about Emacs. The basic incoming message log recipe could be like this. Variable `TODAY' is `$YYYY-$MM-$DD' whose values are set after calling `pm-jadate.rc'. The `LISTS' is user set variable to exclude mailing lists whose activity is not important. Variables `FROM' and `SUBJECT' are fields read the message's headers. BIFF = $HOME/Mail/mail.log INCLUDERC = $PMSRC/pm-jadate.rc ... :0 hwic: *$ ! $LISTS |echo "$TODAY $FROM $FSUBJECT" >> $BIFF Here is small perl script to print summary of trapped UBE messages from a log like above. It gives nice overview which recipes catch most of the UBE messages. perl -ne '/jaube; (\S+)/; $s{$1}++; \ END { $s = (map{$x += $_; $_= $x} values %s)[-1]; \ $i = int $s{$_}/$s *100; \ for (keys %s) { printf "$s{$_} $i $_\n" } \ }' \ mail.log | \ sort -nr Here is sample results during two month period There are total of 3248 UBE messages catched. count % type ------------------------------------------ 554 17 Marketing-CountBigLetterWords 457 14 Marketing 422 12 Marketing-SelectedBigLetterWords 349 10 AddrBogus-ToFrom 263 8 FromReceived-Mismatch 223 6 NoDirectAddress-ToCc 216 6 HdrForgedPegasus 164 5 AddrBogus-To 151 4 MessageId 102 3 BodyHtml 73 2 Received-IPError 63 1 Identical-FromTo 53 1 AddrInvalid 15 0 From-nslookup 9 0 HdrReceivedTime 7 0 HdrX-UIDL 4 0 Marketing-headers About bouncing message back The general consensus is, that you should not send bounces. The UBE sender is not there, because the address is usually forged. Do not increase the network traffic. Instead save the messages to folders and periodically check their contents. It's not nice to be forced to apologize if you bounced message to a wrong destination. DON'T BOUNCE. Forget all recipe examples that use HOST and EXITCODE and be a good Net citizen. Required settings PMSRC must point to source directory of procmail code. This recipe file will include o pm-javar.rc o pm-janslookup.rc o pm-jaaddr.rc Call arguments (variables to set before calling) Only handful of the most important variables are described here. You really should read all the comments placed in the "user configured section" in this procmail module's code. Most of the defaults should work out of the box. o `JA_UBE_VALID_ADDR', your email addresses or other valid from addresses that will say "this is mail addressed directly to you". o `JA_UBE_HDR', If non-empty, a new header is added which tells which recipe was triggered. The header is not added to message, if there is nothing to report; i.e. message passed all tests. o Various flags: Some of the ube detecting recipes give more false hits than nail real ube. Experiment with yourself and turn on or off the recipes that work for the kind of ube messages you receive. o `JA_UBE_MAX_BIG_WORDS', the maximum count of big letter words in the message that is tolerated. The current count 5 is rather conservative and it is suggested you to increase it to prevent trapping too many false hits. Alternatively update JA_UBE_CAPS_OK to include accepted words. o `JA_UBE_APPARENTLY_TO_MAX', how many Apparently-To headers are tolerated. Default is 3. o `JA_UBE_MAX_HTML_TAGS', maximum count of html tags allowed in the body. o `JA_UBE_ATTACHMENT_ILLEGAL_KILL', if set to "yes" (default), then illegal attachment from body is ripped off. This is brute way to truncate the message abruptly to save mailbox space. You still see the headers for tracking, but the body is gone. The regexp to test is set in `JA_UBE_ATTACHMENT_ILLEGAL_REGEXP'. o `JA_UBE_ATTACHMENT_SUSPECT_KILL', if set to "yes" (default "no"), kill suspectible characters in attachement filename. The regexp to test is set in `JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP'. o JA_UBE_CHARSET_LEGAL, if set, accept only these character. The default value detect messages with 7bit only (english speaking. For foreign language you may want to set this something like `$CHAR_7BIT_SET$CHAR_LIST_FINLAD' for Finnish. See `pm-javar.rc' for available character sets. Return values o `ERROR_STATUS', status word of checks. Value "Good" or "Bad" o `ERROR,' is set to short ube trigger recipe reason o `ERROR_MATCH', is set to some MATCH that happened while triggering UBE message. Alternatively you check content of header `JA_UBE_HDR' which contains results of the above variables. Possible values for `ERROR' are: AddrAOLinvalid AddrBogus-From AddrInvalid-From AddrInvalid-To AddrNumeric AddrNumericDomain AddrUbeLike BodyAttachment-FileIllegalAdditional BodyAttachment-FileIllegalMatch BodyAttachment-FileIllegalOther BodyAttachment-FileSuspect BodyCharacters-Illegal BodyHtml-NonMime BodyHtml-script BodyHtmlBase64 BodyHtmlImage BodyHtmlTags BodyMimeCharset-Illegal EnvelopeFrom-Invalid From-nslookup FromReceived-Mismatch HdrForgedPegasus HdrReceived HdrReceivedTime HdrX-Distribution HdrX-UIDL Header-ApparentlyTo HeaderCharacters-Illegal HeaderMimeCharset-Illegal Html-base64 Identical-FromTo Marketing-Body Marketing-CountBigLetterWords Marketing-SelectedBigLetterWords Marketing-Subject Marketing-SubjectGreeting MegaSpammer MessageId-Invalid MessageId-Empty NoDirectAddress-ToCc NotEnoughHeaders Received-IPError VirusBody VirusHeader Usage example # - All legimate messages should already been handled and saved before this recipe. # - Activate the filter only for messages that are not from # daemon and not from valid senders: like from "my" domain # and mailing lists and from somewhere else. VALID_FROM = "(my@address.example.com|word@here.example.com)" :0 *$ ! ^From:.*$VALID_FROM *$ ! FROM_DAEMON { # Do not add extra headers. This saves external shell call # (formail). Also do not try to kill the message content, # again saving one external call (awk). With these, the # recipe is faster and more CPU friendly. PM_JA_UBE_HDR = "" JA_UBE_ATTACHMENT_ILLEGAL_KILL = "no" INCLUDERC = $PMSRC/pm-jaube.rc # Variable "ERROR" is set if message was UBE, record error # to log file with "()\/" :0 : * ERROR ?? ()\/[a-z].* { # Don't save those *.exe, *.zip UBE attachements :0 * ERROR ?? attacment.*file /dev/null :0 : spam.mbox } } There may be UBE messages that fool `FROM_DAEMON' test, so you could also use something more finer check. The standard daemon error message almost always has sentence "Transcript of session follows" in the body. This recipe says: "Unless proven otherwise, I don't believe this is daemon message even if it looked like that". Add More "2^1" checks to raise score for other valid daemon cases. * -1^0 ^FROM_DAEMON * ! 2^1 B ?? Transcript of session follows { # ... Now call UBE checker } File layout The layout of this file is managed by Emacs packages tinyprocmal.el and tinytab.el for the 4 tab text placement. See project http://freshmeat.net/projects/emacs-tiny-tools/ Pm-javac.rc -- Procmail: Vacation framework recipe (id-cache) File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description Framework for all programs that need to reply to messages only once. Usually known as "vacation" feature. If you cahnge th cache file, you can attach this recipe to any messages that you want to deal with only once. Required settings PMSRC must point to source directory of procmail code. This subroutine will include o pm-javar.rc Call arguments (variables to set before calling) o JA_VAC, To activate vacation, set value to "yes" o JA_VAC_RC, When new message-id is found, run this includerc o JA_VAC_ID_CACHE, Remember to clear this file when you start the vacation. Usage example To turn on the vacation feature, create ~/.vac file and recipe below activates vacation. If the vacation is not active, then cache file is removed. (automatic cleanup). The VERBOSE is also turned off when you're on vacation; so that your procmail log will not get filled. So when you go to vacation, you 'touch ~/.vac' and update ~/vacation.msg. When you come back, you 'rm ~/.vac'. That's it. IMPORTANT: If you are subscribed to mailing lists, be sure to file messages from those services first and put the vacation recipe only after the list or bot messages. Also add sufficent "!" conditions in order not to reply to other "bot" service messages. JA_VAC_ID_CACHE = $HOME/.pm-vac.cache :0 *$ ? $IS_EXIST $HOME/.vac { VERBOSE = off JA_VAC = "yes" JA_VAC_RC = $PMSRC/pm-myvac.rc # my vacation recipe INCLUDERC = $PMSRC/pm-javac.rc # framework } :0 E # else * ? $IS_EXIST $JA_VAC_ID_CACHE { dummy = `$RM -f $JA_VAC_ID_CACHE` } Here is example of pm-myvac.rc recipe # Change subject :0 fhw * ^Subject: *\/[^ ].* | $FORMAIL -I "Subject: vacation (was: $MATCH)" :0 fb # put message to body | $CAT $HOME/.vacation.msg :0 # Send it | $SENDMAIL Pm-javar.rc -- Global variable definitions File id Copyright (C) 1997-2010 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at . Description This file defines common variables that you can use in the recipe's condition line. Procmail does not know about escape sequences like `\t' or `\n' and it is therefore much more readable to use variables as substitute for common regular expression atoms. Pay attention that the line starts with "*$ ", where "$" expands the variables: In this file, the variable names represent the well known Perl regular expression names, so that $s is alost like Perl expression \s (whitespace) and $S is almost equivalent to `\S' (non-whitespace). Similarly, $d is `\d' (digit) and $D resembled `\D' (non-digit). :0 *$ $s+something+$s+$d+$a+ The equivalent without variables (you don't see the tabs and spaces here): :0 # Space + tab * [ ]something[ ][0-9]+[a-z]+ In addition all system dependent variables are defined in this module. For example if you have Gnu awk, it is strongly suggest that you set: AWK = "/path/to/gawk" # in Linux, this would be /usr/bin/awk You can define these variables before or after the module, just make sure the binaries reflect your operating system's paths. In general, if you "port" your setup to several system, dont' include absolute paths. In the other hand, if your setup is in the same place using absolute paths will speed up executions by a factor of 3 or more. (depending on how long your PATH is) Standard variables defined See pm-tips.txt file for full explanation or look at the source code. SPC WSPC NSPC SPCL # Whitespace, Non Whitespace, W+linefeed \s \d \D \w \W and \a \A # perl equivalents Special variable JA_FROM_DAEMON In order to boost procmail and to save extra CPU cycles, this module defines variable `JA_FROM_DAEMON' that caches the information of ^FROM_DAEMON. You can refer to `JA_FROM_DAEMON' as you would to big brother FROM_DAEMON. This has the advantage that procmail has already computed the result and the variable `JA_FROM_DAEMON' is used as a cache, thus avoiding repeated FROM_DAEMON regexp tests, which are expensive. Variable `JA_FROM_DAEMON_match' contains "" or the result of matched daemon text. *$ $JA_FROM_DAEMON or the familiar *$ ! $JA_FROM_DAEMON Instead of using the regexp parsing with * ^FROM_DAEMON and * ! ^FROM_DAEMON Special variable JA_FROM_MAILER Works like `JA_FROM_DAEMON' variable but in respect to FROM_MAILER. The matches text is in `JA_FROM_MAILER_MATCH' Usage example For your .procmailrc, you can simply put this, because you want to load the variables at startup PMSRC = "/path/to/install/location/of/this/library" INCLUDERC = $PMSRC/pm-javar.rc If you're developing your own modules that use these variables put these lines at the beginning. `~/.procmailrc'. It checks if WSPC variable does not include a space --> load the variable definitions. If the variable is already defined, the file is not loaded. The test line is something alike #ifdef -- #endif in C/C++ language or a conditional "import" command in other languages. :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } Defined modules After this file loads, you can refer to any module with $RC_JA_MODULE. E.g. to call email spit module in your code you would use following. See at the end of this file for all defined module names. INCLUDERC = $RC_JA_UBE procmail-lib-2009.1202/lib-stebbens/000077500000000000000000000000001130547513300167565ustar00rootroot00000000000000procmail-lib-2009.1202/lib-stebbens/00README000066400000000000000000000101651130547513300200010ustar00rootroot00000000000000This is the README file for Alan Stebbens' procmail library. See below for some information on procmail itself. Here is a quick synopsis of the files: Makefile a Unix Makefile to help install these libary files in /usr/local, or another location. README This file. ackmail.rc a set of recipes which perfom auto-acknowledgement of incoming mail. This file uses guess-mua.rc and unread-mh.rc. See ackmail.3 for details. commands.help A file of information sent in response to a mail request of "Subject: help info". See "commands.rc". commands.rc A set of recipes which recognize commands in the Subject: header and perform them. A log is kept of all such commands. comm-reply-file.rc A recipe file which replaces the body of the current message with a named, or generates an error report. A "subroutine" recipe file for "commands.rc". correct-addr.rc A recipe file which can help do mail forwarding for users who have moved or changed email addresses. *** CURRENTLY NOT WELL TESTED *** date.rc A recipe file to extract date and time information from the DATE variable, or from the current mail buffer if DATE is not defined. dupcheck.rc A recipe file which removes duplicate mail. get-date.rc A recipe file which uses date.rc to extract date and time information from date fields of the current message. get-from.rc A recipe file which extracts the "best" address, including personal information from the various originating address fields. guess-mua.rc A recipe file which attempts to guess the current MUA (Mail User Agent). Not needed of MUA is explicitly defined. headers.rc Defines some variables which can be used for matching against headers. list-addr.rc A recipe file which trys to determine if the current mail is from a mailing list or not. This is still *experimental* and *** NOT WELL TESTED ***. pf-check.rc A recipe to check if the message is from a given ADDR, or if it is from the user and to the ADDR, then to add DEST to the pending folder list, PF_DEST. pf-chkto.rc A recipe to check of the message is to an ADDR, and to add DEST to the pending folder list, PF_DEST. pf-save.rc After all address checks have been done, via either pf-check.rc or pf-chkto.rc, then perform the filing into folders named by PF_DEST. The folders can either be MH-style or folder-file style (but not both). proclint A Perl script which attempts to parse and pick "lints" from procmail scripts. procmail-lib.html An HTML file which describes the Procmail Library. unread-mh.rc A recipe file which attempts to compute how many unread messages there are for an MH user. If you have improvements or contributions to this collection of recipes, please send them to me at . I may not respond quickly to any submissions, but I always appreciate suggestions for improvement. -------------------------------------------------- Procmail is a mail filtering program, with which a user can process incoming mail in an infinite number of ways. Procmail is publicly available at no cost, other than your time. Procmail, SmartList, and my procmail library are available via HTTP: The latest versions of procmail I have: http://reality.sgi.com/aks/depot/mail/procmail/procmail.tar.gz http://reality.sgi.com/aks/depot/mail/procmail/SmartList.tar.gz Specific versions of procmail and SmartList: http://reality.sgi.com/aks/depot/mail/procmail/procmail-3.11pre4+.tar.gz http://reality.sgi.com/aks/depot/mail/procmail/SmartList-3.11pre4.tar.gz My procmail library is at: http://reality.sgi.com/aks/depot/mail/procmail/procmail-lib.shar If you have any questions about using procmail, there is a mailing list with lots of helpful members: . Use the address: to subscribe to the list. -------------------------------------------------- The latest version of procmail can be obtained directly from the ftp-archive at: ftp.informatik.rwth-aachen.de (137.226.225.3) as (g)zipped tar file: /pub/packages/procmail/procmail.tar.gz <160KB as compressed tar file: /pub/packages/procmail/procmail.tar.Z <224KB procmail-lib-2009.1202/lib-stebbens/01README.txt000066400000000000000000000011561130547513300206200ustar00rootroot00000000000000lib-stebbens/01README.txt The original libraries were available (2002-01-02) from Alan's file server (there was no other download method known). The original request used was: Subject: send procmail lib To: Alan K. Stebbens If you have any questions concerning about programs or code in this directory, please contact Alan. NOTE: There is no support for these modules, so bug reports against them is probably in vain (unless you can contact Alan directly). -- 2008-09-19 Jari Aalto End procmail-lib-2009.1202/lib-stebbens/ChangeLog000066400000000000000000000025201130547513300205270ustar00rootroot000000000000002009-12-02 Jari Aalto * proclint.1.pod: (BUG): Document unsupported features; Debian . 2009-08-17 Jari Aalto * proclint Convert braces to modern line-up style. (Main): Remove extra space from RE '-l|--list'. Thanks to Dan Garthwaite. Closes: http://savannah.nongnu.org/support/?106985 2008-12-09 Jari Aalto * proclint.1.pod: Improve manual page. * proclint (Main): Remove 'warn' debugging code. Add Scan() prototype. Add $ERROR to return status code. 2008-11-08 Jari Aalto * proclint: Add proper Copyright, License. Modernize Perl code by changing local to my. Move code and functions to the beginning so that functions are defined before used. Add Main(). Add function protype definitions. * proclint.1.pod: (BUGS): Add. (AUTHORS): Update Copyright. (OPTIONS): Change -o|--option format to "-o, --option". 2004-12-16 Thu Jari Aalto * Makefile: 1.4 CODEDIR changed to DATADIR. (EXDIR): Changed. (NAME): New. 2004-09-21 Tue Jari Aalto * proclint: 1.1 Changed /usr/local/bin/perl to /usr/bin/perl * list-addr.rc: 1.1 Changed /usr/local/bin/procmail to /usr/bin/procmail procmail-lib-2009.1202/lib-stebbens/Copyright000066400000000000000000000014131130547513300206500ustar00rootroot00000000000000# # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # procmail-lib-2009.1202/lib-stebbens/GNU-LICENSE000066400000000000000000000430701130547513300204160ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. procmail-lib-2009.1202/lib-stebbens/Makefile000066400000000000000000000035061130547513300204220ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . ifneq (,) This makefile requires GNU Make. endif include ../common.mk NAME = lib-stebbens BASEDIR = $(DOCDIR)/$(NAME) EXDIR = $(BASEDIR)/examples BIN = proclint INSTALL_OBJS = $(BIN) INSTALL_PM_OBJS = `ls *.rc | grep -v example` INSTALL_EXAMPLE_OBJS = prefile-example.rc procmailrc-example INSTALL_DOC_OBJS = 0*README* Copyright \ GNU-LICENSE *.html *tutorial* *.info all: man man: $(MAKE) -f pod2man.mk BIN=$(BIN) makeman install-doc: # Rule install-doc - install documentation $(INSTALL_BIN) -d $(BASEDIR) $(INSTALL_DATA) $(INSTALL_DOC_OBJS) $(BASEDIR) install-examples: # Rule install-examples - install examples $(INSTALL_BIN) -d $(EXDIR) $(INSTALL_DATA) -D $(INSTALL_EXAMPLE_OBJS) $(EXDIR) install-procmail: # Rule install-procmail - install procmail files $(INSTALL_BIN) -d $(SHAREDIR) $(INSTALL_DATA) $(INSTALL_PM_OBJS) $(SHAREDIR) install-man: # Rule install-man - install manual page $(INSTALL_DATA) -D $(BIN).1 $(MANDIR1)/$(BIN).1 install-bin: $(INSTALL_BIN) -D $(BIN) $(BINDIR)/$(BIN) install: all install-bin install-man install-procmail \ install-examples install-doc .PHONY: man clean \ install-bin install-man install-procmail install-examples install-doc # End of file procmail-lib-2009.1202/lib-stebbens/ackmail.rc000066400000000000000000000222761130547513300207160ustar00rootroot00000000000000# ackmail.rc -- procmail rc to acknowledge mail (with either a # vacation message, or an acknowledgement) # # $Id: ackmail.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Usage: # # After setting the variables below appropriately, add the following # to your .procmailrc: # # INCLUDERC=ackmail.rc # # Features: # # If the file $VACAMSG exists, it is assumed that the user is in # "vacation mode", and mail will be acknowledged with the contents of # the $VACAMSG file, with the subject line appended with "[on # vacation]". # # If $VACAMSG doesn't exist, and $ACKMSG does, mail will be # acknowledged with the contents of $ACKMSG with the subject line # appended with "[acknowledgment]". # # If neither the file $ACKMSG nor $VACAMSG exists, this recipe does # nothing. # # Mail from any daemon or the usual set of mailing lists will not be # acknowledged (uses ^FROM_DAEMON). # # Mail from any of a set of configured users ($NOACKS) will not be # acknowledged (be default, this includes the user). # # Mail from any user will only be acknowledged once per day. # # Regardless of whether or not "ackmail.rc" acknowledges the mail, any # recipes following the INCLUDERC will continue to filter the incoming # mail (that is, it is not considered to be delivered). # # Before including the "ackmail.rc" file, be sure to setup the following # variables: # # MY_ADDR - preferred email address for the user # # MY_NAMES - regex matcing personal names & alternatives; # ultimately, only mail addressed to $MY_NAMES # will be acknowledged; defaults to the # contents of $SIGNATURE or $HOME/.signature, in # that order. # # NOACKS - regex matching people from whom to NOT # acknowledge mail; defaults to $MY_ADDR # # NOACKFILE - path to a file containing regexps of addresses to not # acknowledge # # ACKS - file containing the acknowledgment cache; # defaults to $MAILDIR/.acks.cache # # ACKMSG - file containing the message to reply with; # defaults to ackmsg # # VACAMSG - file containing the message to reply with; # defaults to vacation.msg # # FROMSIG - From: header to use in the auto-ack; defaults # to "Mailer-Daemon of $USER" # # MUA - define as one of the keywords below to tell the # recipe on how to calculate the unread mail: # MUA=default - your unread mail sits in $DEFAULT (you don't filter # mail into folders) # MUA=mh - your mail is filtered into the MH +inbox; tries to # use any Unseen-Sequence, or calculates it from the # output of "folders +inbox". # MUA=XXXXX - causes a recipe named "unread-XXXXX.rc" to be # invoked (if it exists) to calculate the number # of unread messages and returned in $UNREAD. # # # And be sure PATH includes the directory containing "formail". # If the mail is directly to me, and not an auto-reply itself # then do the auto-ack MY_NAMES=${MY_NAMES:-${SIGNATURE:-`cat $HOME/.signature 2>/dev/null`}} ACKS=${ACKS:-ackmail.cache} ACKMSG=${ACKMSG:-ackmsg} VACAMSG=${VACAMSG:-vacation.msg} FROMSIG=${FROMSIG:-"Mailer-Daemon of $USER"} NOACKS=${NOACKS:-$MY_ADDR} NOACKFILE=${NOACKFILE:-''} # Handy regexp patterns (taken from "headers.rc") PRE_ADDR_SPAN='(.*[^-(.%@a-zA-Z0-9])?' POST_ADDR_SPAN='(([^),.!:a-zA-Z0-9].*)?(,|$[^>]))' FROMHDR="(^(((Resent-)?(From|Sender)|X-Envelope-From):|>?From )$PRE_ADDR_SPAN)" # Begin the tests # 1. Is it addressed to me (using any of my names)? # 2. Is there an acknowledgement file or vacation message file? # 3. Is the mail NOT from any kind of daemon # 4. Is the mail NOT from a mailing list manager which procmail doesn't know # 5. Does the subject NOT have any text indicating some kind of automatic # reply mechanism has already taken place? # 6. Is this NOT a message we generated (a bounce, maybe)? # 7. Is the message NOT from anyone on our "noack" list? # If you need to debug your configuration of ackmail.rc, just "touch # ackmail.log" and the recipe below will log the ackmail.rc activity to # ackmail.log. When you are satisfied with your configuration, simply # remove ackmail.log and logging will stop. :0 * ? test -f ackmail.rc.log { OLDACKLOGFILE=$LOGFILE LOGFILE=ackmail.rc.log LOGABSTRACT=all VERBOSE=on } # Get the best return address without names & comments. # This will be the same address we respond to. SENDER=`formail -rtzx To:` # Define a list of well-known list mailer addresses LIST_MAILERS='((Mail(er)?-?)?daemon|root|LISTSERV|ListProc|\ [a-zA-Z0-9-]+-(list|request|owner)|(owner-)?list-[a-zA-Z0-9-]+|\ Majordomo|Mailagent|Postmaster|mmdf|news|n?uucp)' # This is the major condition by which we decide to respond # or not. :0ch * $ ^TO($USER|$MY_ADDR|$MY_NAMES) * ? test -f $ACKMSG -o -f $VACAMSG * !^FROM_DAEMON * $! SENDER ?? $LIST_MAILERS * $! $FROMHDR(Majordomo|Listserv) * !^Subject: .*(\[(ack(nowledge?ment)?|on vacation)\]|\ auto(matic)[- ]reply|\ away from mail|\ out of town|\ can ?not (reply|answer)|\ (on |via )vacation( program)?) * $!^X-Loop: *$MY_ADDR * $!$FROMHDR($NOACKS)$POST_ADDR_SPAN { # Okay -- we're doing to do the auto-ack or vacation mail # # We're forking for the auto-ack, shut up comsat, and assume that, # in this process, the mail is delivered DELIVERED=yes COMSAT=off # Don't output logfile info; the user can query $ACKS to see which # users have been acknowledged. This only affects the child # process. LOGABSTRACT=no # Check for a NOACKFILE; if it exists, and if the sender matches one # of the regexps within the NOACKFILE, then do not ack this mail :0h * ? test -n "$NOACKFILE" -a -f "$NOACKFILE" * ? echo "$SENDER" | egrep -s -f "$NOACKFILE" { HOST=_do_not_ack_this_user } # Check the mail to see if we have replied recently, and if so, if # we should reply again DATE=`date +'%D'` # Get the subject :0 ch SUBJ=| formail -zX'Subject:' | sed -e 's/["~]//g' -e 's/^ *[Rr]e: *//g' SUBJ="${SUBJ:-'(no subject)'}" # Get which file: "vacation.msg" has precedence over "ackmsg" :0 * ? test -f $VACAMSG { ACKFILE=$VACAMSG ACKM='on vacation' } :0 E { ACKFILE=$ACKMSG ACKM='acknowledgment' } # Check the cache for a recent ack (a successful grep "delivers" the # mail) LOCKFILE=$ACKS.lock :0 Wh | fgrep -i -s "$SENDER $DATE" $ACKS # Not in the $ACKS file; add it JUNK=`(fgrep -i -v "$SENDER" $ACKS ; echo "$SENDER $DATE" ) >$ACKS.new ; rm -f $ACKS ; mv $ACKS.new $ACKS ` # Release the lock LOCKFILE # Replace the headers with a reply # (Note: do not use -k here; "h" recipes include the blank # line in the headers, and formail -r generates a blank line # also. If you use '-k', then the original blank line will # be kept, and the additional will be added, resulting # in two blank lines). :0 fhw | formail -rtI"From: $FROMSIG" \ -I"Reply-To: $MY_ADDR" \ -I"Precedence: junk" \ -I"Subject: Re: $SUBJ [$ACKM]" \ -I"X-Loop: $MY_ADDR" \ -I"References:" # If formail failed, it is because it couldn't be found # avoid acks in this case :0 e { LOG="****Error: Formail failed in ackmail.rc at `date` " HOST=_stop_processing_now } # Replace the body with the ack message :0 fbw | cat $ACKFILE # If the cat $ACKFILE failed, it is probably because ackfile can't # be read; in this case, create a reasonable reply :0 efb | echo "Your mail concerning '$SUBJECT' was received." ; \ echo "I'll reply to it as soon as I can." # Now maybe do some substitutions, depending upon whether or not the # particular strings exist. :0 fBb * $SUBJECT | sed -e "s~\$SUBJECT~$SUBJ~g" :0 fBb * $SENDER | sed -e "s~\$SENDER~$SENDER~g" # If the string $UNREAD is in the message, then figure out # how many unread messages and substitute it :0 B * $UNREAD { UNREAD=no # by default # Define the MUA if it isn't defined already :0 * MUA ?? !.+ * ? test -f guess-mua.rc { INCLUDERC=guess-mua.rc } # For any MUA keyword, there should be a corresponding # unread-$MUA.rc file. :0 * MUA ?? .+ * ? test -f unread-$MUA.rc { INCLUDERC=unread-$MUA.rc } # Finally, substitute UNREAD into the current body :0 fb | sed -e "s~\$UNREAD~$UNREAD~g" } # Finally, deliver it :0 w ! -oi -t HOST=end_of_processing # just in case sendmail failed } # Undo any debug logging :0 * LOGFILE ?? ackmail\.rc\.log { VERBOSE=no LOGABSTRACT=yes LOGFILE=$OLDACKLOGFILE OLDACKLOGFILE } procmail-lib-2009.1202/lib-stebbens/comm-reply-file.rc000066400000000000000000000035061130547513300223110ustar00rootroot00000000000000# comm-reply-file.rc -*- text -*- # # procmail rc file to filter a reply message body with a given file, # or report an error. # # $Id: comm-reply-file.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Usage: # # REPLYFILE=file-to-be-sent # REPLYERR="error message if file doesn't exist" # :0 * ! REPLYFILE ?? . { LOG="comm-send-file.rc: REPLYFILE not defined! " } # REPLYFILE is defined :0 E { # On the assumption that the message body has been prepared, # filter it and append the requested file. :0 fbw * ? test -f $REPLYFILE | cat - $REPLYFILE # The file wasn't available, generate an error message :0 E { # Provide for a default error message if $REPLYERR isn't set :0 * ! REPLYERR ?? . { # get the basename of the file (don't show any path) :0 * ! REPLYFILE ?? .*/\/[^/]+$ * ! REPLYFILE ?? \/^.*$ { REPLYERR="Sorry, the file you requested is not currently available." } :0 E { REPLYERR="Sorry, the file '$MATCH' is not currently available." } } :0 fbw | cat - ; echo "$REPLYERR" } } procmail-lib-2009.1202/lib-stebbens/commands.help000066400000000000000000000017351130547513300214370ustar00rootroot00000000000000Currently, my mail filter (a procmail recipe file called "commands.rc"), understands the following commands: send help Sends this file of helpful text. send info Sends a file of complete information on all the filters in the procmail library. send procmailrc Sends an annotated, example procmailrc file. send procmail library Sends a library of useful procmail recipes, including an annotated, example personal procmailrc file, as a "shar" archive. send emacs setup Sends a collection of setup code for many Emacs packages and modes, as a "shar" archive. send pgp key Sends my PGP public key. enable autoacks Causes future mail from the sender to be auto-acknowledged. disable autoacks Causes future mail from the sender to not be auto-acknowledged. These commands must occur on the "Subject:" header, and not in the body of the mail message. The word "get" may be used instead of "send". procmail-lib-2009.1202/lib-stebbens/commands.info000066400000000000000000000276451130547513300214520ustar00rootroot00000000000000This file provides detailed information on the commands supported by my mail filter (a procmail recipe file called "commands.rc"). This is $Revision: 1.1 $. In order to be recognized, the following command phrases must occur on the Subject: header line, and not in the body of the mail message. The word "get" may be used instead of "send", and the noun phrases with spaces may alternatively be hyphenated (ie: "send emacs setup" or "send emacs-setup"). send help send info send procmailrc send procmail info send procmail library send emacs setup send pgp key disable autoacks enable autoacks ------------------------------------------------------------------ send help ========= The file $HELPFILE ("commands.help" by default) is sent as a reply. send info ========= The file $INFOFILE ("commands.info" by default) is sent as a reply. send procmailrc =============== Returns an annotated, example procmailrc file which must be only slightly modified to achieve a working personal mail filter. A good example of how to write a variety of procmail filters. send procmail info ================== Returns information about procmail and how to obtain it; currently, this is maintained in the "procmail.info" file. send procmail library ===================== A collection of procmail recipe files developed by Alan K. Stebbens which may make writing procmail recipes easier and more useful. This library is freely available in the same spirit by which procmail and the GNU utilities are being made available. The following are the files currently comprising the library: ackmail.rc ---------- Ackmail.rc is a procmail recipe file which provides the functionality of intelligent auto-acknowledgement of incoming mail. It uses a file, named "ackmsg" by default, as the prototype message for replies. The file can contain several variables which are substituted with values determined at the time of the reply. The variables currently supported are: $SUBJECT, $SENDER, and $UNREAD (the value of $UNREAD is under the control of the owner; see the recipe files "unread-*.rc"). Ackmail.rc tries very hard not to respond to daemons, mailers, mailing lists, yourself, or a configurable list of addresses and names to which you do not wish automatic replies. When used in combination with another recipe file, "commands.rc", your recipients can decide for themselves to receive these auto-acknowledgements or not. Ackmail.rc will only respond with an auto-acknowledge mail once per day per address. Ackmail.rc can detect when you are on vacation (when you create a "vacation.msg" file) and will generate replies with this message instead. A "cache" of acknowledgements is maintained in a file, named "ackmail.cache" by default. If the "ackmsg" or "vacation.msg" files contain the string $UNREAD, then an attempt to determine the number of unread messages will be made. This computation will depend upon the value of the variable MUA, which tells the recipe which Mail User Agent (MUA), the user is using. The value of MUA is then used to derive a recipe filename of "unread-$MUA.rc", which is then included for procmail processing so that it can define UNREAD correctly for the defined MUA. Currently, there are two unread MUA methods: MUA File What === ==== === default unread-default.rc Counts messages in $DEFAULT mh unread-mh.rc Counts messages in +inbox New MUA values can be added and implemented as additional unread-$MUA.rc files commands.rc ----------- Commands.rc is a recipe file for procmail which implements a "Subject: header command parser and implementor. Commands.rc currently recognizes a given set of commands, but can be easily extended or modified. dupcheck.rc ----------- This procmail recipe file checks for and removes duplicate mail, as determined by the "Message-Id:" header. If you are subscribed to many mailing lists, this is a very useful recipe to use -- it will detect and remove duplicate messages arriving via different mailing lists but from the same originator. get-from.rc ----------- A little recipe used to extract the "best" address for the sender of the incoming mail. The result of this recipe is left in the variable FROM, with the personal name portion extracted into the variable FRIENDLY. The result of this recipe differs from the result of `formail -rt` in that the former includes the complete address, with any comments or quoted strings, while the latter is only the email address. For example, with a message of: To: you@yourhost.yourdomain From: "Ponce De Leon" the results would be: get-from.rc: FROM="Ponce De Leon" http://reality.sgi.com/aks procmail-lib-2009.1202/lib-stebbens/commands.rc000066400000000000000000000225471130547513300211170ustar00rootroot00000000000000# commands.rc -*- text -*- # # procmailrc file to check for commands in the subject line # # $Id: commands.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Usage: # # HELPFILE=commands.help [optional] # INFOFILE=commands.info [optional] # PROCMAILINFO=procmail.info [optional] # COMMANDLOG=commands.log [optional] # NOACKFILE=noacks [optional] # # INCLUDERC=commands.rc # # Notes: # # * This recipe consumes the input if it successfully matches. # Processing does not continue unless the subject is not a # command. # # * HELPFILE should contain general help, and be relatively short. # # * INFOFILE should contain more detailed information on the # supported commands. # # * All default filenames are relative to $MAILDIR. # # * NOACKFILE is used by "ackmail.rc", with the same default. # # * Processed commands are logged in $COMMANDLOG. The format of the # logged information is: # # date : address : command # # * To debug your configuration, touch $MAILDIR/commands.rc.log and # watch its contents for logged information. Remove this file when # you no longer wish to have a detailed debug log. # # * This recipe file uses "comm-reply-file.rc" (which is part of the # procmail library). # # Current commands are: # # (send | get) help # (send | get) info(rmation)? # (send | get) pgp key # (send | get) procmail info # (send | get) procmail lib(rary) # (send | get) smartlist lib(rary) # (send | get) emacs setup # (send | get) procmailrc # (en|dis)able (auto *)ack(nowledgments) # # Author: Alan K. Stebbens # # Check for any of the commands :0 * ? test -f commands.rc.log { OLDCMDLOGFILE=$LOGFILE LOGFILE=commands.rc.log LOGABSTRACT=all VERBOSE=yes } :0 * ^Subject: *['"]?\/\ ((send|get) +(help|info(rmation)?|\ procmailrc|\ (procmail|smartlist) *(- *)?info(rmation)?|\ (procmail|smartlist) *(- *)?lib(rary)?|\ emacs(-| *)setup|\ pgp *key)|\ (en|dis)able +(auto *)?ack(nowledge?ment)?s?) * ! ^FROM_DAEMON * $ ! ^X-Loop: $MY_ADDR { # We're forking at this point -- so shutup procmail COMSAT=off # Tell sendmail we've got control DELIVERED=yes # Save a copy just in case (in log mode) :0 c: * LOGFILE ?? commands\.rc\.log commands.requests # Get the trigger subject SUBJ=$MATCH # Get the best reply address (used for logging) :0 * ! ^Reply-to: *\/[^ ].* * ! ^From: *\/[^ ].* * ! ^Sender: *\/[^ ].* * ! ^From *\/[^ ]+ { FROM=nobody } :0E { FROM=$MATCH } # Just in case these aren't defined FROMSIG="${FROMSIG:-\"The Mailer-Daemon of $USER\" <$USER>}" MY_ADDR="${MY_ADDR:-<$USER>}" # The log file COMMANDLOG=${COMMANDLOG:-commands.log} # The basic processing works like this: # Now that we've captured the important information from the # incoming mail, we replace the headers portion with an # autoreply header. # # Then, as part of recognizing the SUBJECT command, we # replace the body portion with the response # # After testing for all the possible subject commands, # we then submit the mail unless it is empty. # Generate a reply header, and replace the headers :0 fhw | formail -rI"From: $FROMSIG" \ -I"Reply-To: $MY_ADDR" \ -I"Subject: Re: $SUBJ" \ -I"Precedence: junk" \ -I"X-Loop: $MY_ADDR" # Now, start a new message body :0 fbw | echo "This message was sent automatically in reponse to your recent" ; \ echo "mail with the subject: \"$SUBJ\"." ; \ echo "" # Now process each command ##### send procmailrc ##### send procmail lib :0 * SUBJ ?? procmail(rc| *(- *)?lib(rary)?) { # **** This is very site specific **** PROCMAILDIR=$HOME/src/mail/procmail/procmail-lib :0 * SUBJ ?? procmailrc { REPLYFILE=$PROCMAILDIR/procmailrc-example INCLUDERC=comm-reply-file.rc } :0 E { REPLYFILE=$PROCMAILDIR/procmail-lib.shar INCLUDERC=comm-reply-file.rc } } #### send procmail info :0 E * SUBJ ?? (procmail|smartlist) *(- *)?info { PROCMAILINFO=${PROCMAILINFO:-procmail.info} REPLYFILE=$PROCMAILINFO INCLUDERC=comm-reply-file.rc } ##### send smartlist library :0 E * SUBJ ?? smartlist *(- *)?lib(rary)? { # **** This is very site specific **** REPLYFILE=$HOME/src/mail/procmail/smartlist-lib/smartlist-lib.shar INCLUDERC=comm-reply-file.rc } ##### send information :0 E * SUBJ ?? info(rmation)? { # The information file with a suitable default INFOFILE=${INFOFILE:-commands.info} REPLYFILE=$INFOFILE INCLUDERC=comm-reply-file.rc } ##### send emacs setup :0 E * SUBJ ?? emacs(-| *)setup { # Send emacs setup (shar archive is several files) EMACSSETUP="$HOME/emacs/site-setup.shar*" count=`echo $EMACSSETUP | wc -w` # For this command, we are responding with several mails # so we cannot use procmail to "hold" them all at the # same time. So, we generate several sendmail invocations # and leave the current mail buffer empty by filtering it # with /dev/null :0 fw:tmp.reply.lock * $ ? test -f $EMACSSETUP | cat - > tmp.reply ; \ i=1 ; \ for file in $EMACSSETUP ; do \ cat tmp.reply $file \ | formail -I "Subject: Re: $SUBJ [part $i/$count]" \ | $SENDMAIL -oi -t ; \ i=`expr $i + 1` ; \ done ; \ cat /dev/null :0 Efbw | cat - ; \ echo "Sorry, the emacs setup archive file is not currently available." } ##### send pgp key :0 E * SUBJ ?? pgp *key { # Add some more headers :0 fhw | formail -I"Mime-Version: 1.0" \ -I"Content-Type: application/pgp; format=keys-only" \ -I"Content-Description: PGP key of $MY_ADDR" \ -I"Content-Transfer-Encoding: 7bit" # get the text for the body :0 fbw | cat - ; \ sh -c "pgp -kxaf $MY_ADDR 2>/dev/null" # If PGP failed somehow, leave a nice return message :0 efbw | cat - ; \ echo "Sorry, my PGP key is not available at the moment." } ##### (disable|enable) ack(nowledgements) :0 E * SUBJ ?? (dis|en)able { # Be sure NOACKFILE is defined NOACKFILE=${NOACKFILE:-noacks} # remove this address from NOACKS WHO=`formail -zxTo:` # The content of NOACKS are regexps, so we must carefully convert # the address into a regexp which *matches* a regexp. REWHO=`echo "$WHO" | sed -e 's/[.]/\\\\\\\\\\\\./g'` # See if the user is currently in the list of NO-ACKs LOCKFILE=$NOACKFILE.lock :0 * ? grep -s "^$REWHO" $NOACKFILE { # It is -- If "enable", remove it. :0 * SUBJ ?? enable { JUNK=`grep -v "^$REWHO" $NOACKFILE > $NOACKFILE.new ; mv $NOACKFILE.new $NOACKFILE` } :0 Afbw | cat - ; \ echo "Future mail from $WHO will be auto-acknowledged." ; \ echo "" ; \ echo "If you wish to disable auto-acknowledgements, please" ; \ echo "send me an email message with the subject: \"disable autoacks\"." :0 Efbw | cat - ; \ echo "Mail from $WHO is already not being auto-acknowledged." } # Else, $WHO is not in the $NOACKs :0 E { # If the command was disable, add it to the file # We must convert the address to a regexp as part of adding it # to the file. :0 * SUBJ ?? disable { JUNK=`echo "$WHO" | sed -e 's/[.]/\\\\./g' >> $NOACKFILE` } :0 Afbw | cat - ; \ echo "Future mail from $WHO will not be acknowledged." ; \ echo "" ; \ echo "If you wish to enable auto-acknowledgements, please" ; \ echo "send me an email message with the subject: \"enable autoacks\"." :0 Efbw | cat - ; \ echo "Mail from $WHO is already being acknowledged." } # Remove the global lockfile LOCKFILE } ##### send help (explicitly or because of some other request) :0 E { # This is a combined recipe -- both the "send help" recipe # and the "unknown" command recipes result in the sending # of the helpfile. # If an unknown subject, append an error message :0 fbw * ! SUBJ ?? help | cat - ; \ echo 'Sorry, I don't know how to do this request.' ; \ echo '' # The help file with a suitable default HELPFILE=${HELPFILE:-commands.help} REPLYFILE=$HELPFILE INCLUDERC=comm-reply-file.rc } # Okay, procmail should be "holding" some headers and some body # text. Send it (if it is not an empty mail) :0 cw * > 1 ! -oi -t # Don't log anything else LOGABSTRACT=off # Log this request (and mark the mail as "delivered") :0 hw: $COMMANDLOG$LOCKEXT | echo "`date` : $FROM : $SUBJ" >> $COMMANDLOG HOST=end_of_processing } :0 * LOGFILE ?? commands\.rc\.log { LOGFILE=$OLDCMDLOGFILE LOGABSTRACT=yes VERBOSE=no } # End of commands.rc procmail-lib-2009.1202/lib-stebbens/correct-addr.rc000066400000000000000000000301601130547513300216550ustar00rootroot00000000000000# correct-addr.rc # # $Id: correct-addr.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1996 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Procmail recipe file to help forward mail from an OLD address to a # NEW address, and do some mailing list mail management. # # This recipe file is intended to make it easy for users to forward # their mail from their old address to a new address, and, at the same # time, educate their correspondants about it by CC'ing them with the # mail. # # Only mail directly addressing the user at the old address will cause a # "correction notice" to be sent. # # Mail *not* directly addressing the old address (eg: from a mailing list) # is treated separately, according to the MAILLIST variable; it can be one # or more of these values: # # drop This is the default behaviour, and is only defined to # explicitly acknowledge this. In other words, "drop" # and "forward" are mutually exclusive, and omitting # "forward" implies "drop", but not vice versa. # # forward forward all mailing list mail to $NEWADDR, inserting # "Resent-From:" and "Resent-To:" headers. Of course, # $NEWADDR must also be defined. # # report report the headers of all mailing list mail to # $POSTMASTER, so that the person handling this role can # send the appropriate unsubscription requests. # # *** NOT IMPLEMENTED *** # # bounce return all mailing list mail with "User has moved!" to # the "request" or "owner" address; great pains are taken # to not respond to a general distribution list address. # If the proper list address cannot be determined, then # the ultimate fallback return address is "postmaster" at # the originating domain. # # remove If the originating mailing list software type can be # determined, automatically generate an "unsubscribe" # address on the $OLDADDR. Currently, the recipe # understands Majordomo, SmartList, and LISTSERV commands. # If the mailing list software cannot be determined, then # falls back to "report" action. # # change If the originating mailing list software type can be # determined, automatically generate mails to the list # request address to unsubscribe the old address and to # subscribe the new address, if given. If the mailing # list software cannot be determined, then falls back # to "report" action. # # Multiple keywords can be given to accomplish several things on the # mailing list mail. # # Without the "forward" keyword, mailing list mail will not ever be # forwarded, even if NEWADDR is defined. Therefore, to have mailing # list mail be both forwarded and bounced, use "forward,bounce". To # have mailing list mail be forwarded, and have the subscription # changed where possible, use "forward,change". # # # Usage: # # These variables are *optional*, with the defaults as shown: # # OLDLOGIN=$LOGNAME # The primary old login; this will be used in the # correction notice sent to correspondants. # # OLDUSER=$FRIENDLY (see get-from.rc} # The user's old real name, included in the correction # notice. If not set by the user, FRIENDLY is used, which # is determined by the procmail recipe file "get-from.rc". # # OLDLOGINS='$\LOGNAME' # A regexp matching the old login name(s). If the user # received mail at more than one login name, this should # match them all. For most users, the default is fine. # # NOTLOGINS= # A regexp matching logins mail to which should NOT be # forwarded or corrected. This can be used to form # a filter to correct mail addressed ambiguously. See # the man page for examples. # # NOTSUBJECTS= # Any mail containing subjects matching this regexp does # not get corrected or filtered. # # DOMAIN= # The domain in which this user resides; without this # definition, this script can only match on the user # name. # # HOSTS='[^. ]+' # A regexp matching the hosts at which the OLDLOGIN # receives mail. This is used in conjunction with $DOMAIN # so don't place the domain in this regexp. # # NEWADDR= # The address to which mail should be forwarded. There is # no default, resulting in no forwarding; in this case, only # reply with "no such user" notices. # # NEWUSER=$OLDUSER # The new user name, defaulting to the old user name. This # is used for correction notices. # # POSTMASTER=Postmaster # This is used as the From: address for both the correction # "no such user" notices. # # MAILLIST=[keyword,...] # One or more keywords: forward, report, bounce, remove, # or change, separated by spaces or commas. See the # description above for details. # # INCLUDERC=correct-addr.rc # # Examples: # # a. John Carter has moved from his current location to "carter@mars.com", # and he wishes to have his mailing mail forwarded. # # NEWADDR = carter@mars.com # MAILLIST = forward # INCLUDERC = correct-addr.rc # # b. Clark Kent has moved back to his hometown, and does not want his # mail forwarded at all, especially his mailing lists. # # NEWADDR # guarantee no NEWADDR # MAILLIST = bounce,remove # INCLUDERC = correct-addr.rc # # c. Dennis Mitchell has been receiving mail by many aliases, and, having # gone off to college, wishes to have all of his mail sent to his # new email address. # # NEWADDR = menace@engineering.ucsb.edu # OLDLOGINS = "(Dennis|D.Mitchell|Dennis.Mitchell|Menace)" # MAILLIST = forward # INCLUDERC = correct-addr.rc # # d. Lois Lane has gotten married, and wishes to have her mail forwarded # to her new address, with her mailing list subscriptions changed, and # she wishes to have any correction notices mention her new name. # # NEWADDR = lois@smallville.ia.us # OLDLOGINS = "(Lois|Lane|L.Lane|Lois[._]Lane)" # NEWUSER = "Lois Kent" # MAILLIST = forward,change # INCLUDERC = correct-addr.rc # # e. Tom, a clever system manager, has installed an automatic alias for # users when their logins expires (and they no longer have a home # directory in which to place a ~/.procmailrc file), which invokes # a small shell script, called "correct-mail": # # olduser1: "|correct-mail olduser1" # olduser2: "|correct-mail olduser2" # # The shell script looks like this: # # #!/bin/sh # PATH=$PATH:/usr/local/bin ; export PATH # procmail -m LOGNAME=$1 \ # MAILLIST=bounce,report \ # DEFAULT=/dev/null \ # MAILDIR=/tmp \ # LOGFILE=/usr/adm/correct-mail.log \ # LOGABSTRACT=yes \ # /etc/procmailrcs/correct-addr.rc # # First let's do some optional logging # If the file "correct-addr.rc.log" exists, we log extensively # to it. :0 * ? test -f correct-addr.rc.log { CA_LOGFILE=$LOGFILE CA_LOGABSTRACT=$LOGABSTRACT CA_VERBOSE=$VERBOSE LOGFILE=correct-addr.rc.log LOGABSTRACT=all VERBOSE=yes } # A temporary file used to hold mail being reported to the postmaster REPORTMAIL=tmp.ca-mail.$LOGNAME # Make sure variables have default settings OLDLOGIN=${OLDLOGIN:-$LOGNAME} HOSTS=${HOSTS:-'[^. >(),;]+'} POSTMASTER="${POSTMASTER:-\"Postmaster \"}" MAILLIST=${MAILLIST:-forward} DOMAIN="`echo \"$DOMAIN\" | sed -e 's/\\./\\\\./'`" # HOSTPART matches the entire hostname part of an address HOSTPART="(@($HOSTS(\.$DOMAIN)?|$DOMAIN))?([,();> ]|$)" # Define a regexp matching the old addresses :0 * OLDLOGINS ?? . { OLDADDRS="($OLDLOGIN|$OLDLOGINS)$HOSTPART" } # There isn't a set of other logins :0 E { OLDADDRS="$OLDLOGIN$HOSTPART" } # Okay -- now begin the basic tests. # Be sure we don't loop :0 * $ ^X-Loop: $LOGNAME@$HOST { } # Make sure that the negative filters do not apply # If there is a NOTLOGINS defined, and it matches the addressee # then don't correct/forward :0 E * NOTLOGINS ?? . * $ ! ^TO$NOTLOGINS$HOSTPART { } # If there is a NOTSUBJECTS defined, and it matches the subject # then don't correct or forward :0 E * NOTSUBJECTS ?? . * $ ! ^Subject: *$NOTSUBJECTS { } # Else, if the mail matches the OLDLOGINS, then correct and forward :0 E * $ ^TO$OLDADDRS { # Begin the correction and forwarding part OLDADDR=$MATCH :0 * OLDADDR ?? [,(); >]$ { OLDADDR="`echo \"$OLDADDR\" | sed -e 's/[,(); >]$//'`" } # First, save a copy LOCKFILE=$REPORTMAIL.lock :0 c $REPORTMAIL # Set OLDUSER to FRIENDLY if not already set :0 * ! OLDUSER ?? . { INCLUDERC=get-from.rc OLDUSER=$FRIENDLY } # Generate a new header :0 fhw | formail -rt -I"From: $POSTMASTER" \ -I"Subject: Your mail to $OLDADDR" \ -I"X-Loop: $LOGNAME@$HOST" # Is there a new address for forwarding? :0 a * NEWADDR ?? . { # Be sure NEWUSER is set NEWUSER=${NEWUSER:-$OLDUSER} # Make sure the new user gets a copy of the correction notice :0 afhw | formail -A"Cc: $NEWADDR ($NEWUSER)" :0 afbi | echo "Your mail to $OLDUSER at:" ; \ echo "" ; \ echo " $OLDADDR" ; \ echo "" ; \ echo "is no longer correct; ${NEWUSER} now receives mail at:" ; \ echo "" ; \ echo " $NEWADDR" ; \ echo "" ; \ echo "This message, with your original mail, is also being forwarded" ; \ echo "to the new address." ; \ echo "" ; \ echo "Please remember to update the address you have for $NEWUSER in" ; \ echo "any mail address database you may use." } # If NEWADDR is not set, just tell the sender that this address # is no longer valid :0 Efbi | echo "Your mail to $OLDUSER at:" ; \ echo "" ; \ echo " $OLDADDR" ; \ echo "" ; \ echo "is being returned because this user is no longer at this address" ; \ echo "and no forwarding address has been provided." # Append the signature and the original mail, and send it :0 fb | cat ; \ echo "" ; \ echo "Regards, the $POSTMASTER" ; \ echo "" ; \ echo "Your original mail follows:" ; \ echo "------------------------------------------------------------" ; \ formail <$REPORTMAIL JUNK=`rm -f $REPORTMAIL` LOCKFILE # Now ship off the mail to sendmail :0 ! -oi -t } # If the mail wasn't directly to $OLDLOGIN, it is mail from a # mailing list, so don't send a correction notice, #### Mailing list mail #### :0 E * MAILLIST ?? (forward|report|bounce|remove|change) * $!^X-Loop: $LOGNAME@$HOST { # Both change and remove require some mailing list heuristics # Use common code for this :0 * MAILLIST ?? (change|remove) { # get common header definitions INCLUDERC=headers.rc # Try to determine the mailer address INCLUDERC=list-addr.rc # ***** NOT YET IMPLEMENTED ***** } :0c * MAILLIST ?? report { LOCKFILE=tmp.mail.lock :0 chw # save a copy of the headers | sed -en '1,/^[ ]*$/s/^/ /p' >tmp.mail :0 fhw # generate report header to Postmaster | formail -I"From: Mailer-Daemon " \ -I"To: $POSTMASTER" \ -I"Subject: Mailing list mail to old address: $OLDLOGIN" \ -I"X-Loop: $LOGNAME@$HOST" :0 afbwi # make a report | echo "Mail is still being sent to $OLDLOGIN indirectly, possibly" ; \ echo "through a mailing list. The headers of the mail are supplied " ; \ echo "below." ; \ echo "" ; \ echo "------------------- Original mail headers ------------------" ; \ cat tmp.mail LOCKFILE :0 aw # file the report ! -oi -t } # forward it if NEWADDR defined, and MAILLIST includes "forward" :0 * MAILLIST ?? forward * NEWADDR ?? . { # Add new headers indicating the forwarding :0 fhw | formail -A"X-Loop: $LOGNAME@$HOST" \ -i"Resent-From: $OLDADDR" \ -i"Resent-To: $NEWADDR" :0 aw ! $NEWADDR } # Otherwise, assume a drop :0 /dev/null } procmail-lib-2009.1202/lib-stebbens/date.rc000066400000000000000000000303551130547513300202270ustar00rootroot00000000000000# date.rc # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id: date.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Procmail recipe to extract and create some variables related to # the date in the message. If the message has no date reference, # either the variables are returned undefined, or set using the # current date depending upon DATE_DEFAULT_NOW. # Currently, this recipe file parses dates with these formats: # # 1. Tue(sday), 31 Dec 96 # 2. Tue, 31 Dec 1996 # 3. 12/31/96 # 4. Tuesday, December 31, 1996 # # If DATE is not defined, then obtain the date from the current input message # from the following headers, in decreasing priority: Resent-Date:, Date:, # and "From ". # # If DATE is defined, it is simply used as the input. # # Thus to parse the date from the current mail message do this: # # DATE INCLUDERC=date.rc # # To make this even easier, use "get-date.rc": # # INCLUDERC=get-date.rc # # To parse a given date string, simply set DATE: # # DATE=12/31/96 INCLUDERC=date.rc # # # These variables are set from the parsing of DATE: # # DATE # the original, complete date string from which # # all other variables were derived # DATE_WEEKDAY # the weekday name, if present # DATE_WDAY # the short weekday name, if present # DATE_DAY # the day of the month (eg: 1) # DATE_DAY2 # the day of the month with two digits: (eg: 01) # DATE_MONTH # the month of the year # DATE_MONTH2 # the month of the year with two digits: (eg: 01) # DATE_MONTHNAME # the long name of the month (eg: December) # DATE_MONTHABBR # the abbreviated name of the month (eg: Dec) # DATE_YEAR # the four-digit year (eg: 2001) # DATE_YEAR2 # the last two digits of the year (eg: 96) # # DATE_MMDDYY # the date as MM/DD/YY (use DATE_SEP1 as separator) # DATE_MMDDYYYY # the date as MM/DD/YYYY # DATE_YYMMDD # the date as YY/MM/DD (use DATE_SEP1 as separator) # DATE_YYYYMMDD # the date as YY/MM/DD (use DATE_SEP1 as separator) # DATE_DDMMMYY # the date as DD MMM YY (use DATE_SEP2 as separator) # DATE_DDMMMYYYY # the date as DD MMM YYYY # # DATE_UNIX # the date as WDAY, DD MMM YYYY (ala `date`) # DATE_LONG # the date as WEEKDAY, MMMMM DD, YYYY # DATE_DEC # the date as DD-MMM-YYYY # DATE_MMMDDYYYY # the date as MMMMM DD, YYYY # DATE_TIME # the date/time in `date` format: Fri Oct 11 12:52:48 PDT 1996 # DATE_CTIME # the date/time in "ctime" format: Fri Sep 13 00:00:00 1986 # # DATE_SEP1 # the character used to separate digits/letters of # # MMDDYY or YYMMDD # DATE_SEP2 # the character used to separate DDMMMYY # # TIME # the orininal string from which the time variables # # were derived. # TIME_HOURS # hours (as given) # TIME_HOURS2 # hours in 2 digits (as given) (eg: 01) # TIME_HOURS12 # hours modulo 12 # TIME_HOURS24 # military hours [00-23] # TIME_MINS # minutes (eg: 34) # TIME_SECS # seconds (eg: 56) # TIME_AMPM # 'am' or 'pm' # TIME_ZONE # The timezone JST, EST, EDT, etc. # # TIME_MILITARY # hhmm (0000-2359) eg: 0630 # TIME_HHMM # hh:mm (eg: 12:03) # TIME_HHMMSS # hh:mm:ss (eg: 12:03:45) # TIME_12 # hh:mm am/pm # TIME_24 # hh:mm (military style) # # These variables are used within date.rc but will not return # meaningful values. # # DAYS_RE MONTHS_RE S Y N NN APM ZONE X D DAYS_RE='(Mon|Tues?|Wed(nes)?|Thu(rs)?|Fri|Sat(ur)?|Sun)(day)?' MONTHS_RE='(Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|June?|\ July?|Aug(ust)?|Oct(ober)?|(Sept?|Nov|Dec)(ember)?)' S='[/-,. ]+' Y='[0-9][0-9][0-9][0-9]' N='[0-9]+' NN='[0-9][0-9]' APM='[ap]m' ZONE='([-+][0-9][0-9][0-9]( GMT)?|[PMCE][SD]T([45678][PMCE]DT)?|JST)' :0 * ! DATE ?? . { :0 * ^Resent-Date: *\/[^ ].* { DATE=$MATCH } :0 E * ^Date: *\/[^ ].* { DATE=$MATCH } :0 E * ^From *[^ ]+ +\/[^ ].* { DATE=$MATCH } } :0 * ! DATE ?? . * DATE_DEFAULT_NOW ?? . { DATE=`date` } # If there is a date to work with, let's begin to parse it :0 * DATE ?? . { # First, look for a weekday, and extract it :0 * $ DATE ?? ()\/$DAYS_RE { DATE_WDAY=$MATCH # See if the day was abbreviated or long :0 * DATE_WDAY ?? day { DATE_WEEKDAY=$DATE_WDAY # get the long day name # And, extract the short version from it :0 * DATE_WEEKDAY ?? ^\/... { DATE_WDAY=$MATCH } } :0 E # okay, it was a short name { :0 * DATE_WDAY ?? Tue { DATE_WEEKDAY=Tuesday } :0 E * DATE_WDAY ?? Wed { DATE_WEEKDAY=Wednesday } :0 E * DATE_WDAY ?? Thu { DATE_WEEKDAY=Thursday } :0 E * DATE_WDAY ?? Sat { DATE_WEEKDAY=Saturday } :0 E { DATE_WEEKDAY=${DATE_WDAY}day } } } # Here's where we parse the date :0 # MM/DD/YYYY? * $ DATE ?? ()\/$N$S$N$S$Y { X=$MATCH :0 * $ X ?? ()\/$N { MM=$MATCH } :0 * $ X ?? $N$S\/$N { DD=$MATCH } :0 # try YYYY first * $ X ?? $S\/$Y { YYYY=$MATCH } :0 E * $ X ?? $N$S$N$S\/$N { YY=$MATCH } } :0 E # YYYY/MM/DD? * $ DATE ?? ()\/$Y$S$N$S$N { X=$MATCH :0 * $ X ?? ()\/$Y { YYYY=$MATCH } :0 * $ X ?? $Y$S\/$N { MM=$MATCH } :0 * $ X ?? $Y$S$N$S\/$N { DD=$MATCH } } :0 E # MM/DD/YY or YY/MM/DD? * $ DATE ?? $N$S$N$S$N { X=$MATCH :0 * $ X ?? ()\/$N { MM=$MATCH } :0 * $ X ?? $N$S\/$N { DD=$MATCH } :0 * $ X ?? $N$S$N$S\/$N { YY=$MATCH } # Use heuristics to determine of MM/DD/YY or YY/MM/DD # If MM > 12, it must be YY :0 E * MM ?? ^([2-9][0-9]|1[3-9]) { X=$YY YY=$MM MM=$DD DD=$X X } # swap formats } :0 E # is it DD MMM YYYY ? * $ DATE ?? ()\/$N$S$MONTHS_RE$S$N { X=$MATCH :0 * $ X ?? ()\/$N { DD=$MATCH } :0 * $ X ?? ()\/$MONTHS_RE { MMM=$MATCH } :0 # first try matching YYYY * $ X ?? ()\/$Y { YYYY=$MATCH } :0 E # ok, use YY, but don't match the first pair * $ X ?? $N.*$S\/$N { YY=$MATCH } } :0 E # YYYY MMM DD? * $ DATE ?? ()\/$Y$S$MONTHS_RE$S$N { X=$MATCH :0 * $ X ?? ()\/$Y { YYYY=$MATCH } :0 * $ X ?? ()\/$MONTHS_RE { MMM=$MATCH } :0 * $ X ?? $Y$S.*$S\/$N { DD=$MATCH } } :0 E # MMM DD, YYYY? * $ DATE ?? ()\/$MONTHS_RE$S$N$S$Y { X=$MATCH :0 * $ X ?? ()\/$MONTHS_RE { MMM=$MATCH } :0 * $ X ?? ()\/$N { DD=$MATCH } :0 * $ X ?? ()\/$Y { YYYY=$MATCH } } # Okay, this might be a Unix date: MMM DD HH:MM:SS ZONE YEAR # So, test the parts individually :0 E # MMM DD ... YYYY? * $ DATE ?? $MONTHS_RE$S$N.*$Y { :0 # MMM DD? * $ DATE ?? ()\/$MONTHS_RE$S$N { X=$MATCH :0 # get the month name * $ X ?? ()\/$MONTHS_RE { MMM=$MATCH } :0 # get the day * $ X ?? ()\/$N { DD=$MATCH } :0 E { DD='??' } } :0 # is there a year? * $ DATE ?? ()\/$Y { YYYY=$MATCH } } # Now match for any time :0 # hh:mm(:ss) (a/pm) (+700 | pdt/pst...) * $ DATE ?? ()\/$N:$NN(:$NN)?($S$APM)?($S$ZONE)? { TIME=$MATCH # get any time string # clear these variables TIME_HOURS TIME_HOURS2 TIME_MINS TIME_SECS TIME_AMPM TIME_HOURS24 :0 # get the hours * $ TIME ?? ()\/$N { TIME_HOURS=$MATCH TIME_HOURS2=$MATCH :0 * TIME_HOURS2 ?? ^.$ { TIME_HOURS2=0$TIME_HOURS } } :0 * $ TIME ?? $N:\/$NN { TIME_MINS=$MATCH } :0 * $ TIME ?? $N:$NN:\/$NN { TIME_SECS=$MATCH } :0 * $ TIME ?? ()\/$APM { TIME_AMPM=$MATCH :0 # if 01..09,10,11 pm? * TIME_AMPM ?? pm * TIME_HOURS ?? (0?[1-9]|1[01]) { TIME_HOURS24=`expr $TIME_HOURS + 12` } :0 E # if 12 am? * TIME_AMPM ?? am * TIME_HOURS ?? 12 { TIME_HOURS24=00 } TIME_HOURS12=$TIME_HOURS } # no AM/PM, create HOURS24, HOURS12 :0 E # given time >= 13? * TIME_HOURS ?? (1[3-9]|2.) { TIME_HOURS24=$TIME_HOURS TIME_HOURS12=`expr $TIME_HOURS - 12` } :0 E # no am/pm, and time < 12 { TIME_HOURS24=$TIME_HOURS TIME_HOURS12=$TIME_HOURS } :0 # now, check for time zone * $ TIME ?? ()\/$ZONE { TIME_ZONE=$MATCH } # Create the remaining derived vars TIME_HHMM="$TIME_HOURS:$TIME_MINS" TIME_HHMMSS=$TIME_HHMM:${TIME_SECS:-00} TIME_MILITARY=$TIME_HOURS24$TIME_MINS } X T # clear the variables we used # We now have three parts: MM or MMM, DD, and YY or YYYY. # If we have MMM, convert to MM (which will later be converted back to MMM) :0 # is MMM defined? * MMM ?? . { :0 # is it the long name? * MMM ?? ^.... { DATE_MONTHNAME=$MMM :0 # extract the abbreviation * MMM ?? ^\/... { DATE_MONTHABBR=$MATCH } MM # clear MM } :0 E # nope, it must be an abbreviation * MMM ?? Jan { MM=01 } :0E * MMM ?? Feb { MM=02 } :0E * MMM ?? Mar { MM=03 } :0E * MMM ?? Apr { MM=04 } :0E * MMM ?? May { MM=05 } :0E * MMM ?? Jun { MM=06 } :0E * MMM ?? Jul { MM=07 } :0E * MMM ?? Aug { MM=08 } :0E * MMM ?? Sep { MM=09 } :0E * MMM ?? Oct { MM=10 } :0E * MMM ?? Nov { MM=11 } :0E * MMM ?? Dec { MM=12 } MMM # clear MMM } # If we have MM, convert to MMM :0 * MM ?? . { :0 # check on leading zero * MM ?? ^0?\/[0-9]$ { DATE_MONTH=$MATCH DATE_MONTH2=0$MATCH } :0 E { DATE_MONTH2=$MM DATE_MONTH=$MM } MM=$DATE_MONTH # Now, convert MM -> DATE_MONTHNAME :0 * MM ?? 10 { DATE_MONTHNAME=October } :0E * MM ?? 11 { DATE_MONTHNAME=November } :0E * MM ?? 12 { DATE_MONTHNAME=December } :0E * MM ?? 1 { DATE_MONTHNAME=January } :0E * MM ?? 2 { DATE_MONTHNAME=February } :0E * MM ?? 3 { DATE_MONTHNAME=March } :0E * MM ?? 4 { DATE_MONTHNAME=April } :0E * MM ?? 5 { DATE_MONTHNAME=May } :0E * MM ?? 6 { DATE_MONTHNAME=June } :0E * MM ?? 7 { DATE_MONTHNAME=July } :0E * MM ?? 8 { DATE_MONTHNAME=August } :0E * MM ?? 9 { DATE_MONTHNAME=September } MM # clear MM } # Set the month abbreviation :0 * DATE_MONTHNAME ?? ^\/... { DATE_MONTHABBR=$MATCH } # Now check on the day :0 * DD ?? ^0?\/[0-9]$ { DATE_DAY=$MATCH DATE_DAY2=0$MATCH } :0 E { DATE_DAY=$DD DATE_DAY2=$DD } DD # clear DD # Now check on the year: if YYYY is not available, use YY YYYY=${YYYY:-$YY} YY # clear YY # If YYYY only has two digits, derive the current year :0 * YYYY ?? ^..$ { YYYY=`date +%Y | sed -e 's/..$/'$YYYY'/'` } DATE_YEAR=$YYYY YYYY # clear YYYY :0 # get the last two digits of the year * DATE_YEAR ?? ^..\/.. { DATE_YEAR2=$MATCH } SEP1=${DATE_SEP1:-'/'} SEP2=${DATE_SEP2:-' '} # Now, setup the formatted strings DATE_MMDDYY="$DATE_MONTH2$SEP1$DATE_DAY2$SEP1$DATE_YEAR2" DATE_MMDDYYYY="$DATE_MONTH2$SEP1$DATE_DAY2$SEP1$DATE_YEAR" YYMMDD="$DATE_YEAR2$SEP1$DATE_MONTH2$SEP1$DATE_DAY2" YYYYMMDD="$DATE_YEAR$SEP1$DATE_MONTH2$SEP1$DATE_DAY2" DATE_DDMMMYY="$DATE_DAY2$SEP2$DATE_MONTHABBR$SEP2$DATE_YEAR2" DATE_DDMMMYYYY="$DATE_DAY2$SEP2$DATE_MONTHABBR$SEP2$DATE_YEAR" DATE_MMMDDYYYY="$DATE_MONTHNAME $DATE_DAY, $DATE_YEAR" DATE_UNIX="$DATE_WDAY, $DATE_DAY$SEP2$DATE_MONTHABBR$SEP2$DATE_YEAR" DATE_LONG="$DATE_WEEKDAY, $DATE_MONTHNAME $DATE_DAY, $DATE_YEAR" DATE_TIME="$DATE_WDAY $DATE_MONTHABBR $DATE_DAY2 $TIME_HHMMSS" DATE_CTIME="$DATE_WDAY $DATE_MONTHABBR $DATE_DAY2 $TIME_HOURS24:$TIME_MINS:${TIME_SECS:-00}" :0 * TIME_AMPM ?? . { DATE_TIME="$DATE_TIME $TIME_AMPM" } :0 * TIME_ZONE ?? . { DATE_TIME="$DATE_TIME $TIME_ZONE" DATE_CTIME="$DATE_CTIME $TIME_ZONE" } DATE_TIME="$DATE_TIME $DATE_YEAR" DATE_CTIME="$DATE_CTIME $DATE_YEAR" } procmail-lib-2009.1202/lib-stebbens/dupcheck.rc000066400000000000000000000206561130547513300211030ustar00rootroot00000000000000# dupcheck.rc # # Copyright (C) 1997 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Usage: # # INCLUDERC=dupcheck.rc # # If the current mail has a "Message-Id:" header, run the # mail through "formail -D", causing duplicate messages to # be dropped. # # If the mail does not have a "Message-Id", or if the variable # "dupcheck_use_md5" is set, then run the body through MD5SUM (defaults # to "md5sum"), causing duplicate messages to be dropped. However, # even if "dupcheck_use_md5" is set, the "formail -D" filter will # still be applied if a Message-Id: exists. # # Currently, the only way to use *only* an "md5sum" duplicate check # is to remove the Message-Id: before invoking this recipe file. # Something like this: # # :0fh # remove the Message-Id: # | formail -IMessage-Id: # INCLUDERC=dupcheck.rc # # In my opinion, however, an MD5 checksum should be used in addition to using # the Message-Id:, not instead of. The MD5 checksums can be used to # detect and avoid redistributed or resent messages. # # The variable MD5SUM can be set to the program to perform the checksum # on the message body. By default, it is set to "md5sum". # # This recipe has been enhanced with a "fail-safe" algorithm to avoid # losing mail which has been "soft-failed" by some later part of the # user's recipe file. This algorithm is only applied if the variable # "dupcheck_failsafe" has been set to the number 1 or 2. # # There are two methods available to accomplish this, and selected by # the variable "dupcheck_failsafe". # # 1. the simple way: remove the checksum files when procmail exits with # an exitcode of 75. This is done by using a TRAP command. # # The disadvantage is that when any mail "soft fails" for any # reason, duplicate mail arriving after the soft-failure for mail # originally received before the soft-failure will not be detected. # # An advantage of this method is its simplicity. The worst case is # that a few duplicates may not be detected. # # 2. the hard way: using an additional "pending" log file, when a new # mail arrives and passes the checksum filters the first time, add it # to the "pending" file. Using a TRAP command, remove the processed # mail from the "pending" file, unless the exitcode was 75 # (EX_TEMPFAIL). If the mail fails the checksum commands, but is # still in the pending file, then do NOT drop the mail as a # duplicate, and leave it in the pending file. Eventually, when the # mail is finally delivered (by any means), it will be removed from # the "pending" file. # # The disadvantage with this method is its complexity: an additional # "pending" file is needed, and there is a small performance hit for # each mail, in order to maintain the pending file. # # The advantage of this method is its completeness: all duplicates # will still be detected and dropped. # # Both methods require the use of the TRAP command; they set additional # commands into the TRAP variable. If the TRAP command has already been # set, the new commands are added to the list of commands. # # *** Warning: if the user sets the TRAP command in a later recipe, care # should be taken to avoid losing the commands installed by this recipe. # The way to set TRAP with a new command, without losing the existing # ones, if any is: # # TRAP="${TRAP:+${TRAP}; }new-command args ..." # # All the default filenames used by this recipe are relative to the # current directory, $MAILDIR. msgids=.msgids # where we keep the message id's md5sums=.md5sums # where the md5 checksums go pendingids=.pendingids # pending mail cache dupcheck_failsafe=${dupcheck_failsafe:-2} # set to 1, 2, or anything else, # to indicate which method is # preferred. Defaults to 2. # If unset or not 1 or 2, then *no # failsafe* method is applied. OLDCOMSAT=${COMSAT:-off} # Don't tell COMSAT anything COMSAT=off # To keep the complexity of this recipe down, we'll separate the # failsafe methods :0 # methods 1 or 0 (none) * !dupcheck_failsafe ?? ^^2^^ { :0 Wh: $msgids.lock # is there a Message-Id:? * ^Message-Id: *\/[^ ].* | formail -D 16384 $msgids # mail is not a duplicate.. :0 e # passed formail's check; failsafe it? * dupcheck_failsafe ?? 1 { TRAP="${TRAP:+${TRAP}; }test \$EXITCODE -eq 75 && rm -f $msgids" } :0 # derive a checksum if needed or requested * 1^0 !^Message-Id: * 1^0 dupcheck_use_md5 ?? . { :0 b # scan only the body MD5SUM=|${MD5SUM:-md5sum} # compute md5sum on the body LOCKFILE=$md5sums.lock # lock $md5sums :0 aWhi # see if this is a duplicate message |fgrep -s "$MD5SUM" $md5sums # if fgrep succeeds, we've tossed the mail # Hurray! The mail is not a duplicate! :0 echi # add the new checksum to the file |echo "$MD5SUM" >>$md5sums LOCKFILE # unlock $md5sums :0 # see if the msg already has a header * ^X-MD5-Checksum: \/[^ ].* * $? test "$MD5SUM" != "$MATCH" { insert_opt='i' } # save the old flags on mismatch :0 fh # insert (or replace) current checksum |formail -${insert_opt:-'I'}"X-MD5-Checksum: $MD5SUM" :0 # any failsafe? * dupcheck_failsafe ?? 1 { TRAP="${TRAP:+${TRAP}; }test \$EXITCODE -eq 75 && rm -f $md5sums" } } } :0 E # fail-safe method 2: * dupcheck_failsafe ?? ^^2^^ { # With method 2, we must maintain a file of "pending" mail using this # recipe and a command in the TRAP variable. :0 chi:$pendingids.lock # ensure that the pending cache is writable * !?test -w $pendingids | rm -f $pendingids ; touch $pendingids pending # clear var LOCKFILE=$pendingids.lock # lock $pendingids # If there's a Message-Id and the mail is not pending :0 # is there a message-id? * ^Message-Id: *[^ ]\/.* { MSGID=$MATCH # save for later :0 # see if pending * $!?fgrep -s '$MATCH' $pendingids { :0 Wh:$msgids.lock # see if the mail is a duplicate |formail -D 16384 $msgids :0 chi # it's not; update the pending cache |echo "$MSGID" >>$pendingids } :0 E # it is a pending mail { pending=y } # mark it so # Update the TRAP command list to remove the msgid from the # pending cache on normal exits TRAP="${TRAP:+${TRAP}; }\ if test \$EXITCODE -ne 75 ; then \ fgrep -v '$MSGID' $pendingids >$pendingids.new ; \ mv $pendingids.new $pendingids ; \ fi" } LOCKFILE # unlock $pendingids # if not already pending, derive a checksum if needed or requested :0 * 1^0 !^Message-Id: * 1^0 dupcheck_use_md5 ?? . { :0 b # checksum the desired headers and body MD5SUM=|${MD5SUM:-md5sum} # see if this is a duplicate message LOCKFILE=$pendingids.lock # check the pending cache :0 # make sure it's not pending * ! pending ?? y * $!?fgrep -s '$MD5SUM' $pendingids { :0 Whi:$md5sums.lock # see if mail is an MD5 duplicate |fgrep -s "$MD5SUM" $md5sums # Hurray! the mail is not a duplicate :0 chi: # add the new checksum to the file |echo "$MD5SUM" >>$md5sums :0 achi # update the pending cache |echo "$MD5SUM" >>$pendingids } LOCKFILE # maybe pending now # Either we've updated the pending file, or the checksum was # already in it. So, now we update the TRAP command list to # remove the checksum on normal exits. TRAP="${TRAP:+${TRAP}; }\ if test \$EXITCODE -ne 75 ; then \ fgrep -v '$MD5SUM' $pendingids >$pendingids.new ; \ mv $pendingids.new $pendingids ; \ fi" :0 # see if the msg already has a header * ^X-MD5-Checksum: \/[^ ].* * $? test "$MD5SUM" != "$MATCH" { insert_opt='i' } # save old headers on mismatch :0 fh # in any case, set the new checksum |formail -${insert_opt:-'I'}"X-MD5-Checksum: $MD5SUM" } # end md5 check } COMSAT=$OLDCOMSAT # set COMSAT back to original value OLDCOMSAT procmail-lib-2009.1202/lib-stebbens/eg.spam-bounce-w-threshold.rc000066400000000000000000000033351130547513300243510ustar00rootroot00000000000000 SPAMSITES='(spam.com|foo.org|blah.com)' # sites to check MAXFROM=10 # more than 10 mails/day from :0 # check for mail from a spam site * $ ^(From|Sender:|Reply-To:).*@.*$SPAMSITES { # ok -- mail is from a possible spam site -- check # of occurances FROM=`formail -rtzxTo:` # get the best from DATE=`date +%Y%m%d` # get YYYYMMDD SUBJ=`formail -zxSubject:` # get the subject FROMLOG=from.log # logfile of FROM addresses :0ci: # log this message | echo "$FROM $DATE : $SUBJ" >>$FROMLOG # Find out how many message have been received today COUNT=`fgrep -c "$FROM $DATE" $FROMLOG` :0 # see if we've received too many * $ -$MAXFROM^0 * $ $COUNT^0 { # count was exceeded - generate a reply :0 # clean up the subject * SUBJ ?? Re: *\/[^ ].* { SUBJ=$MATCH } :0 fh # generate a reply header * $ !^X-Loop: *$LOGNAME@$HOST | formail -rt -I"From: ($LOGNAME's Mail-Agent) $LOGNAME" \ -I"Subject: Re: $SUBJ" \ -I"Precedence: junk" \ -I"X-Loop: $LOGNAME@$HOST" :0 afb # generate a reply body | echo "Your message is being returned because you've sent me" ; \ echo "too many message today. Your original message follows:" ; \ cat - :0 a # send it off ! -t :0 E # no reply generated error.log # keep an error log } # mail count is okay, forge on } # normal mail processing follows The recipe works by keeping a log of all recieved mail, with a single line of "$FROM $DATE : $SUBJ" being appended to the log file. Then, if the number of lines with the "$FROM $DATE" string exceeds a threshold, a reply is generated. If any error in the reply, or if a mail loop is detected, file the mail to "error.log". procmail-lib-2009.1202/lib-stebbens/gen-spam-reply.rc000066400000000000000000000062221130547513300221460ustar00rootroot00000000000000# gen-spam-reply.rc # # Copyright (C) 1997 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id: gen-spam-reply.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # This is a sample procmail rc file which can be used # to generate an automatic response to mail which has # somehow been identified as being a source of spam. # # If the variables ADDR, TOADDR, or REGEXP match, then # current message, then a response is generated to the # originator of the message, stating that something about # the message had been identified as a source of spam. # The original message is returned as part of the response. # # # This recipe file does not set the policy by which a # "spam site" is selected, it merely implements whatever # policy the user has chosen. # # Use this "subroutine" recipe file as follows: # # Set one or more of the following variables: # # ADDR=some-spam-source-address # TOADDR=some-noisy-mailing-list # REGEXP=a-regexp-which-matches-a-spam-mail # INCLUDERC=gen-spam-reply.rc # # # Our handy FROM_DOMAIN variable. If you *know* that this recipe will # always have FROM_DOMAIN defined already, then you don't need to define # it again. But, I've put it here, so that the recipe file can stand # on its own and is more understandable. # # See "headers.rc" for a collection of header regexps. # :0 # pull in handy headers file, if needed * ! HEADERS_RC ?? . { INCLUDERC=headers.rc } # See if the mail came by any source address from $ADDR spam # flag to maybe set :0 # ADDR set and matches? * ADDR ?? . * $${FROM_DOMAIN}${ADDR}\> { spam=1 } :0 # TOADDR set and matches? * TOADDR ?? . * $^TO$TOADDR { spam=1 } :0 # REGEXP set and matches? * REGEXP ?? . * $$REGEXP { spam=1 } :0 # is the mail spam? * spam ?? . { # yes, generate a reply header SUBJ=`formail -zXSubject: | tr -d '"'` # get the subject (without quotes) :0 fhw # generate a reply header | formail -rt -I"Subject: Re: $SUBJ" \ -I"Precedence: junk" \ -I"X-Loop: $LOGNAME@$HOST" :0 afb # form the reply body | echo "\ Email from your site is being shunned because something about\n\ it has been identified as a source of spam. If your mail\n\ was, in fact, not spam, please resend it using the\n\ keyword 'not-spam' in the subject. Unsolicited commercial\n\ use of this mailbox will be billed at $500 per incident.\n\ \n\ Your original email follows:\n\ ----------------------------------------------------------" ; \ cat - :0 a # now feed the reply to sendmail ! -oi -t } procmail-lib-2009.1202/lib-stebbens/get-date.rc000066400000000000000000000002071130547513300207750ustar00rootroot00000000000000# get-date.rc # # See date.rc for Copyright info. # # $Id: get-date.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # DATE INCLUDERC=date.rc procmail-lib-2009.1202/lib-stebbens/get-from.rc000066400000000000000000000030071130547513300210240ustar00rootroot00000000000000# get-from.rc -- procmail rc file to get the "best" from address # # Sets FROM and FRIENDLY, the latter being the "friendly" user name # sans any address. # # $Id: get-from.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Get the best FROM :0 * ! ^Reply-to: *\/[^ ].* * ! ^From: *\/[^ ].* * ! ^Sender: *\/[^ ].* * ! ^From +\/[^ ]+ * ! ^X-Envelope: *\/[^ ].* { FROM=nobody } :0E { FROM=$MATCH } # Get the "friendly" name part of the address, by # 1. removing any bracketed address part, # 2. removing any unbracketed address part, # 3. unquoting any text # 4. unparenthesizing any text FRIENDLY=`echo $FROM | sed -e 's/ *<.*> *//' \ -e 's/ *[^ ][^ ]*[\@\!][^ ][^ ]* *//' \ -e 's/"\(.*\)"/\1/' \ -e 's/(\(.*\))/\1/'` FRIENDLY=${FRIENDLY:-$FROM} procmail-lib-2009.1202/lib-stebbens/guess-mua.rc000066400000000000000000000024461130547513300212200ustar00rootroot00000000000000# guess-mua.rc # # Guess the Mail User Agent and set MUA # # $Id: guess-mua.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # First, let's check for MH # Make sure it's not already defined :0 * MUA ?? !.+ { # See if mhpath works MHPATH=`mhpath + 2>/dev/null` :0 * MHPATH ?? .+ { MUA=mh } # Else, see if ~/.pinerc works :0 E * test -f $HOME/.pinerc { MUA=pine } # Else, check for ~/.mailrc (for BSD/mail) :0 E * test -f $HOME/.mailrc { MUA=mail } # Add others as they are needed.. } procmail-lib-2009.1202/lib-stebbens/headers.rc000066400000000000000000000062771130547513300207330ustar00rootroot00000000000000# procmail rc to define patterns to recognize the headers # # $Id: headers.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Use these is recipes like this: # # # If mail is from john or mary, then file in "+urgent" # :0 # * $ $FROM(john|mary)@ # urgent/. # # # if the mail is directly to me, then file it # :0 # * $ $TO($USER)@ # mymail/. # # # See which list this mail is from: # :0 # * $ $FROM_LIST_MAILER # { LISTADDR=$MATCH } # These patterns span any comment text before and after email addresses # Use PRE_ADDR_SPAN before any names; it will span a string of non-address # characters up to the beginning of a valid email address. PRE_ADDR_SPAN='(.*[^-(.%@a-zA-Z0-9])?' # Use POST_ADDR_SPAN after any names; it will span a string of non-address # characters up to the a comma "," or the end of the line POST_ADDR_SPAN='(([^),.!:a-zA-Z0-9].*)?(,|$[^>]))' # These are to match RFC822 style addresses (not including UUCP addresses) # Use $USERADDR to match a user name part of an email address USERADDR='[-a-zA-Z0-9_:.+=/]+' # Use $HOSTADDR to match the FQDN hostname part of an address HOSTADDR='[-a-zA-Z0-9_:.+=/]+' # Use $HOSTNAME to match the "plain" hostname (not include any domains) HOSTNAME='[-a-zA-Z0-9_:+=/]+' # Use $ADDR to match either an RFC 822 or UUCP email address ADDRESS="?" # Use $FROM to match mail from someone FROM="(^((Reply-To|(Resent-)?(From|Sender)|X-Envelope-From):|>?From )\ $PRE_ADDR_SPAN)" # Use $TO to match mail to someone (but only "To:", not "Cc:") TO="(^((Original-)?(Resent-)?To|(X-Envelope|Apparently(-Resent)?)-To):\ $PRE_ADDR_SPAN)" # Use $CC to match mail to someone (but only "Cc:", not "To") CC="(^((Original-)?(Resent-)?Cc|(X-Envelope|Apparently(-Resent)?)-Cc):\ $PRE_ADDR_SPAN)" # For completeness, this should be roughly equivalent to ^TO TOCC="($TO|$CC)" # Pattern to recognize lists by precedence LIST_PRECEDENCE='(^Precedence:.*(junk|bulk|list))' # Names of common list mailers # List the more specific mailers first, with generic names later LIST_MAILERS="(LISTSERV|ListProc|${USERADDR}-(l(ist)?|request|own[er]r)|\ owner-${USERADDR}|Majordomo?|Mailagent|mmdf|news|n?uucp|\ Post(mast(er)?|-?office)|procmail|SmartList|(Mailer-)?daemon|root)" # Pattern to put them all together, just to detect mail from a list FROM_LIST="($LIST_PRECEDENCE|$FROM$LIST_MAILERS$POST_ADDR_SPAN)" procmail-lib-2009.1202/lib-stebbens/list-addr.rc000066400000000000000000000036541130547513300211770ustar00rootroot00000000000000# # list-addr.rc # # Get a mailing list address, if possible. # :0 * DEBUG ?? . { SENDMAIL=true LOGABSTRACT=all VERBOSE=yes } INCLUDERC=headers.rc # There seems to be a new convention to provide sub/unsub info on # informational headers. The following is an attempt to discover # if there is any header which contains the patter .*-request. # If so, it's a good bet that the string is the list request address. :0 H * $\/${USERADDR}-request@$HOSTADDR { LISTADDR=$MATCH } # Okay, if that didn't work, now we do some heuristic lookups of # well-known list mailer addresses. # However, we must do this carefully, because some mails have the # "From:" or "Sender:" set to "BLAH-request" or "BLAH-owner", but # the "From " header has "Daemon" or "Root". The problem is that # just doing a "^$FROM\/$LIST_MAILERS" will always match the "From " # header if it was from "root" or "daemon", even though the more # useful address is on the subsequent "Resent-From:" or "Sender:" # header. This is why the multi-line condition below :0 EH * $!^Resent-Reply-To:$PRE_ADDR_SPAN\/$LIST_MAILERS@$HOSTADDR * $!^Resent-Sender:$PRE_ADDR_SPAN\/$LIST_MAILERS$HOSTADDR * $!^Resent-From:$PRE_ADDR_SPAN\/$LIST_MAILERS$HOSTADDR * $!^Reply-To:$PRE_ADDR_SPAN\/$LIST_MAILERS$HOSTADDR * $!^Sender:$PRE_ADDR_SPAN\/$LIST_MAILERS$HOSTADDR * $!^From:$PRE_ADDR_SPAN\/$LIST_MAILERS$HOSTADDR * $!^X-Envelope-From:$PRE_ADDR_SPAN\/$LIST_MAILERS@$HOSTADDR * $!^From $PRE_ADDR_SPAN\/$LIST_MAILERS@$HOSTADDR { :0 * $ $FROM$LIST_MAILERS@$HOSTADDR { LISTADDR=$MATCH } } # Cool. We matched one of the headers from above :0 E { LISTADDR=$MATCH } # This stuff only happens in DEBUG mode # ie: procmail -DDEBUG -m list-addr.rc # # Procmail recipe file to save the current message to # a list of one or more folders set by pf-check.rc. # # You may wish to set the variable PF_DEST before invoking. # # INCLUDERC=pf-save.rc # # If the message is filed into a folder, LOGABSTRACT is # set to "off" so a duplicate log is not created. :0 * PF_DEST ?? . { # Add a new X-Filed if necessary :0 fh * !^X-Filed: | formail -A "X-Filed: $PF_DEST" # Else, if there is already a header, possibly append to it :0 E { OLD_PF_DEST=`formail -zxX-Filed:` :0 fh * $!^X-Filed:.*$PF_DEST |formail -I"X-Filed: $OLD_PF_DEST $PF_DEST" } # If filing into MH folders, use one copy and procmail will take # care of linking. :0 c * PF_DEST ?? /\.$ $PF_DEST # If not filing into MH folders, use recursive filing :0 E { DEST=`echo $PF_DEST | cut -d' ' -f1` PF_DEST=`echo $PF_DEST' ' | cut -d' ' -f2-` # File into the first folder now :0 c: $DEST # Possibly file into the 2nd and other folders with recursion # It must be non-blanks, and not identical to the already filed DEST :0 c * PF_DEST ?? [^ ] * $! DEST ?? $PF_DEST |procmail -pm PF_RECURSE=yes pf-save.rc # If we were recursing, don't file multiple copies into DEFAULT :0 * PF_RECURSE ?? yes { HOST=_stop_now_ } } LOGABSTRACT=off } procmail-lib-2009.1202/lib-stebbens/pod2man.mk000066400000000000000000000020421130547513300206450ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . BIN ?= package PODCENTER ?= $$(date "+%Y-%m-%d") MANSECT ?= 1 MANDEST ?= $(MANSRC) MANPOD ?= $(MANSRC)$(BIN).$(MANSECT).pod MANPAGE ?= $(MANDEST)$(BIN).$(MANSECT) makeman: $(MANPAGE) $(MANPAGE): $(MANPOD) which pod2man && \ podchecker $(MANPOD) && \ pod2man --center="$(PODCENTER)" \ --name="$(BIN)" \ --section="$(MANSECT)" \ $(MANPOD) \ | sed 's,[Pp]erl v[0-9.]\+,$(BIN),' \ > $(MANPAGE) && \ rm -f pod*.tmp # End of of Makefile part procmail-lib-2009.1202/lib-stebbens/prefile-example.rc000066400000000000000000000043571130547513300223740ustar00rootroot00000000000000# prefile.rc # # Example prefile.rc file # # $Id: prefile-example.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Tailor this to suit your taste # # Use the syntax "FOLDER/." for MH folders. # Use the syntax "FOLDER" for BSD Mail folders. # Do not mix mingle the styles. If, for some strange # reason, you want to do both kinds of filing, do all # the filing of one style first, then do all the other # style next. Eg: # # PF_DEST # do MH style first # ADDR=foo DEST=foo/. INCLUDERC=pf-chkto.rc # ADDR=bar DEST=bar/. INCLUDERC=pf-check.rc # ... # INCLUDERC=pf-save.rc # # PF_DEST # now do folder-file style # ADDR=foo DEST=foo INCLUDERC=pf-chkto.rc # ADDR=bar DEST=bar INCLUDERC=pf-check.rc # ... # INCLUDERC=pf-save.rc # # ... PF_DEST # clear these vars PF_FROM :0 * ? test pf-chkto.rc { # Make a series of checks for various mailing lists and # associated folders in which to file them. If a message # is addressed to multiple lists, it will be filed into # multiple folders (with hardlinks by procmail). # These are MH style prefiling recipes ADDR=info-gnu-emacs DEST=gnu/emacs/. INCLUDERC=pf-chkto.rc ADDR=perl-users DEST=info/perl/. INCLUDERC=pf-chkto.rc ADDR=procmail DEST=info/procmail/. INCLUDERC=pf-chkto.rc ADDR=bladerunners DEST=rec/blading/. INCLUDERC=pf-chkto.rc # These are the same recipes for non-MH folders ADDR=info-gnu-emacs DEST=gnu-emacs INCLUDERC=pf-chkto.rc ADDR=perl-users DEST=info-perl INCLUDERC=pf-chkto.rc ADDR=procmail DEST=info-procmail INCLUDERC=pf-chkto.rc ADDR=bladerunners DEST=rec-blading INCLUDERC=pf-chkto.rc } # Personal mail prefiling -- if the mail is either from an address, # or to an address, from me, then it gets prefiled. # IN other words, it tracks mail threads to and from an address and # yourself. :0 * ? test pf-check.rc { ADDR="(aks(@.*sgi\.com)?|Alan.*Stebbens)" DEST=priv/Alan.Stebbens/. # MH style INCLUDERC=pf-check.rc ADDR="((vice-)?president@whitehouse.gov|Mr. (Vice-)?President)" DEST=junk/politics/. INCLUDERC=pf-check.rc ADDR="(newt@congress.gov|Newt.Gingrich)" DEST=junk/politics/. INCLUDERC=pf-check.rc #... } # Now save the mail if any there are any destinations :0 * PF_DEST ?? . * ? test pf-save.rc { INCLUDERC=pf-save.rc } procmail-lib-2009.1202/lib-stebbens/proclint000066400000000000000000000217331130547513300205410ustar00rootroot00000000000000#!/usr/bin/perl # # proclint [-[no]list] [-[no]includerc] [-procmailrc] rcfiles ... # # Copyright # # Copyright (C) 2006-2010 Jari Aalto # Copyright (C) 1995-2010 Alan Stebbens # # License # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . # # Description by Alan Stebbens # # By default, -noincluderc and -nolist are set. # # Because debugging procmailrc scripts is difficult # I try to encode checks into this script. # # If -list given, list all lines of the recipe, numbered, and # with levels and a type flag character. # # Current errors caught: # # '{' and '}' nesting errors. # Missing '*' on conditions # Lines which aren't recipes or assignments # Unterminated recipes my($DIR,$PROG) = $0 =~ m,^(.*/)?([^/]+)$,; $DIR =~ s,/$,, || chomp($DIR = qx(pwd)); my $FH_TEMPLATE = 'fh00'; my $ERROR = 0; $| = 1; sub Usage (;$) { my $code = shift || 0; print <<"EOF"; exit $code; usage: $PROG [options] Check procmail rc files for proper syntax, recipe nesting, etc. Options (default are marked with '*'): -h, --help This message -i, --includerc Scan and possibly list files included with INCLUDERC -I, --noinclude* Do not scan INCLUDERC references -l, --list List lines in the procmail recipe files. -L, --nolist* Do not list lines, except for errors. -p, --procmailrc Check \$HOME/.procmailrc The output consists of: 'LINE-NUMBER:FLAG:DEPTH: text'. FLAG is one of: 'R' recipe 'C' condition 'A' action (redirect, '!', or pipe, '|') 'F' folder '=' assignment '+' continuation 'E' *line may be erroneous* DEPTH indicates the depth of the recipe nesting and is shown only when greater than zero. EOF } sub Untab ($) { local $_ = shift; while (($x = index($_,"\t")) >= $[) { substr($_,$x,1) = " " x (((($x / 8) + 1) * 8) - $x) } $_; } sub Eval { my $val = shift; while( ( $val =~ /\$(\w+)/ ) ) { if( defined( $Assigns{$1} ) ) { $val = $` . $Assigns{$1} . $'; } elsif( defined( $ENV{$1} ) ) { $val = $` . $ENV{$1} . $'; } else { $val = $` . $'; # omit the variable -- it's empty } } $val; } sub Scan ($; $$); sub Scan ($; $$) { my $file = shift; my $fileLevel = shift || 0; my $mainLevel = shift || 0; return if $Scanned{$file}; $Scanned{$file}++; my($type, $count, $conditions, $var, $val); my($includefile, $depth); my($level) = $mainLevel; local $_; unless ($quiet) { print "\n" if $listlines; print (" " x $fileLevel); print "Scanning file $file:"; } local($FH) = $FH_TEMPLATE++; open( $FH , $file ) or do { print "Can't open $file: $!\n"; $ERROR = 1; return; }; print "\n" unless $quiet; my $recipe = ''; my $errs = ''; my $continuation = ''; my $line = ''; while( <$FH> ) { chomp; $_ = Untab $_ if /\t/; if( $continuation ) { $line .= "\n".$_; $_ = $line; $line = ''; $continuation = ''; } if( /\\$/ ) { # continuation? $continuation = 1; chop; # remove the trailing slash $line = $_; # make the continuation next; } $type = ' '; if( /^\s*\#/ or /^\s*$/ ) { # ignore comments or blank lines $type = ' '; $_ = ' ' unless length; } elsif( ! $recipe or /^\s*:/) # are we looking for a recipe? { # This is a state driven scanner # State Parse Next What # 0 : 1 Start recipe parse # 1 * 1 Parse condition # 1 ! 0 Parse redirect # 1 | 0 Parse pipe # 1 { 0 Increment recipe level, parse sub-recipe # 1 0 Parse filename path if( /^\s*:\s*(\S.*)?/ ) # recipe start? { $flags = $1; # get flags $count = $flags =~ /^(\d+)/ ? $1 : $flags =~ /[eEaA]/ ? 0 : 1; $recipe = $.; # we're in a recipe $conditions = 0; $type = 'R'; # set the type } elsif( /^\s*}/ ) # end of a nested recipe? { $level--; $type = 'R'; if ($level < 0) { $errs .= "Too many close brackets!\n"; $level = 0; } } elsif( /^\s*(\w+)\s*=\s*(\S.*)?/ ) # an assignment? { $type = '='; # assignment ($var,$val) = ($1,$2); if( $includerc ) { $Assigns{$var} = $val; if( $var eq 'INCLUDERC' ) { $newfile = Eval $val; if( $newfile && -f $newfile ) { $includefile = $newfile; } elsif ( $newfile ) { $errs .= "Included file \"$newfile\" does not exist.\n"; } } } } elsif( /^\s*(\w+)\s*$/ ) # an un-assignment? { $type = '='; # unassignment } else { $errs .= "Bad recipe line: \"$_\"\n"; $type = 'E'; } } else { if( /^\s*\*/ ) # a condition? { $conditions++; $type = 'C'; # condition $count--; } elsif ( /^\s*!/ && $count <= 0) # a redirection? { $recipe = ''; # an action, we're out of the recipe $type = 'A'; # Action } elsif ( /^\s*\|/ ) # a pipe? { $recipe = ''; # another action $type = 'A'; # Action } elsif ( /^\s*{/ ) # a subrecipe { $level++; # increment the level $recipe = ''; # and we're out of the recipe $type = 'A'; # Action $level-- if /\s+}/; # decrement count if one-liner } elsif ( --$count >= 0 && !/^\s*[\|{]/) # more conditions? { $conditions++; $type = 'C'; # assume condition } else # default is path { $type = 'F'; # folder # make reasonable mistake guess if ( /^\s*[\#*(){}|!?]|^\s*\w+ \w+/ ) { $errs .= "Possibly bad folder name?\n"; } $recipe = ''; } } Print: if ( $listlines or $errs ) { @lines = split /\n/; $depth = $level > 0 ? sprintf("<%d>",$level) : " "; while ($_ = shift(@lines)) { print (" " x $fileLevel); $_ .= "\\" if @lines; printf "%3d:%1s%s %s\n",$.,$type,$depth,$_; $type = '+'; } } if( $errs ) { print $errs; $ERROR = 1; $errs = ''; } if ($includefile) { Scan( $includefile, $fileLevel + 1, $level ); unless ($quiet) { print "\n" if $listlines; print (" " x $fileLevel); print "Back to file $file:\n"; } $includefile = ''; } } if ($recipe) { print "$file: EOF: recipe at line $recipe never terminated.\n"; $ERROR = 1; } if ($level > $mainLevel) { print "$file: EOF: Unterminated nested recipies.\n"; $ERROR = 1; } close $FH; } sub Main () { unless ($#ARGV >= $[) { Usage 1; } while( $_ = shift @ARGV ) { if ( /^(-h|--help)/ ) { Usage; } elsif ( /^(-l|--list)/ ) { $listlines++; } elsif ( /^(-L|--nolist)/ ) { $listlines = ''; } elsif ( /^(-i|--includerc)/ ) { $includerc++; } elsif ( /^(-I|--noincluderc)/ ) { $includerc = ''; } elsif ( /^(-p|--procmailrc)/ ) { $HOME = $ENV{'HOME'} || (getpwuid($>))[7]; push(@ARGV,"$HOME/.procmailrc"); } elsif ( /^-/ ) { print "Unknown option: '$_'\n"; next; } else { Scan $_; } } return $ERROR; } Main(); # End of file procmail-lib-2009.1202/lib-stebbens/proclint.1000066400000000000000000000132511130547513300206740ustar00rootroot00000000000000.\" Automatically generated by Pod::Man 2.1801 (Pod::Simple 3.07) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "proclint 1" .TH proclint 1 "2008-12-09" "proclint" "2008-12-09" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" proclint \- Lint procmail rc files for proper syntax .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& proclint [options] .Ve .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-h, \-\-help\fR" 4 .IX Item "-h, --help" Display short help. .IP "\fB\-i, \-\-includerc\fR" 4 .IX Item "-i, --includerc" Scan and possibly list files included in code with \s-1INCLUDERC\s0 statements. .IP "\fB\-I, \-\-noinclude\fR" 4 .IX Item "-I, --noinclude" Do not scan \s-1INCLUDERC\s0 references (default). .IP "\fB\-l, \-\-list\fR" 4 .IX Item "-l, --list" List lines in the procmail recipe files. .IP "\fB\-L, \-\-nolist\fR" 4 .IX Item "-L, --nolist" Do not list lines, except for errors (default). .IP "\fB\-p, \-\-procmailrc\fR" 4 .IX Item "-p, --procmailrc" Check \f(CW$HOME\fR/.procmailrca .SH "DESCRIPTION" .IX Header "DESCRIPTION" Check procmail rc files for proper syntax, recipe nesting, etc. The output consists of: \f(CW\*(C`LINE\-NUMBER:FLAG:DEPTH: text\*(C'\fR. \s-1FLAG\s0 is one of: .PP .Vb 7 \& R recipe \& C condition \& A action (redirect, \*(Aq!\*(Aq, or pipe, \*(Aq|\*(Aq) \& F folder \& = assignment \& + continuation \& E *line may be erroneous* .Ve .PP \&\s-1DEPTH\s0 indicates the depth of the recipe nesting and is shown only when greater than zero. .SH "BUGS" .IX Header "BUGS" There are many bugs. E.g. multiline handling is not done (continued strings). .PP Please regard the output as advisory only.x .SH "STATUS CODES" .IX Header "STATUS CODES" Program returns non-zero in case problem is found. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" None. .SH "FILES" .IX Header "FILES" None. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIprocmail\fR\|(1) .SH "AUTHORS" .IX Header "AUTHORS" Program was written by Alan K. Stebbens . .PP This manual page was written by Jari Aalto . Released under license \s-1GNU\s0 \s-1GPL\s0 v2 or (at your option) any later version. For more information about license, visit . procmail-lib-2009.1202/lib-stebbens/proclint.1.pod000066400000000000000000000042111130547513300214510ustar00rootroot00000000000000# This is manual page in Perl POD format. Read more at # http://perldoc.perl.org/perlpod.html or run command: # # perldoc perlpod | less # # To check the syntax: # # podchecker *.pod # # Create manual page with command: # # pod2man PAGE.N.pod > PAGE.N =pod =head1 NAME proclint - Lint procmail rc files for proper syntax =head1 SYNOPSIS proclint [options] =head1 OPTIONS =over 4 =item B<-h, --help> Display short help. =item B<-i, --includerc> Scan and possibly list files included in code with INCLUDERC statements. =item B<-I, --noinclude> Do not scan INCLUDERC references (default). =item B<-l, --list> List lines in the procmail recipe files. =item B<-L, --nolist> Do not list lines, except for errors (default). =item B<-p, --procmailrc> Check $HOME/.procmailrca =back =head1 DESCRIPTION Check procmail rc files for proper syntax, recipe nesting, etc. The output consists of: C. FLAG is one of: R recipe C condition A action (redirect, '!', or pipe, '|') F folder = assignment + continuation E *line may be erroneous* DEPTH indicates the depth of the recipe nesting and is shown only when greater than zero. =head1 BUGS There are many bugs. E.g. multiline handling is not done (continued strings). Please regard the output as advisory only. Patches are welcome as there is nobody developing proclint as of 2007-01-12. =over 4 =item * Program does not understand comments after environment variable assignments. =item * Program does not complain when mail is being delivered to mailboxes in a directory which does not exist. =item * Extraneous locallockfile settings are not detected. =back =head1 STATUS CODES Program returns non-zero in case problem is found. =head1 ENVIRONMENT None. =head1 FILES None. =head1 SEE ALSO procmail(1) =head1 AUTHORS Program was written by Alan K. Stebbens . This manual page was written by Jari Aalto . Released under license GNU GPL v2 or (at your option) any later version. For more information about license, visit . =cut procmail-lib-2009.1202/lib-stebbens/procmail-lib.html000066400000000000000000000100511130547513300222130ustar00rootroot00000000000000 AKS Procmail Library Description

AKS Procmail Library

The AKS Procmail Library contains the following files:

Makefile
a Unix Makefile to help install these libary files in /usr/local, or another location.
ackmail.rc
a set of recipes which perfom auto-acknowledgement of incoming mail. This file uses guess-mua.rc and unread-mh.rc. See ackmail.3 for details.
commands.help
A file of information sent in response to a mail request of "Subject: help info". See "commands.rc".
commands.rc
A set of recipes which recognize commands in the Subject: header and perform them. A log is kept of all such commands.
comm-reply-file.rc
A recipe file which replaces the body of the current message with a named, or generates an error report. A "subroutine" recipe file for "commands.rc".
correct-addr.rc
A recipe file which can help do mail forwarding for users who have moved or changed email addresses. Currently not well tested.
dupcheck.rc
A recipe file which removes duplicate mail.
get-from.rc
A recipe file which extracts the "best" address, including personal information from the various originating address fields.
guess-mua.rc
A recipe file which attempts to guess the current MUA (Mail User Agent). Not needed of MUA is explicitly defined.
headers.rc
Defines some variables which can be used for matching against headers.
list-addr.rc
A recipe file which trys to determine if the current mail is from a mailing list or not. This is still experimental and not well tested.
procmail-lib.html
An HTML file which describes the Procmail Library.
unread-mh.rc
A recipe file which attempts to compute how many unread messages there are for an MH user.

If you have improvements or contributions to this collection of recipes, please send them to me at <aks@sgi.com>. I may not respond quickly to any submissions, but I always appreciate suggestions for improvement.


Procmail is a mail filtering program, with which a user can process incoming mail in an infinite number of ways. Procmail is publicly available at no cost, other than your time. The current version of procmail is always available at:

The latest version of procmail can be obtained directly from the FTP archive:

ftp.informatik.rwth-aachen.de (137.226.225.3)

as (g)zipped tar file: /pub/packages/procmail/procmail.tar.gz <160KB

as compressed tar file: /pub/packages/procmail/procmail.tar.Z <224KB

Procmail, SmartList, and my procmail and SmartList libraries are also available via FTP:

ftp://hub.ucsb.edu/pub/mail/procmail.tar.gz

ftp://hub.ucsb.edu/pub/mail/SmartList.tar.gz

ftp://hub.ucsb.edu/pub/mail/procmail-lib.shar

ftp://hub.ucsb.edu/pub/mail/smartlist-lib.shar

If you have any questions about using procmail, there is a mailing list with lots of helpful members: <procmail@informatik.rwth-aachen.de>. Use the address: <procmail-request@informatik.rwth-aachen.de> to subscribe to the list.

procmail-lib-2009.1202/lib-stebbens/procmail-tutorial000066400000000000000000000214451130547513300223560ustar00rootroot00000000000000To: procmail Cc: procmail-author Subject: Using procmail to prefile your mail Reply-To: Alan Stebbens -------- The following is a small procmail tutorial I have written for some of my peers, who are greatly inundated with email as part of their daily work. I thought that the procmail community would be a good forum to review it. Thanks! _______________________________________________________________ Alan Stebbens (415) 933-6437 Interactive Digital Systems (IDS), Silicon Graphics, Inc. (SGI) M/S:9L991, 2011 N. Shoreline Blvd., Mountain View, CA 94043 ============================================================ This document describes how you can to use procmail to prefile your incoming mail so that the only action you need to take on any prefiled message is to delete it. Since it was prefiled, it is already saved in the appropriate folder or folders, thus, you can safely delete it after viewing it in your inbox. Here's how. There are many ways to do this, but I'll describe two basic methods. Let's assume that you are on the info-gnu, info-gcc, mh-users, perl-users, smartlist, and procmail mailing lists. Let's further assume that you use MH-style folders since you use MH as your mailer (as I do, with emacs + mh-e "on top"). BTW, Procmail can do both kinds of mail dropping: in numbered, unique filenames in directories as folders, or appending to files as folders. The syntax for a "plain" file drop is: folder while the syntax for a MH-style folder is: folder/. The basic method is to write a "copy" recipe which recognizes a particular mailing list, and copies the mail into the corresponding folder: :0c * ^TOinfo-gnu info/gnu/. :0c * ^TOinfo-gcc info/gcc/. :0c * ^TOmh-users info/mh/. :0c * ^TOperl-users info/perl/. :0c * ^TOsmartlist info/smartlist/. :0c * ^TOprocmail info/procmail/. and so on. These recipes have the effect of filing the mail into folders corresponding to the mailng lists, and then filing the mail into the $DFAULT maildrop, which is your system mailbox. The "c" flags on the recipe start means "copy", so that procmail keeps going. The problem now is that when you read the mail from the inbox, you don't know if the mail has actually been saved or not. So, it is a good idea to "flag" the mail by adding a new header indicating how it was filed. Here's how: :0c * ^TOinfo-gnu info/gnu/. :0afh |formail -A"X-Filed: info/gnu" :0c * ^TOinfo-gcc info/gcc/. :0afh |formail -A"X-Filed: info/gcc" :0c * ^TOmh-users info/mh/. :0afh |formail -A"X-Filed: info/mh" and so on, for each mailing list you wish to have mail filed for. The "a" flag means that the recipe is an AND condition, applied only if the preceding receipe (at the same leve) was successful. The "f" flag means that the recipe is a "filter", meaning that the stdout of the process will replace the stdin which was the message; "formail" is designed for this usage. The "h" means filter only the headers. Now, when you receive mail in your inbox, if it has been prefiled, the header "X-Filed" will appear in the message with the name of the folder under which the mail was copied. There are still some problems with this method: (a) if the message is sent to several mailing lists (eg: To: info-gnu, info-gcc, .etc), then a "X-Filed:" header for each mailing list will be inserted; (b) if you are using MH-style folders, multiple identical copies (except for the "X-Filed:" header) of the mail will be filed into several folders, when it could have been hard-linked from the original, saving space; (c) There are now two recipes per mailing list, and all of the recipes are the same except for the mailing list name, and the corresponding folder. This leads us to the next method: of creating and using "subroutine" recipe files. Let's assume that we have a "checking" recipe and a "filing" subroutine recipe. The "checking" recipe would need an ADDRESS to recognize and a corresponding DESTination folder in which to prefile the message. The "filing" recipe would then file the message into the appropriate DEST folder as well as insert one "X-File:" header with the names of the folders appended. I'll call the "checking" recipe "pf-check.rc", for "prefile check", and I'll call the "filing" recipe "pf-save.rc", for "prefile save". Here's how our main recipe in ~/.procmailrc would now look: ADDR=info-gnu DEST=info/gnu/. INCLUDERC=pf-check.rc ADDR=info-gcc DEST=info/gcc/. INCLUDERC=pf-check.rc ADDR=mh-users DEST=info/mh/. INCLUDERC=pf-check.rc and so on, for each mailing list. After all the checking recipes, we need to invoke the "saving" recipe: INCLUDERC=pf-save.rc If you are really stuck on brevity, you could write the recipes like this, even using tabs to make it look pretty: ADDR=info-gnu DEST=info/gnu/. INCLUDERC=pf-check.rc ADDR=info-gcc DEST=info/gcc/. INCLUDERC=pf-check.rc ADDR=mh-users DEST=info/mh/. INCLUDERC=pf-check.rc ADDR=perl-users DEST=info/perl/. INCLUDERC=pf-check.rc ADDR=procmail DEST=info/procmail/. INCLUDERC=pf-check.rc ... INCLUDERC=pf-save.rc Of course, all this is vaporware until pf-check.rc and pf-file.rc exist (and work :^). Here's what they look like: # pf-check.rc # # Author: Alan K. Stebbens # # Procmail recipe file to check an address ADDR for filing. # If the address matches, append DEST to PF_DEST. # # After all checks are complete, invoke pf-save.rc to save the # message into the appropriate folders. # # Set these variables before invoking: # # ADDR Address to which addressed mail will be filed # into the named folder. # # DEST Destination into which addressed mail will be # dropped. # # INCLUDERC=pf-check.rc :0 * ADDR ?? . * DEST ?? . * $ ^TO$ADDR { PF_DEST="$PF_DEST $DEST" } Pretty simple, so far. Here's pf-save.rc: # pf-save.rc # # Author: Alan K. Stebbens # # Procmail recipe file to save the current message to # a list of one or more folders set by pf-check.rc. # # You may wish to set the variable PF_DEST before invoking. # # INCLUDERC=pf-save.rc # # If the message is filed into a folder, LOGABSTRACT is # set to "off" so a duplicate log is not created. :0 * PF_DEST ?? . { # Add a new X-Filed if necessary :0 fh * !^X-Filed: | formail -A "X-Filed: $PF_DEST" # Else, if there is already a header, possibly append to it :0 E { OLD_PF_DEST=`formail -zxX-Filed:` :0 fh * $!^X-Filed:.*$PF_DEST |formail -I"X-Filed: $OLD_PF_DEST $PF_DEST" } # If filing into MH folders, use one copy and procmail will take # care of linking. :0 c * PF_DEST ?? \.$ $PF_DEST # If not filing into MH folders, use recursive filing :0 E { DEST=`echo $PF_DEST | cut -d' ' -f1` PF_DEST=`echo $PF_DEST | cut -d' ' -f2-` # File into the first folder now :0 c: $DEST # Possibly file into the 2nd and other folders with recursion :0 c * PF_DEST ?? ([^ ]) |procmail -m PF_DEST="$PF_DEST" PF_RECURSE=1 pf-save.rc # If we were recursing, don't file multiple copies into DEFAULT :0 PF_RECURSE ?? . { HOST=_stop_now_ } } LOGABSTRACT=off } This recipe is a little more complicated because it has to handle both MH-style filing (easy) and non-MH-style filing (harder). IMHO, procmail should be consistent in how it handles filing to multiple folders but it is not. Using these recipes will save those of you on many mailing lists at least 3 seconds per message (conservatively), as well as help you to develop a consistent filing algorithm. Three seconds may not seem like much time to save, but if you are on several mailing lists, you may be receiving up to 100 message per day or more. Do the arithmetic: 3 * 100 = 300 seconds = 5 minutes. 500 messages a day is almost a half hour of your time just filing email. And this is based on the assumption that you can make a decision and issue the corresponding command to your mailer to file a message within 3 seconds. I can do it in 3 seconds with Emacs' help, but not in Pine or Zmail, or most other mailers; so, you will spend more time per message accomplishing your filing. Another way to think of it: why should you spend your time making these trivial kinds of decisions? I hope this helps. Some of you have already indicated that other parts of my procmail library have been useful. I strongly believe that we should make the computers do as much of the work as possible. Email, like any good tool, should enable us to get more work done, without creating more of it. Alan procmail-lib-2009.1202/lib-stebbens/procmail.info000066400000000000000000000010701130547513300214370ustar00rootroot00000000000000 If you have any questions about using procmail, there is a mailing list with lots of helpful members: . Use the address: to subscribe to the list. -------------------------------------------------- The latest version of procmail can be obtained directly from the ftp-archive at: ftp.informatik.rwth-aachen.de (137.226.225.3) as (g)zipped tar file: /pub/packages/procmail/procmail.tar.gz <160KB as compressed tar file: /pub/packages/procmail/procmail.tar.Z <224KB procmail-lib-2009.1202/lib-stebbens/procmailrc-example000066400000000000000000000213201130547513300224630ustar00rootroot00000000000000# This is an annotated example ~/.procmailrc file # # Use it as a guide to creating your own ~/.procmailrc file. # # You must edit this before installing it; # *** IT WILL NOT WORK AS IS ***. # # $Id: procmailrc-example,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # It is a good idea to define SHELL to /bin/sh, so that no # unexpected surprises occur. Some systems redefine SHELL to # your default login shell, which may not be a Bourne-shell compatible # shell. Since most procmail recipes use Bourne-shell language # features, SHELL=/bin/sh is a good idea. SHELL=/bin/sh # Defining the path to include the directories where procmail is # installed is necessary if the system default path doesn't include # them. Typically, ~/.procmailrc is invoked by procmail via # sendmail, and the PATH may not be sufficient as it is. PATH=$PATH:/usr/local/bin:/usr/local/mh/bin # Defining MAILDIR does a "cd $MAILDIR". So, define it to the # directory which contains most of your mail recipes. I use # $HOME/Mail. MAILDIR=$HOME/Mail # It is an important feature to keep a log of your mail -- just so you # have some kind of idea what is happening to it. Note that plain # filenames are relative to MAILDIR, since procmail always sets the # current directory to MAILDIR. So, if you keep your recipe and log # files in $MAILDIR, then you can name the files by their basename. LOGFILE=Log # I use FAILDROP to define a mail drop location which is on a # *different* filesystem than my $DEFAULT maildrop. This allows # me to write conditional recipes, which are invoked only if # the $DEFAULT or other delivery fails. FAILDROP=/other/spool.mail # If you use MH as your MUA (as I do), then defining several # folders here make it easy to globally change them later. # MH folders are indicated by the trailing "/.". INBOX=inbox/. ADMIN=admin/. OTHER=other/. BADMAIL=errs/. # I use this in many recipes to identify myself, and to # annotate filtered mail with "X-Loop: $MY_ADDR" headers as # part of a loop detection algorithm. MY_ADDR=myname@myhost.mydomain.dom # I use $MY_NAMES variable to recognize the various aliases # which all lead to my incoming maildrop. If you have an # AOL and Compuserve and Internet account all forwarded to # the same address, you would define this as the all of the # varying alternatives. MY_NAMES="(First Mi. Lastname|First|Lastname|First\.Lastname|\ F.Lastname|FML)@(myhost\.mydomain\.dom|aol\.com|\ compuserv.com) # Define FROMSIG to your standard "From:" signature line. FROMSIG="First's Mailer-Daemon <$MY_ADDR>" # I include "dupcheck.rc" to avoid duplicate incoming mail. Note that # this will not identify mail duplicated by different mailers, just # duplicate mail from the same origin. INCLUDERC=$LIB/dupcheck.rc # Pull in the standard header patterns INCLUDERC=$LIB/headers.rc # If I am on vacation, I create a file called ~/Mail/vacation.msg # into which I place my notice explaining my absence. This file # is examined by "ackmail.rc" (see below). # However, some of my other recipes below varying their behavior # depending upon the value of $VACATION. In vacation mode, # more things get tossed than otherwise. # So, set VACATION to "yes" in vacation mode :0 * ? test -f vacation.msg { VACATION=yes } # The rest of the recipe is broken into two basic parts: # # a. process mail if it is addressed *directly* to me, # on either a "To:" or "Cc:" header. # # b. process other mail (mail to me via any mailing # lists of which I am a member). # # # I like the variable $USER (since I grew up on a BSD system), # so let's define it using the SysV equivalent (which procmail # sets up). USER=${USER:-$LOGNAME} # If the mail is to me ($USER), do some special things :0 * $ ^TO($USER) { # First -- since I allow a selected set of commands # on the Subject: line, I use "commands.rc" to recognize # and perform them. # Check for any commands on the Subject line # (but only if commands.rc is present). :0 * ? test -f commands.rc { INCLUDERC=commands.rc } # I also like to have mail to me acknowledged, to I use # ackmail.rc. Include it :0 * ? test -f ackmail.rc { INCLUDERC=ackmail.rc } # So far, the mail is not a command, and it has been # acknowledged, so now we can safely file it away. # If the mail is directly to me, -> +inbox :0: $INBOX # If the drop to $INBOX failed, then let's try dropping # it into $DEFAULT (which is where it would have gone # our recipe hadn't tried filtering it). :0 e: $DEFAULT # Well, the $DEFAULT drop didn't work, so let's try # yet another filesystem. :0 e: $FAILDROP } # Okay -- mail below here came to me indirectly -- from some # mailing list. # In vacation mode, let's trash any root mail -- someone else # get's to worry about this :0 h * VACATION ?? yes * ^(To|From):.*root([ ,>]|$) /dev/null # I've occasionally written an addition to this basic procmail # recipe by writing small, special case filtering recipes. I # Then "include" them using the method below. This allows me # to later disable the special case filtering by removing the # file, or moving it to another name. # A common special case is where you develop a group of # users who share a common interest for a while. I then # write such a small recipe to detect the incoming mail of interest # and redirect it to these interested users. A kind of # "home brew" mailng list. # # This way, I can share the mail to me by relaying it to them without # having to inform (and educate) them about mailing lists. Typically, # some of these users are either adminstrative types or highly # non-technical types who do not wish to learn about mailing lists, but # do wish to share in the mail of interest. # This is only a short term solution -- setting up a mailing # list is the proper thing to do for longer term distributions. :0 * ? test -f mac-users.rc { INCLUDERC=mac-users.rc } # I treat junkmail filtering as a "special case", and keep it # in a separate file. Basically, all the mail delivered in # this file goes to /dev/null. :0 * ? test -f junkmail.rc { INCLUDERC=junkmail.rc } # Here's an example of a piece of mail which you might # wish to have printed regularly when it arrives, and # even auto-filed, but still show up in your +inbox for # online perusal. # Check on edupage; automatically print it (unless I'm on vacation) # and auto-file it. Leave it also in my inbox to be read and deleted. :0 * ^Sender: *owner-edupage * ^To:.*\ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Just count how many messages in $DEFAULT UNREAD=no # default output # There are two basic methods: a fast way and a slow way # The fast way (loses sometimes -- but, really, who cares? we're # just counting unread messages.) :0 * ? test -f $DEFAULT { UNREAD=`egrep -c '^From ' $DEFAULT` } # The slow way, but, the "procmail" way :^) # #:0 #* ? test -f $DEFAULT #{ JUNK=`formail -e -s echo -n x < $DEFAULT` # :0 # * JUNK ?? 1^1 x # { UNREAD = $= } #} procmail-lib-2009.1202/lib-stebbens/unread-mh.rc000066400000000000000000000052661130547513300211750ustar00rootroot00000000000000# unread-mh.rc # # procmail recipe to compute how many unread messages # for MH as the MUA (mail user agent). # # $Id: unread-mh.rc,v 1.1 2002/01/01 22:25:33 jaalto Exp $ # # Copyright (C) 1995 Alan K. Stebbens # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # Usage: # # Referenced by "ackmail.rc" when MUA=mh and the text of the # reply includes the string '$UNREAD' # # If MH_INFOLDERS is set, uses the output of "folder +$folder" # for each folder mentioned in MH_INFOLDERS. The sum of the # current message number subtracted from the last message # number for each folder is returned. # # If MH_INFOLDERS is not set, then check for the Unseen-Sequence # profile entry. If this is set, uses the number of messages # in this sequence. # # If there is no Unseen-Sequence profile entry, or there is no # sequence in the +inbox, then use the output of 'folders +inbox' # as for MH_INFOLDERS above. # # Note: PATH should include the MH bin directory UNREAD=no # default output SHELL=/bin/sh # be sure # If the user has defined one or more explicit folders in the # variable MH_INFOLDERS, then use a shell script to get UNREAD :0 * MH_INFOLDERS ?? .+ { UNREAD=`(for f in $MH_INFOLDERS ; do folder +$f ; done) | sed -n -e 's/^.*- *\([0-9]*\)); cur= *\([0-9]*\);.*/ok \1 \2/p' | awk '/ok/ { s+=$2-$3 } END { print s }'` } # If no explicit folder list, try using unseen sequences :0 E { # Get some MH info MH_INBOX=`mhpath +inbox` MH_UNSEENSEQ=`mhparam Unseen-Sequence` MH_INSEQFILE=$MH_INBOX/.mh_sequences :0 chW * MH_UNSEENSEQ ?? [a-z]+ * ? test -f $MH_INSEQFILE * ? grep "^$MH_UNSEENSEQ:" $MH_INSEQFILE |UNREAD=`pick +inbox $MH_UNSEENSEQ 2>/dev/null | wc -l` # Ok -- no unseen sequence. Try last resort of using +inbox info. :0 E { INFOLDER=`folder +inbox` :0 * INFOLDER ?? cur= *\/[0-9]+ { CUR=$MATCH :0 * INFOLDER ?? messages *\( *[0-9]+- *\/[0-9]+ { MAX=$MATCH :0 * ? test "$MAX" -gt "$CUR" { UNREAD=`expr $MAX - $CUR` } } } } } procmail-lib-2009.1202/lib/000077500000000000000000000000001130547513300151535ustar00rootroot00000000000000procmail-lib-2009.1202/lib/ChangeLog000066400000000000000000001077461130547513300167440ustar00rootroot000000000000002009-02-26 Jari Aalto Mass update: Copyright years. 2008-12-20 Jari Aalto * pm-jamime-kill.rc: (Possible conflict with the awk): Warn about gawk being a symlink and not real GNU awk. 2008-12-18 Jari Aalto * pm-jamime-kill.rc: Cosmetics. Adjust comments, code layout and improve documentation of variable JA_MIME_TYPE. 2008-12-09 Jari Aalto * pm-jamime-decode.rc (jamimeHandledFrom): Remove unused JA_MIME_TYPE which prevented calling the recipe. Closes Debian bug #388526. 2008-09-22 Jari Aalto * pm-jamime-kill.rc: (MIME_BOUNDARY_COUNT 3): Rewrite AWK so that is correctly kills the set JA_MIME_TYPE, like "text/html" portion. 2008-09-20 Jari Aalto * pm-jafwd.rc: (top level) Add missing 'Change Log' header. 2007-09-20 Jari Aalto RELEASE 20070930.1156 * pm-jaube-keywords.rc (jaubeKeywords): Many new additions. (JA_UBE_KEYWORD_HEADER): Recipe moved inside another recipe so that the processing is more logical (recipe logic): Removed all "else" cases and now the ERROR is sum of all found reasons separated by colon (:). This means that error string may be like: "Header-SubjectKeywords:Body-Keywords" 2006-09-13 Jari Aalto * pm-jaube-keywords.rc (jaubeKeywords): Added: realestate, your monthly payment, your cr rating 2006-09-12 Jari Aalto * pm-jaube.rc (NoDirectAddress-ToCc): Added FROM_DAEMON test to weed out false positives. * pm-jaube-keywords.rc (jaubeKeywords): Added: trade, trading, deal to you, we specialize, low rate, update your, losing it all, access PayPal account, filing quotes, view my profile, since we've chatted, VIP visitor, you search for something, bitch, hope (LINEBUF): Moved restoring the value from `$jaubeKwdLinebufOld' to the end of file. (at the end): Added new rule to trim down ERROR_MATCH; strip leading and trailing newlines. 2006-09-11 Jari Aalto * pm-jaube.rc (MessageId-Empty): renamed. Was `MessageIdEmpty' 2006-09-08 Jari Aalto * pm-jaube.rc (MessageId-Invalid): Made the check more strict and added explanation about RFC822. Corrected wrong regexp (removed $ from the end). Made domain portion more strict. * pm-jaube-keywords.rc (LINEBUF): Changed from 8192 to 65536 2006-09-07 Jari Aalto * pm-javar.rc (CHAR_LIST_SCANDINAVIAN): Added `$#'. 2006-09-07 Jari Aalto * pm-javar.rc (CHAR_LIST_SWEDEN): Wrong list *FINNISH => *FINLAND. (CHAR_LIST_NORWAY): Renamed. Was `CHAR_LIST_NORGE' (CHAR_LIST_SCANDINAVIAN): Wrong list *FINNISH => *FINLAND. 2006-06-14 Jari Aalto * pm-jaube-keywords.rc (jaubeSubjectKeywordsOnly): Added 'secretary' regexp. (jaubeKeywords): Added 'boob' regexp. 2006-03-13 Jari Aalto * pm-jamime-save.rc - All temp variables (but dummy) now have prefix JaMimeSave to prevent clashes to user variables. (AWK): Wrong test: COUNT => MIME_BOUNDARY_COUNT in recipe. BEGIN-clause error in awk. Corrected \e => 'e'. The 'extrtacted to file ...' message was missing preceding newline in the replaced message (stuck against MIME headers which was wrong). (JA_MIME_SAVE_OVERWRITE ?? no): Change the filename from FILE.ext.YYYY-MM-DD to YYYY-MM-DD-hhmm.file.ext which preserves the file extension better. Added the Hour and minute to make the filename more unique. (file ?? a-z): Check for existing LINEBUF setting. IF bigger than 500K+ (the default), then use what user has set. Bug: code overrode e.g value 9999999 with 500K+. Closes sourceforge bug http://sourceforge.net/tracker/index.php?func=detail&aid=1447661&group_id=11052&atid=211052 2006-02-26 Jari Aalto * pm-javar.rc (MV): Wrong initialisation. Was `RM'. Closes sourceforge bug http://sourceforge.net/tracker/index.php?func=detail&aid=1296225&group_id=11052&atid=111052 2006-02-16 Thu Jari Aalto * pm-jamime-kill.rc (top level::set-defaults): jpeg|tiff conctained incorrect recipe start "0". Fixed to ":0". Error reported by Lucio Chiappetti . Thanks. Added application/x-msdownload killer default recipe for *.exe attachments. (JA_MIME_EXTRA_HEADER): New user variable. Documented in 'Call arguments'. (jaMimeKillMsg): New variable. (at the bottom): Added new recipe to add JA_MIME_EXTRA_HEADER if `jaMimeKillMsg' was set. * pm-jaube-prg-bmf.rc: Documentation layout corrections. Fit into 77 column wide display. * pm-jamime-kill.rc: 2.10 Documentation improvements. (Required settings): Mention about `metamail' package and program `mimencode'. (jaMimeKillModified): Variable remaned. Was `modified'. Prevent clashes with other global variables and put it in proper namespace. * pm-javar.rc: Improved description of `mimemail' and next to variable `MIME_BIN'. 2006-01-25 Jari Aalto * pm-jaube-keywords.rc: Added many variables from pm-javar.rc: NL, CR, TAB, WSPC, SPC, NSPC, CHAR and changed pevi 2005-10-10 Mon Jari Aalto * pm-jalist.rc (List-Post): Added new recipe to check List-Post, List-Unsubscribe and List-subscribe. Patch thanks to Frederic Crozat 2005-05-06 Jari Aalto * pm-jaube.rc (JA_UBE_MIME_CHARSET_ILLEGAL): Added word anchors \< and \> 2005-03-03 Jari Aalto * pm-jamime-decode.rc: Rewrote Subject handling to tackle multiple ISO encoded string. Bug reported by . (PM_JAMIME_COMPLEX_SUBJECT): New return variable. * pm-jasubject.rc: Added check for ISO-8859-1 encoded Subject. Idea by 2005-03-02 Jari Aalto * pm-jaube-keywords.rc (jaubeSubjectKeywordsOnly): Many corrections. Deleted possibly 'ok' words and added word anchors. 2005-03-01 Jari Aalto * pm-jaube-keywords.rc - Namespace cleanup. (jaubeSubjectKeywordsOnly): Renamed. Was `subjectKeywordsOnly'. (jaubeKeywords): Renamed. Was 'keywords'. Fixed \ \ and added other corrections. (jaubeLanguage): Renamed. Was `language'. * pm-jamime-recode.rc - Renamed all variables 'MIME_DECECODE' => 'MIME_RECODE'. (JA_MIME_RECODE_TREAT_SUBJECT): New user variable. (JA_MIME_RECODE_TREAT_FROM): New user variable. * pm-jamime-decode.rc - The default operation mode is now only to decode Subject line - Body/From treatment must be separately turned on. - Tightened regexps to check iso-8859 (handledSubject): Added 's/_/ /g' to Subject clean. Bug reported by . (JA_MIME_DECODE_TREAT_SUBJECT): New user variable. (JA_MIME_DECODE_TREAT_FROM): New user variable. (JA_MIME_DECODE_TREAT_BODY): New user variable. 2005-02-28 Jari Aalto * pm-jamime-recode.rc: New file. 2005-02-28 Jari Aalto * pm-jaube-prg-runall.rc: Replaced 'ERROR=' assignment with `ERROR' which kills the variables. It is cleaner that they hold no value at all. * pm-jaube-prg-bogofilter.rc (JA_UBE_BOGOFILTER_OPT): Removed extra `$' from variable definition line. * pm-jaube-prg-spamprobe.rc ($JA_UBE_SPAMPROBE_PRG): Check for failures with `A' set ERROR only if succeeded. 2005-02-26 Jari Aalto * pm-jamime-decode.rc (dummy): Removed variable `id'. * pm-javar.rc (dummy): Removed variable `id'. * pm-jamime-decode.rc (JA_MIME_DECODE_HEADER): New. 2005-02-20 Jari Aalto * pm-jaube-keywords.rc (keywords): Added 'pain killer'. 2005-02-18 Jari Aalto * pm-jaube-keywords.rc (keywords): word fix: pharmac => pharmae?c 2005-02-16 Wed Jari Aalto UPDATED COPYRIGHT YEAR IN ALL FILES. * pm-javar.rc: 2.31 Added `$CR' riage return. `SPCL' now includes $CR. * pm-jamime-save.rc: 2.9 Use '&& MV', not '; MV'. * pm-jamime-decode.rc: 2.6 - Added From: header decoding. - Removed `jaMimeDecodeShellmetas'. Let shell do it's job. - The ISO-8859-1 Subject/From RFC 2047 encodings code was improved. with `sed'. (Subject|From): REcipe check made more accurate. - Added support for ?B? base64 decoded From/Subject headers. 2005-02-15 Jari Aalto * pm-jaube-keywords.rc: (keywords): Updated regexp cum => cum(shots?)? 2005-02-04 Jari Aalto * pm-jaube-keywords.rc (keywords): Better 'hi' regexp to allow ! and 'hiiiii...'. 2005-02-04 Jari Aalto * pm-jaube.rc (Check attachements): Corrected file name regexp. 2005-01-29 Sat Jari * pm-jalist.rc ($NSPC): All variables replaced with shorter Perl styled '$S' ($from): Added missing beginning-of-line anchor (^) to every recipe. (dummy): Cleanup. Removed all $NL variables from `dummy' debug variables. (Documentation): Fixes and corrections. (List-id): 2.13 Frederic Crozat reported 2004-11-18 that 'List-Id: gnome-print-list.gnome.org' was not matched and sent patch. Fix applied. (TRY From-Subject 3 words): Frederic Crozat reported 2004-11-18 that forwarded message was falsely trapped due to multiline match and sent a path. Fix applied but with slight changes. The MATCH must be written as '$\MATCH' to make special characters immune. Like if grabbed word we '[Fwd:' it will be converted to '()\[Fwd:'. 2005-01-26 Jari * pm-jaube-prg-bogofilter.rc (recipe JA_UBE_BOGOFILTER_HEADER_NEW): incorrect optiona name --spam_header_name => --spam-header-name and commented out lock file. 2005-01-25 Jari Aalto * pm-jaube.rc (Check attachements): Removed SPACE from regexp because clever spammers try to send file names like 'this.doc .pif'. 2005-01-21 Jari * pm-jaube-keywords.rc (subjectKeywordsOnly): Changed 'make.*(it|her|extra)' to 'make.*(her)' which is more strict. 2005-01-12 Jari Aalto * pm-jaube.rc (JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL): Set value to empty string. That is better default. 2004-12-28 Jari Aalto * pm-jaube-prg-spamprobe.rc (JA_UBE_SPAMPROBE_FORCE): Removed lockfile. 2004-12-17 Jari Aalto * pm-janslookup.rc (JA_NSLOOKUP_CACHE): Added anchor ^ in cache grep regexp. Use EGREP, not GREP. Tightened regexp. 2004-12-16 Thu Jari Aalto * Makefile: 1.2 CODEDIR changed to DATADIR. 2004-12-15 Wed Jari Aalto * pm-jaube-prg-spamassassin.rc: New module. * pm-jaube-prg-bogofilter.rc: New module. * pm-jaube-prg-annoyance-filter.rc: 1.3 (JA_UBE_ANNOYANCE_SPAM_DB_OPT): Fast dictonary option --fread is no longer the default. * pm-javar.rc (RC_UBE_BOGOFILTER): New variable. * pm-jaube-prg-runall.rc: 1.14 (spamasassin): Rmeoved duplicate `JA_UBE_SPAMASSASSIN_PRG' variable test. Added 100 character test for SA. (bogofilter): Code removed and moved to separate file. (spamassassin): Code removed and moved to separate file. * pm-jaube-prg-bmf.rc (Rearrange headers): 1.20 Typo in 'dummy' message: X-Spambmf => X-Spam-Bmf. 2004-11-04 Thu Jari Aalto * pm-jadaemon.rc: 2.9 (JA_DAEMON_SAVE). New user variable. Save old subject. Suggested by 'Balu'. (JA_DAEMON_REGEXP): Added missing newline. Fixed SF-pm-lib bug 1046370. 2004-10-27 Jari Aalto * pm-jaube-keywords.rc (subjectKeywordsOnly): Added missing backslash after 'keywords'. (keywords): Added missing backslash 2004-10-24 Sun Jari Aalto * pm-jasubject.rc: (top level) 2.6 Removed 'id' variable. Removed 'NL' variables. Moved 'public' portion upward. Removed extra empty lines. (awk): Improved subject detection so that it can now take into account long backets like in '[this is long bracket]'. Everything up till 'bracket]' word is deleted. Bug reported by Markus Hubig (LINEBUF): Value is now saved and restored. Need bigger value. 2004-10-21 Jari Aalto * pm-jaube-keywords.rc (keywords): More mutable Cialis and Viagra traps added. 'size matters' also improved. (like s|ze). 2004-10-19 Jari Aalto * pm-jaube-keywords.rc: Added missing (#) to the 1st line. (Marketing-SelectedBigLetterWords): Removed some words that are likely to occur in email. (JA_UBE_CAPS_OK): Variable is set to empty string. This is now disabled by default, because there are too many valid messages with acronyms. 2004-10-18 Jari Aalto - In pm-jaube-* files ERROR variables are now 'killed', and not just set to empty strings. * pm-jaube-keywords.rc (jaubeKwdLinebufOld): New. Save value of LINEBUG, increase it and restore it at the end. (ERROR_STATUS): No longer contains word 'Good'. Only word 'Bad' if ERROR is set. This avoids calling formail. Only spam messages are tagged. (keywords): Regexp '(sav(ing|e)|buy|see|web)' was too lose (second word had '?'), and matched legal dovuments. Made stricter. (JA_UBE_KEYWORD_HEADER): simplified formail recipe. 2004-10-17 Jari Aalto * pm-jaube-keywords.rc (end of file): Display ERROR and ERROR_STATUS on exit by assigning value to 'dummy'. (JA_UBE_KEYWORD_HEADER): Improved formail call. The header included 'Good ' with two spaces at the end. Removed. * pm-jaube.rc (doc::Return values) Added list of ERROR codes. (regexpBody): Put virus regexp variable definitions inside recipe block, so that no unnecessary messages are recorded to the log file. 2004-10-16 Jari Aalto * pm-jaube.rc (HeaderCharacters-Illegal): Missing '$' from '${ERROR+:}'. Added. (HeaderMimeCharset-Illegal): Moved below the other header charset tests. (BodyMimeCharset-Illegal): Moved below the other header charset tests. 2004-10-15 Jari Aalto * Makefile (exec_prefix): Change from /usr/share to /usr/local/share, because 3rd party packages that are not included with the OS, should install under /usr/local by default. (INSTALL_CODE_DIR): Renamed. Was PMDIR (include common.mk): Moved definitions to separate file. 2004-10-14 Jari Aalto * pm-jaube-keywords.rc (subjectKeywordsOnly): Added few more keywords, like 'see.*this.*(web|site|page)' etc. (HeaderMimeCharset-Illegal): All charcter set tests are now run unconditionally, no matter if previous tests already set ERROR e.g. to BodyAttachment-FileIllegalAdditional. The charset error is simply appended to the previous error. * pm-jaube.rc (regexpHeader): Added Virus message detection. New rules: VirusHeader, VirusBody 2004-10-07 Jari Aalto * pm-jaube.rc (Attachments): Moved rule to the top. They are more important than the AddrInvalid-To * pm-jalist.rc (trigger): added words 'apps', like in mailing list cygwin-apps. (cc): Added cc_* variables to check message sent to mailing list with CC header. 2004-10-06 Jari Aalto * pm-jaube-prg-runall.rc (bsfilter): New. Now supported. * pm-javar.rc (RC_UBE_BSFILTER): New. 2004-10-06 Jari Aalto * pm-jalist.rc (JA_LIST_FROM_TO_IGNORE): New user variable. (Sender is identical to To): Ignore 'root' generated system messages according to $JA_LIST_FROM_TO_IGNORE (id): Variable removed. (3 word check): Added test for JA_FROM_DAEMON and JA_FROM_MAILER. * pm-jaube.rc (JA_UBE_ATTACHMENT_ILLEGAL_REGEXP): Added .inf .bas .bin .dll .swf .msi .msc .mst .pcd .reg .vbe .wsc .wsf .wsh .sct .chm .jar 2004-10-04 Jari Aalto * pm-jaube-keywords.rc (keywords): Adjusted 'dollar' regexp. In addition to VI0XX $12.33 it now also matches two digits+ whole part: VI0XX $12 2004-10-02 Jari Aalto * pm-jaube-prg-runall.rc (JA_UBE_BOGOFILTER_HEADER_NEW): Incorrect variable initialization. Was *_ORIGINAL when should have been *_NEW. fixed. Now header is X-Spam-Bogofilter-Status. 2004-09-28 Jari Aalto * pm-jaube-prg-annoyance-filter.rc: New module. * pm-jaube-keywords.rc (keywords): Added general regexp to match word like V:I:A:G:R:A!! * pm-jaube-prg-runall.rc: Added support for spamoracle and annoyance filter. * pm-jaube-keywords.rc (keywords): Added 'bondage', 'sadomasokism' * pm-javar.rc (RC_UBE_SPAMORACLE): New variable. (RC_UBE_ANNOYANCE): New variable. (top level): Added /bin/ prefix to most ised programs, like ls, tr, rm, mv, cp, sed, cat. This will speed up calling programs. Added * pm-jaube-prg-spamoracle.rc: New module. * pm-jaube-prg-bmf.rc (JA_UBE_BMF_HEADER_PREFIX): Changed from 'X-Spam-Bmf' to 'X-Spam-Bmf-'. 2004-09-26 Jari Aalto * pm-jaube-prg-spamprobe.rc: Documentation incorrectly referred tp X-Spamprobe. Corrected to X-Spam-Spamprobe-Status. * pm-jaube-prg-spamprobe.rc (run filter): Added lockfile. * pm-jaube-prg-ifile.rc (run filter): Added lockfile. * pm-jaube-prg-bmf.rc (run filter): Added lockfile. * pm-jaube-prg-runall.rc (bogofilter): Added lockfile during shell call. 2004-09-25 Jari Aalto * pm-jaube-prg-runall.rc (doc:Important notes): New topic. Explain why X-Bogocity header is renamed to X-Spam-Bogofilter-Status. (JA_UBE_BOGOFILTER_HEADER_ORIGINAL): New user variable. (bogofilter): Use --spam_header_name if $JA_UBE_BOGOFILTER_HEADER_NEW is set. * pm-jaube-prg-spamprobe.rc (JA_UBE_SPAMPROBE_HEADER): Changed header from 'X-Spamprobe' to 'X-Spam-Spamprobe-Status' to be consistent with e.g. X-Spam-Status used by spamassassin. * pm-jaube-prg-bmf.rc (JA_UBE_BMF_HEADER_PREFIX): Changed header from 'X-Spambmf' to 'X-Spam-Bmf-Status' to be consistent with e.g. X-Spam-Status used by spamassassin. * pm-jaube-prg-ifile.rc: (JA_UBE_IFILE_HEADER): Changed header from 'X-Spamifile' to 'X-Spam-Ifile-Status' to be consistent with e.g. X-Spam-Status used by spamassassin. * pm-jaube-keywords.rc (keywords): Removed 'pleasure'. 2004-09-24 Jari Aalto * pm-jaube-keywords.rc (subjectKeywordsOnly): Removed words learn, we. Too generic. (keywords): Removed 'charm'. Too generic. 2004-09-24 Jari Aalto * pm-jaube.rc: (docs): Corrected sentences. Used example.com for all email addresses. (Required settings): pm-jaube1.rc is not used. Removed. (Html): Moved this recipe to the end. The other recipes are more reliable. * pm-jaube-prg-runall.rc (spamassassin): Added lockfile * pm-jaube-keywords.rc (keywords): Added more matches and adjusted some to use more restrictive regexps. 2004-09-23 Jari Aalto * pm-jasubject.rc: 2.5 (Code Note): Better english sentences. (Awk usage note): Suggest gawk, not nawk. * pm-jasrv.rc: 2.6 (top line): Description changed. * pm-japing.rc: 2.6 (Usage example): indented 4 spaces forward for better HTML output. * pm-jamime-save.rc: 2.8 (doc) Suggest gawk, not nawk. * pm-jamime-kill.rc: (doc) 2.8 Removed reference to HP 9, 10. Added 'Note:' to the beginning stating, that this module cannot do miracles. * pm-jalist.rc: 2.9 Typo in docs: know => known. * pm-jafwd.rc: 2.6 (top line): Description modified. * pm-jaempty.rc: 2.7 (top line): Description modified. * pm-jaube-prg-runall.rc (top level): ERROr variable is now cleared after subroutine calls if the message was not spam. (bogofilter): Many corrections. $JA_UBE_BOGOFILTER_OPT cannot be empty in shell call. Added match to show contents of X-Bogosity. (spamprobe): Clear ERROR is message is not spam. * pm-jaube-prg-bmf.rc (tests=bmf): In 'No' case there was no value 'tests=bmf' and SA values were not restored. Fixed. * pm-jaube.rc (final-check): Added `JA_UBE_ATTACHMENT_SUSPECT_KILL' to call AWK to delete attachment. The variable was previously unused. (Body: Attachments): Variables `JA_UBE_ATTACHMENT_ILLEGAL_REGEXP' and `JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL' tested match against body, which was wrong. Now they test against filename. * pm-jadaemon.rc (JA_DAEMON_REGEXP): Update. Now includes many more regexps, which also catch spam messages that pretend to be daemon messages. 2004-09-20 Jari Aalto * pm-jaube-prg-ifile.rc (call ifile): Surrounded the blocks following the `ifile' with a check that `jaubeIfileFolder' was set. The rest of the code is called only if program succeeded. Changed 'fw' to 'fhw' in formail. 2004-09-14 Jari Aalto * pm-javar.rc (RC_UBE_SPAMPROBE): Incorrect file name. Fixed. * pm-jaube-prg-bmf.rc: Typos in documentaton fixed. * pm-jaube-prg-ifile.rc: Typos in documentaton fixed. * pm-jaube-prg-spamprobe.rc: Typos in documentaton fixed. * pm-jaube-prg-runall.rc: New module. * pm-javar.rc (JA_FROM_MAILER): Added RC_UBE_RUNALL. 2004-09-14 Jari Aalto * pm-jaube-prg-bmf.rc (JA_UBE_BMF_HEADER_PREFIX): Clarified comment above. 2004-09-10 Jari Aalto * pm-jaube-keywords.rc (keywords): Added 'our +(company|product)' 2004-09-01 Wed Jari Aalto * pm-jaube-keywords.rc: (subjectKeywordsOnly) 2.21 Added \$[0-9][0-9.]+ and changed may keywords to use '\<' word boundary. For example it was unfortunate that 'rich' matched 'Richard' and so on. 2004-08-31 Jari Aalto * pm-javar.rc (TAB): Again TAB was changed to spaces by my Emacs setup. Inserted literal tab there. 2004-08-27 Fri Jari Aalto * pm-jaube-keywords.rc: Set ERROR_STATUS variable at the end to `Bad' if message was UBE. * pm-javar.rc: Added RC_UBE_IFILE. * pm-jaube-prg-ifile.rc: New module. * pm-jaube-prg-spamprobe.rc: 2.3 Complete rewrite. CAll formail only if JA_UBE_SPAMPROBE_HEADER is set. formail did not use JA_UBE_SPAMPROBE_HEADER variable. 2004-08-26 Jari Aalto * pm-jalist.rc: 2.7 Documentation typos fixed. Removed invalid URL www.netmeg.net. Added pointer to www.gmane.org. * pm-jaube.rc: 2.15 (BodyHtmlImage): New rule. * pm-jaube-keywords.rc: Added some more keywords. E.g. Better V....gra test. 2004-08-25 Wed Jari Aalto * pm-jaube-keywords.rc: Documentation typos fixed. * pm-jaube-prg-spamprobe.rc: Added Section 'Required settings' * pm-jaube-prg-bmf.rc: 1.9 Added Section 'Required settings' Added missing ERROR variable. * pm-jaube.rc (BodyHtml-script): Added () in front of test. 2004-08-24 Jari Aalto * pm-javar.rc (d): Added $n $t, $OR, $NOR * pm-jaube-keywords.rc: Removed commas from results put in JA_UBE_KEYWORD_HEADER * pm-javar.rc (CHAR_7BIT_CONTROL): New. * pm-jaube.rc Removed commas from results put in JA_UBE_HDR (JA_UBE_ATTACHMENT_SUSPECT_REGEXP): Updated. (JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL): New. (JA_UBE_CHARSET_LEGAL): Added CHAR_7BIT_CONTROL (JA_UBE_SUBJECT_GREETING): New. (MessageId-Invalid): Moved \/ earlier so that there will be something in MATCH. 2004-08-24 Tue Jari Aalto * pm-jaube.rc (AddrInvalid-To): added condition line to set ERROR_MATCH (tld): Added missing TLDs according to standard. (AddrInvalid-To): Remove anchor (^) Because There is Apparently-To: etc. and not just To: (BodyHtml-script): New rule. (FromReceived-Mismatch): Added extra check for JA_UBE_VALID_ADDR 2004-08-23 Mon Jari Aalto * pm-jasrv-daemon.rc: 2.5 Procmail 3.22 ':0 HB' bug fixes. * pm-janetmind.rc: 2.5 Procmail 3.22 ':0 HB' bug fixes. * pm-jaempty.rc: 2.6 Procmail 3.22 ':0 HB' bug fixes. * pm-jadaemon.rc: 2.6 Procmail 3.22 ':0 HB' bug fixes. * pm-jaube-keywords.rc: Use ${FORMAIL:-formail} (JA_UBE_KEYWORD_HEADER): Now includes defalt value 'X-Spam-JaubeKwd' * pm-jaube.rc: 2.15 Use ${FORMAIL:-formail} Procmail 3.22 ':0 HB' bug fixes. 2004-08-22 Sun Jari Aalto * pm-javac.rc (JA_VAC_ID_CACHE_SIZE): from_daemon => JA_FROM_DAEMON * pm-jasrv-daemon.rc (dummy): from_daemon => JA_FROM_DAEMON * pm-japing.rc (dummy): from_daemon => JA_FROM_DAEMON * pm-jafwd.rc (dummy): from_daemon => JA_FROM_DAEMON * pm-jacookie.rc. from_daemon => JA_FROM_DAEMON * pm-javar.rc Updated doocumentation a bit. Removed variables SPAMASSASSIN and BOGOFILTER. These programs are not installed by default in hosts. (TAB): New variable. (from_daemon): may clash user variables. Renamed to JA_FROM_DAEMON. Likewis FROM_DAEMON_MATCH => FROM_DAEMON_MATCH (from_mailer): may clash user variables. Renamed to JA_FROM_MAILER. Likewise from_mailer_match => FROM_MAILER_MATCH * pm-jaube-keywords.rc: (JA_UBE_KEYWORD_HEADER): New user variable. The results are recorded to a header if this variable is set. * pm-jaube.rc: 2.15 (JA_UBE_ATTACHMENT_ILLEGAL_KILL): New user option. Now the big base64 files can be removed so that mailbox does not get filled. (JA_UBE_LOG): Variable removed. It is no longer used. (JA_UBE_ATTACHMENT_SUSPECT_KILL): New user variable. (JA_UBE_ATTACHMENT_SUSPECT): New user variable. (BodyAttachment-Suspect): New rule. 2004-08-21 Sat Jari Aalto * pm-jaube-keywords.rc: (Body-Keywords): Removed all extra regexps and moved them to 'keywords'. * pm-jaube-prg-bmf.rc: 1.3 Serious problems with logic and calling formail. Fixed. * pm-jaube.rc: 2.15 (ERROR_STATUS): New variable. The message status: Good, Bad. (Marketing-Body): '.*' at the end puts too much text to the MATCH if message contains very long lines. Restricted it to few words. (JA_UBE_CAPS_OK_DEFAULT): Added more words. (BodyAttachment-IllegalType): New rule for audio messages. 2004-08-20 Fri Jari Aalto * pm-janslookup.rc: 2.8 Corrected 'answer:' regexp under Debian nslookup. * pm-javar.rc (RC_UBE_KEYWORDS): New variable. * pm-jaube-keywords.rc: New module. The most simplistic UBE filter. * pm-jaube.rc: 2.9 Added new topic 'Are you sure you want to use procmail for UBE?' to clarify why procmail really is not suitable for UBE detection. (JA_UBE_FROM_QUESTIONABLE): Added microsoft, yahoo. (PGPmessage): Renamed to jaubePGPmessage; so that it won't clash to user's variables. (Marketing-Body): Removed 'Games', 'cellular +phone', 'deal', 'tired'. They are too generic and may calse false hits. Removed 'iemmc.org|cyberpromo|answerme\.com\|savetrees\.com' => Matching individual sites is not productive. Might not even exist any more. (JA_UBE_MIME_CHARSET_ILLEGAL): New variable. New rules to match header and body. (Body: Attachment): Added new rule to detect pif|exe|com|bat|cmd (Marketing body): Rule cleaned a bit. Dangerous and general regexps that may match legimite mail were removed. (JA_UBE_MBOX): Variable removed. No messages are no longer stored anywhere. The status can be checked from variable ERROR and user can act according to it. (AddrInvalid-To): Added check for CC:, which is valid header too. (Marketing-Body): Made more strict: |(visit|Welcome|our).*Web ?site\ => |(visit|Welcome).*our.*Web ?site\ (JA_UBE_CAPS_OK): Added: DHCP, CVS ... (FromReceived-Mismatch): Removed other recipe, which was totally bogus. We can't test Received -> From, only From against Received headers. (AddrUbeLike): tightened regexp (NotEnoughHeaders): Added Delivered-To, Envelope-To (JA_UBE_FROM_QUESTIONABLE): Added missing @-sign to acchor host names. (jaubeHTML): New variable. If content is HTML do not run 'Marketing-CountBigLetterWords' check (JA_UBE_ATTACHMENT_ILLEGAL): New user variable. 2004-08-19 Thu Jari Aalto * pm-jaube-prg-bmf.rc: 1.1 New module. Interface to http://www.sf.net/projects/bmf - Bayesian Mail Filter program. 1.2 Adde prefix `jaubeBmf' to all variables so that module does not clash with other procmail scripts. * pm-jamime-save.rc: Typos corrected in documentation. Removed variable 'id' and used permanent tag 'pm-jamime-save.rc:' instead. (Required settings): updated. * pm-jamime.rc (dummy): Removed variable 'id' and used permanent tag 'pm-jamime.rc:' instead. 2004-08-17 Tue Jari Aalto * pm-jaube.rc: 2.9 Added new rule: HTML base64 is certainly UBE. 2004-08-16 Mon Jari Aalto * pm-jaube.rc: 2.9 Replaced variable 'id' with package name. The variable will not last if another recipe is called. (Check nslooup): If nslook up was ok, the ERROR variable was mistakenly left as 'no'. Now it is empty, as it is a return code of pm-jaube.rc * pm-janslookup.rc: 2.8 Replaced variable 'id' with package name. The variable will not last if another recipe is called. 2004-08-15 Jari Aalto * pm-javar.rc (SENDMAIL): Added SPAMASSASSIN, BOGOFILTER, FGREP. Added comment beside GREP. 2004-06-28 Mon Jari Aalto * pm-jalist.rc: 2.6 Moved postfix and prefix deletion rules above the list conversion rule: JA_LIST_MAKE_UNIQUE by request of 2004-04-27 Jari Aalto * pm-janslookup.rc (nslookup): Extra ')' removed from regexp. This fixes invalid regexp error. * pm-jaube.rc (JA_UBE_RC): This recipe is now self standing. External JA_UBE_RC file is no longer called. The ERROR is set if message was UBE. 2004-04-26 Jari Aalto * pm-jamime-kill.rc (Content-Type): Added image/jpeg and 'E' for recipes. 2004-04-26 Jari Aalto * pm-jamime-kill.rc (dummy): Check that MIME_BIN_QP contains value. * pm-jalist.rc (reply-to): Added to_addr ?? ()\/$abc+ Patch by Fred Yankowski to prevent recipe from crashing procmail on messages that are missing the To header and have only a blank value in the Reply-to header. 2004-04-01 Jari Aalto * pm-jacookie.rc: Removed JA_COOKIE_MBOX. User can take of this after the recipe has finished. * pm-jacookie1.rc (OUTPUT): Mistakenly read non existing variable RET, should have read OUTPUT to get CRC. 2003-08-20 Wed Jari Aalto * pm-jamime-save.rc: 2.2 The MIME header 'Content-Disposition: attachment; filename=file.txt' assumed that all were one line. Glenn Rice reported that it could be also divided after ';'. Now looks filename=file.txt from following line too. 2003-06-04 Wed Jari Aalto * pm-javar.rc: Added variable `$S'; Perl non-whitespace. 2003-03-30 Sun Jari Aalto * pm-jaube.rc: 2.2 Missing word start \< added to JA_UBE_CAPS_OK Fixed recipe `Marketing-CountBigLetterWords': The match was done in body although flag B was set on start line. Moved B ?? tests inside test statements (*). 2002-08-15 to Jari Aalto * pm-jadaemon.rc: 2.1 reported leaking daemon messages: Novel MTA. Added code to use Novel's X-Diagnostic header. 2001-08-03 Fri Jari Aalto * pm-jamime-decode.rc (SHELLMETAS = $jaMimeDecodeShellmetas): 2.0 Ralph SOBEK in Procmail-L 2000-01-10 noticed error that SHELLMETAS was not restored to correct value. Fixed. (FROM): 2.0 Added code by Ralph SOBEK to decode iso-8859 From: field (SUBJECT): 2.0 Added code by Ralph SOBEK to decode iso-8859 Subject: field 2000-12-19 Tue Jari Aalto * pm-javar.rc ${RM:-"mv"}): 1.2 Added. * pm-jamime-save.rc: 1.2 $MV is now configurable in pm-jvar.rc $contentEncoding) was not set, becaus the mime detection headers we in another order. How handles Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit and Content-Type: application/octet-stream; name="Ass_rake.dbf" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Ass_rake.dbf" 2000-01-04 Jari Aalto * pm-jaube.rc: Message "AddrBogus-To" changed to "AddrInvalid-To" * pm-jasubject.rc: It makes sense setting subject only if clean contains something in return: clean ?? [a-z] * pm-jalist.rc: ABC variable now contains = The :E was removed, because it restricted changing the order of recipes. All use LIST ?? ^^^^ check now and are independent of each others. List-Id detection added. X-Mailman detection added. X-Mailing-List recipe needed lot of rework. Moved recipes around int he module. Copyright updated. * pm-jaaddr.rc: Corrected COMMENT_PLUS ([+]*|--)\/.* --> (\++|--)\/.* that made procmail pre7 dump core procmail-lib-2009.1202/lib/Makefile000066400000000000000000000022201130547513300166070ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with program. If not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # # Visit ifneq (,) This makefile requires GNU Make. endif include ../common.mk INSTALL_OBJS = *.rc all: @echo "There is nothing to make. See INSTALL" install-procmail: # Rule install-procmail - install procmail files $(INSTALL_BIN) -d $(SHAREDIR) $(INSTALL_DATA) $(INSTALL_OBJS) $(SHAREDIR) install: install-procmail .PHONY: install-procmail # End of file procmail-lib-2009.1202/lib/pm-jaaddr.rc000066400000000000000000000252331130547513300173450ustar00rootroot00000000000000# pm-jaaddr.rc -- extract 'foo@some.com' email address from variable INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc extracts the various components of email address # from variable `INPUT'. You can do quite a lot interesting things with # your email address. One of the tricks that you could use if you # don't have sendmail plus addressing capabilities, is that you put # the additional infomation to the RFC comment. Eg. If you read and # followup to posts in usenet games groups, you could use: # # From: (John Doe+usenet.games) # # Or if your email address's localpart (that's characters before @) # already signify your First and surname, you don't need to repeat it # in comment. However, place special marker "+" to mark # additional information part for your procmail recipes: # # From: (+usenet.games) # # The use of RFC comment should work everywhere because RFC requires # that comments are preserved along with the address information. # If you would have sendmail plus addressing capabilities you would # have used: # # From: (John Doe) # # The idea is that the list infomation is readily available from # the email. The following recipe will derive the plus information # and use it directly as a mailbox where to drop the message. If # The Editor: Emacs, means anything to you, you can program it # to generate the appropriate From headers automatically when you # send mail from Gnus Mail/Newsreader MUA. Drop me a message if # you need an example how a piece of Emacs lisp code makes those # magic RFC plus addresses in the background while you compose the # body of the message. # # RC_EMAIL = $PMSRC/pm-jaaddr.rc # TOME = "(login1|login2)" # # :0 # *$ ^TO\/.*$TOME.* # { # INPUT = $MATCH # INCLUDERC = $RC_EMAIL # PLUS = $COMMENT_PLUS # # # If COMMENT_PLUS was defined, we found "+" # # address which contain "usenet.games". Save it to # # folder. # # :0 : # * PLUS ?? [a-z] # $PLUS # } # # Notes # # 1998-05 David Hunt also mentioned that "you need to # remember that some MTAs, (qmail for one, and soon vmail) use a dash # ( - ) as the subaddress delimiter. So you'll want to allow for that # in your code". For this reason the email part accepts both # "-" and "+". The RFC comment however accepts only "+" and "--". # # Example input # # "From: foo+procmail@this.site.com (Mr. foo)" traditional # "From: foo-procmail@this.site.com (Mr. foo)" new styled # # NOTE: M$SOFT mailers tend to send idiotic smart quotes "'Mr. foo'" # and this recipe ignores these two quotes ["'] as if message had # only the standard ["] # # Returned values # # ADDRESS "foo+procmail@this.site.com" # containing the email address without <> # # ACCOUNT "foo+procmail" # all characters before @ # # ACCOUNT1 "foo" # characters before plus: account1+account2@site # Note, if there is no "+", this is same as ACCOUNT. # # ACCOUNT2 "procmail" # _only_ set if plus found: account1+account2@site # # SITE "this.site.com" # all characters after @ # # DOMAIN "site.com" # the main domain, preceding words in site are # considered subdomain (local) addresses. # # sub.sub.domain.net # # SUB "this.site" # all the sub-domain names without the NET part. # # SUB1 "site" # The first subdomain counted from the _RIGHT_ after NET # # SUB2 "this" # Second subdomain. # # SUB3 "" # Third subdomain. # # SUB4 "" # Fourth subdomain. # # NET "com" # last characters after last period ( net,com,edu ...) # # COMMENT Anything unside parenthesis (Mr. Foo) or if no # parentheses found, then anything between quotes # "Mr. Foo" # # COMMENT_PLUS Anything after the "+" in the comment, like # "Mr Foo+mail.usenet" --> "mail.usenet" # # Note: some MTA's don't allow + character, so use # alternatively '--': # "Mr Foo--mail.usenet" --> "mail.usenet" # # Additionally there is variables DOT1 DOT2, which behave like # ACCOUNT1 and ACCOUNT2, but in respect to dotted firstname.surname # type address: # # john.doe@site.com # # ACCOUNT1 = john.doe # ACCOUNT2 = # DOT1 = john # DOT2 = doe # # If there is plus, the ACCOUNT2 is defined # # john.doe+foo@site.com # # ACCOUNT1 = john.doe # ACCOUNT2 = foo # DOT1 = john (in respect to ACCOUNT1) # DOT2 = doe (in respect to ACCOUNT1) # # # Variable ERROR is set to "yes" if INPUT wasn't recognized or parsing # the address failed. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. # # Call arguments (variables to set before calling) # # INPUT = string-to-parse # # Usage example # # Read From field and address from it. This is lot faster than using # external `formail' call. # # PMSRC = $HOME/pm # RC_ADDR = $PMSRC/pm-jaaddr.rc # # :0 # * ^From:\/.*@.* # { # INPUT = $MATCH # # # Turn off the logging while executing this part # VERBOSE="off" INCLUDERC = $RC_ADDR VERBOSE="on" # # :0 # * ERROR ?? yes # { # # Hmm, no std email address found. Any other ideas? # } # } # # Change Log (none) # .................................................... &initialising ... id = " pm-jaaddr.rc" dummy = " ====================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables. Defining them on their own kills them ADDRESS ACCOUNT ACCOUNT1 ACCOUNT2 DOT1 DOT2 SITE DOMAIN SUB1 SUB2 SUB3 SUB4 NET COMMENT COMMENT_PLUS ERROR = "yes" # set defualt value # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 dummy = "$NL$NL$id: start: Parsing $INPUT $NL" charset_jaaddr = "[^$WSPC@(){}&?,;:<>\"']+" # ... ... ... ... ... ... ... ... ... ... ... ... ... . catch comment ... dummy = "$NL$id: :::::::::::::::::::::::: COMMENT $NL" :0 # Catch anything inside parentheses * INPUT ?? [(]()\/[^)]+ { COMMENT = $MATCH } :0 E # Else, Try catching "'Mr. Foo'" in Microsoft smart quotes * INPUT ?? \"'()\/[^\']+ { dummy = "$id: Comment catched from inside Microsoft smart quetes.." COMMENT = $MATCH } dummy = "$NL$id: normal quotes $NL " :0 E # Else, Try catching "Mr. Foo" in quotes * INPUT ?? \"()\/[^\"]+ { dummy = "$id: Comment catched from double quotes.." COMMENT = $MATCH } dummy = "$NL$id: :::::::::::::::::::::::: COMMENT_PLUS $NL" :0 # derive plus address, if RFC comment trick * COMMENT ?? (\++|--)\/.* { COMMENT_PLUS = $MATCH } # ... ... ... ... ... ... ... ... ... ... ... ... ... catch address .. dummy = " $NL$id: Find $NL " # Try strict address first <> :0 *$ INPUT ?? $s*<\/$charset_jaaddr@$charset_jaaddr> { INPUT = $MATCH # Drop the trailing ">" too # :0 *$ INPUT ?? ^\/$charset_jaaddr@$charset_jaaddr { ADDRESS = $MATCH } } dummy = "$NL$id: :::::::::::::::::::::::: INPUT --> ADDRESS [$INPUT] $NL" # No joy, then try to locate @ character :0 E *$ INPUT ?? $s*\/$charset_jaaddr@$charset_jaaddr { ADDRESS = $MATCH } # ... ... ... ... ... ... ... ... ... ... ... ... ... ... .. explode .. # If we got the address, derive other parts dummy = "$NL$id: :::::::::::::::::::::::: ADDRESS [$ADDRESS] $NL" :0 * ADDRESS ?? @\/.* { SITE = $MATCH :0 # Get last three characters * SITE ?? (\.)\/...^^ { NET = $MATCH } :0 E # Nope, it was two (like .us) * SITE ?? \.\/..^^ { NET = $MATCH } # If next recipe does not match, ie. there is no two components in # the address. Eg: # # foo@a.b.com -> DOMAIN = b.com # foo@this.com -> DOMAIN = this.com DOMAIN = $SITE :0 *$ SITE ?? (\.)\/[^.]+\.$NET { DOMAIN = $MATCH } # It's a bit tricky to count backward with procmail, but in this # case it it possible, because there is "." separating the parts. # # this.site.here.com : Get everything until period, delete period # -> SUB this.site.here # # Next; we repeate following 3 times # # this.site.here : get everything until period, delete period # -> this.site : save this to `tmp' # # If there is no matches, reset `tmp' to empty to prevent next recipes to # match. If there is no more matches, the ":0 E" recipe assigns the last # # --> this : into last SUB :0 * SITE ?? ()\/.*\. * MATCH ?? ()\/.*[^.] { SUB = $MATCH SUB1 = $SUB # suppose only one subdomain. @this.com tmp = "" :0 * SUB ?? .*\.\/[^.]+^^ { SUB1 = $MATCH } tmp :0 * SUB ?? ()\/.*\. * MATCH ?? ()\/.*[^.] { tmp = $MATCH :0 * tmp ?? .*\.\/[^.]+^^ { SUB2 = $MATCH } :0 E { SUB2 = $tmp tmp = "" } } :0 * tmp ?? ()\/.*\. * MATCH ?? ()\/.*[^.] { tmp = $MATCH :0 * tmp ?? .*\.\/[^.]+^^ { SUB3 = $MATCH } :0 E { SUB3 = $tmp tmp = "" } } :0 * tmp ?? ()\/.*\. * MATCH ?? ()\/.*[^.] { tmp = $MATCH :0 * tmp ?? .*\.\/[^.]+^^ { SUB4 = $MATCH } :0 E { SUB4 = $tmp tmp = "" } } } :0 * ADDRESS ?? ^^\/[^@]+ { ACCOUNT = $MATCH # Handle plus addresses and explode it :0 * ACCOUNT ?? [-+]\/.* { ACCOUNT2 = $MATCH } :0 * ACCOUNT ?? ()\/[^+]+ { ACCOUNT1 = $MATCH } # Handle firstname.surname :0 * ACCOUNT1 ?? [.]\/.* { DOT2 = $MATCH } :0 * ! DOT2 ?? ^^^^ * ACCOUNT1 ?? ()\/[^.]+ { DOT1 = $MATCH } } } dummy = "$NL$NL$id: end: $ERROR $NL" # end of file pm-jaaddr.rc procmail-lib-2009.1202/lib/pm-jabup.rc000066400000000000000000000113751130547513300172230ustar00rootroot00000000000000# pm-jabup.rc -- Keeep N arriving message backup in separate directory # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details # . # # Description # # Preserve last N arriving messages in a separate sub-directory. # This should be your safety-belt recipe that you put to the beginning # of your .procmailrc. # # Procmail saves the backup files with names like: msg.rcG msg.scG # msg.3YS1, msg.4YS1, msg.VYS1, msg.fYS1 to the backup directory. # # Note: this recipe will alawys call shell commands for each message # you recive. That is needed because cleaning of the backup directory. # If you receive only small number of messages per day, the performance # drop of your .procmailrc is not crucial. But if you store many messages # per day, then the shell calls may be a performance problem. # # In that case, consider moving the cleanup to the pm-jacron.rc # module (The cleanup is run only once a day, not for every message) # # John Gianni send his simple bsckup script to Jari, who packaged # and generalized the code. The code is reused with John's permission # and maintaining responsibility was transferred to Jari # # Required settings # # (none) # # Call arguments (variables to set before calling) # # o JA_BUP_MAX, How many messages to keep at maximum. 32 is default # o JA_BUP_DIR, Where to store the messages. $HOME/Mail/bup by default # o JA_BUP_FILES, regexp to match the saved files. Procmail default. # o JA_BUP_CHECK_DIR. Once you have verified that this recipe works, # that directories are ok, please set this flag to "no" to prevent # running unnecessary `test' command for each email. # # Usage example # # You only want to keep backup of messages that are not from mailing # lists. You may want to use TO_ macro to detect addresses better, # this example matches against all headers # # LISTS = "(procmail|list-1|list-2)" # JA_BUP_DIR = $HOME/Mail/backup/. # Create the path too # JA_BUP_MAX = 42 # this should be enough # # :0 # *$ ! $LISTS # { # INCLUDERC = $PMSRC/pm-jabup.rc # } # # If you get many messages, please don't use this module. Instead # see pm-jacron.rc where similar backup work is done better. # # Change Log (none) # .................................................... &initialising ... id = " pm-jabup.rc" dummy = "subroutine: $id start" # .......................................................... &public ... default = "$HOME/Mail/bup" JA_BUP_DIR = ${JA_BUP_DIR:-$default} JA_BUP_MAX = ${JA_BUP_MAX:-32} JA_BUP_FILES = ${JA_BUP_FILES:-"msg.*"} JA_BUP_CHECK_DIR = $JA_BUP_CHECK_DIR:-"yes"} # ........................................................... &check ... :0 * JA_BUP_CHECK_DIR ?? yes { # - If we're using the default directory, check that it exists. # - Create one if needed and exit if create was unsuccessfull :0 *$ JA_BUP_DIR ?? $default *$ ! ? $IS_DIR $default || $MKDIR $default { EXITCODE = 217 # just some code, doesn't mean anything HOST # stop immediately } :0 *$ ! ? $IS_DIR $JA_BUP_DIR { dummy = "$id: $JA_MSG_ERROR $JA_BUP_DIR is not a directory" EXITCODE = 217 HOST } } # ........................................................... &do-it ... dummy = "subroutine: pm-jabup.rc delivering backup." :0 c: $JA_BUP_DIR # i = ignore write errors # # - The 'rm -f dummy' makes sure that rm always has at least one argument, # because there may not be files in the directory. # - 'ls -t' returns files sorted by date, newest first # - 'sed' just chops first N files from the ls listing, leaving list # of old files # # NOTE # # - If you get lot of mail, it is too expensive to run this after # every message. Plese use cron(1) or pm-jacron.rc module to run something # only once a day. :0 hwic | cd $JA_BUP_DIR \ && $RM -f dummy `$LS_BY_DATE $JA_BUP_FILES | $SED -e 1,${JA_BUP_MAX}d` dummy = "subroutine: $id end." # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-jacookie.rc000066400000000000000000000357611130547513300177130ustar00rootroot00000000000000# pm-jacookie.rc -- Handle cookie (unique id) confirmations # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with program. If not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # # Visit # # Overview of features # # o Each user must register himself to cookie cache before he # is considered "known" # o Unless user return the generated cookie string; which is # typically a decimal or hex number, he is not considered as # known and should not have access to services you provide. # o Can be used as a "doorbell" spam/UBE shield # # Description # # This recipe handles generating the cookie to new users, comparing # the returned cookie against the original one and passing known # users through if they already had returned their cookie. # # When you run automatised scripts, eg. to manage mailing lists # where users can subscribe and unsubscribe, you have better to # install safety measure so that someone can not subscribe his enemy # to 30 mailing lists. # # The *cookie* is any continuous block of random characters that # is sent to person who wanted to use the service. He must send # back the *cookie* before the service starts an action, like # subscribe. If someone forges the From address to pretend to be # someone else and then subscribes as-beeing-someone-else to a # mailing list, the cookie protects this from happening. # # The cookie is sent to someone-else, and he must return the cookie # before the "subscribe" service is activated. Obviously this # someone-else will not be interested in sending back the cookie and # thus the forgery fails. Isn't that simple, but efective protection # against misuse? # # Should I use this as Challenge-Response Spam shield? # # Unsolicited Bulk Email aka Spam is crawling from every possible # domain thinkable, so you might think that a challenge-response # policy could be deployed to regular email communication as well. # The idea would be that unknown people are requested to # "join" to a white list, before discussion is initiated with them. # Bulk email shotguns do not reply to challenges (here: cookies), # so confirmations are not returned. Individual people that want to # talk, *may* want to return the cookies. # # Sounds like a perfect Unsolicited Bulk Email shield? No more # non-invited mail? Wrong. Don't use this module for that. The # whole idea of challenge-response is flawed and causes trouble # for every person who tries to contact. Imagine for 10 people # using C-R systems; they would all need to authenticate # themselves. Who is going to believe that he is not replying to # a spammer who is collecting email addresses? And what about # automatic messages that might be received -- there is no # artificial intelligence to deparate "human" messages from # automatically generated messages, so challenges just # increase the overall mail traffic. Every C-R system doubles # the mail traffic and becomes spam problem by itself. # # In short, don't use this module for implementing a C-R system # to block regular mail to you. # # How it works # # By default the cookie generated uses CRC 32 `cksum', but if you have # md5, you should use it. The cookie is generated from the reply # address and immediately stored to cookie database file with entry # # DATE FROM-a COOKIE-a # DATE FROM-b COOKIE-b # # If this was a new user or an old user, who has not registered his # cookie yet, then original message is sent back to the sender with # instructions: "please place the magic string to Subject line and # resent the message." # # When cookie is returned back, a new line to the database is added, # simply by adding a duplicate entry. The file now looks like this: # # DATE FROM-a COOKIE-a # DATE FROM-b COOKIE-b # DATE FROM-a COOKIE-a # # When there is two or more same entries, like FROM-a, the address # is supposed to be known and person behind it "cleared". # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jadate.rc # o pm-jacookie1.rc # o pm-jastore.rc # # Call arguments (variables to set before calling) # # o JA_COOKIE_SEND, flag. Default is "yes". Set to "no" if you want # to take full control of the message returned to user. You can check # variable `ERROR' and use `key' which holds the unique `cookie' # o JA_COOKIE_CACHE, cache to determine if this is new user or not. # o JA_COOKIE_AUTO_KEY, flag. If set to "yes"; the cookie is # initially put to the Subject when the message is bounched back. # Receiver only has to press "r" to reply to send the cookie # and message back (convenient). You set this flag to "no" when # you want to avoid accidnebts eg. when receiver is about to # subscribe to a mailing lists: he has to manually insert the cookie # into subject. But keep flag to "yes" if you use this module to # get your friends registered easily. # o JA_COOKIE_KEYS, the cookie database. Email address and person's # access cookie. # o JA_COOKIE_RC, dubroutine to generate the cookie id from INPUT. # By default uses CRC 32. # o JA_COOKIE, the string from which the cookie will be generated. # If you already have the return addres for the sender derived, # you should assing a value to this to save unnecessary formail call. # # Returned values # # ERROR will contain the efective action when this recipe file ends # # o "new-user", This is first message from sender. # o "known-user", message has email that has been "cleared" ie. # cookie had been returned and user registered. # o "key-mismatch", This is at least second message from sender. # But he dind't send the confirmation in this message. # # `key' is an internal variable in this recipe file and will hold the # cookie id in case of "new-user" and "key-mismatch". You may want to # use it if you generate your own reply. # # Example usage for UBE shield # # This is what I use to prevent unknown people from sending me UBE. # It takes a bit extra, but they can easily return the message. # Fill in the missing variables, this won't work out of the box for you. # # WORK = "(domain1|domain2|domain3)" # LISTS = "(procmail|list-2|list-3|list-4)" # VALID = "(postmaster|abuse|$LISTS|$WORK)" # RC_COOKIE = $PMSRC/pm-jacookie.rc # UBE_SPOOL = $HOME/Mail/junk.ube.spool # Save spam here # # :0 # *$ ! From:.*$VALID # *$ ! ^FROM_DAEMON # { # JA_COOKIE_SEND = "yes" # Activate it # INCLUDERC = $RC_COOKIE # # :0 : # * ! ERROR ?? known-user # $UBE_SPOOL # # # ... Past this point: it was user in whitelist, so the # # recipes after this block will take care of it # } # # Example usage for subscriptions # # $RC_COOKIE = $PMSRC/pm-jacookie.rc # # ...Mailing lists handled here... # ...Your work messages filed here.. # # TO = `formail -rt -zxTo:` # We need this elswhere # JA_COOKIE_TO = $TO # # # For List-X all subscribe requests must # # be confirmaed # # * ^TO_()list-x # * ^Subject: +subscribe\> # { # JA_COOKIE_SEND = "no" # INCLUDERC = $RC_COOKIE # # :0 # * ERROR ?? known-user # { # # User sent the subsribe request again, allow joining # # immediately. # } # :0 E # { # # Because the Send was set to "no"; we're in charge # # to send a reply to the user. # # ...generate suitable message with formail -rt # } # # } # # # End of example # # Change Log: (none) # ............................................................ &init ... dummy = " ====================================================================== pm-jacookie.rc: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } :0 *$ ! YYYY ?? ^^$d$d$d$d^^ { INCLUDERC = $PMSRC/pm-jadate.rc } JA_COOKIE_SEND = ${JA_COOKIE_SEND:-"yes"} JA_COOKIE_AUTO_KEY = ${JA_COOKIE_AUTO_KEY:-"yes"} JA_COOKIE_CACHE = ${JA_COOKIE_CACHE:-$HOME/.cookie-cache-new-user} JA_COOKIE_CACHE_SIZE = ${JA_COOKIE_CACHE_SIZE:-8192} JA_COOKIE_KEYS = ${JA_COOKIE_KEYS:-$HOME/.cookie-cache-keys} JA_COOKIE_WHITELIST = ${JA_COOKIE_WHITELIST:-$HOME/.cookie-cache-whitelist} JA_COOKIE_RC = ${JA_COOKIE_RC:-$PMSRC/pm-jacookie1.rc} JA_COOKIE_XLOOP = ${JA_COOKIE_XLOOP:-"\ Procmail Authentication service (PAS)"} JA_COOKIE_SUBJECT_TAG= ${JA_COOKIE_SUBJECT_TAG:-"PAS-cookie-"} JA_COOKIE_HEADER = ${JA_COOKIE_HEADER:-"X-PAS-Auth-Key:"} cookie = "" JA_COOKIE_MSG = ${JA_COOKIE_MSG:-"\ Your message need to be authenticated. Include the authentication key at the end of Subject header and resend your message."} # - If not set, set the variable. We use `r' instead of `rt' # because of `-rD' later. # - User can preset the JA_COOKIE to his liking if the "to" field's # string is not enough to generate a unique cookie from it. JA_COOKIE_FROM = ${JA_COOKIE_FROM:-`$FORMAIL -r -zxTo:`} # - Should non-authenticated messages be saved? Change this # to mailbox name as needed. JA_COOKIE_DEVNULL = ${JA_COOKIE_DEVNULL:-/dev/null} # ..................................................... &read-cookie ... jaCookieData = "" jaCookieKey = "" :0 *$ $SUPREME^0 H ?? ^Subject:()\/.* +$JA_COOKIE_SUBJECT_TAG[0-9]+ *$ $SUPREME^0 B ?? ^Subject:()\/.* +$JA_COOKIE_SUBJECT_TAG[0-9]+ { jaCookieSubject = $MATCH :0 * ^FROM_DAEMON { # The sender is not there, drop this message :0 h * JA_COOKIE_DEVNULL ?? /dev $JA_COOKIE_DEVNULL # For mailbox, use lock :0 : $JA_COOKIE_DEVNULL } :0 *$ jaCookieSubject ?? $JA_COOKIE_SUBJECT_TAG\/[0-9]+ { jaCookieData = $MATCH } # Remove cookie from subject :0 *$ jaCookieSubject ?? ^()\/.* +$JA_COOKIE_SUBJECT_TAG *$ MATCH ?? ^()\/.*[ ] *$ MATCH ?? ^()\/.*[^ ] { jaCookieSubject = $MATCH } } # No cookie was in the subject :0 E * ^Subject: \/.* { jaCookieSubject = $MATCH } # ....................................................... &whitelist ... # Is this user in whitelist already? ERROR = "" jaCookieWhitelist = "" :0 * jaCookieData ?? ^^^^ * ? $GREP '\<$JA_COOKIE_FROM\>' $JA_COOKIE_WHITELIST { jaCookieWhitelist = "yes" ERROR = "known-user" } # ........................................................... &do-it ... jaCookieNewUser = "yes" jaCookieDate = $YYYY-$MM-$DD # - Mail arrived, check cache. Use regional lock because formail # is in the condition line. # - If user was there already, formail returns success # - Options -rD cause adding the email to the cache. LOCKFILE = ${JA_COOKIE_CACHE}.lock dummy = "pm-jacookie.rc: Testing new user" :0 * jaCookieWhitelist ?? ^^^^ * ? $FORMAIL -rD $JA_COOKIE_CACHE_SIZE $JA_COOKIE_CACHE { jaCookieNewUser = "no" } LOCKFILE mail = "" # He is not in whitelist (ERROR="") and he did not return # the cookie (cookie="") dummy ="pm-jacookie.rc: Check if white [$jaCookieWhitelist] ERROR [$ERROR] cookie [$cookie]" :0 * jaCookieWhitelist ?? ^^^^ * jaCookieNewUser ?? no { dummy = "pm-jacookie.rc: Old user, did he return a cookie [$jaCookieData]" :0 * jaCookieData ?? [0-9] { # This user has returned confirmation. Check that it is correct dummy = "pm-jacookie.rc: confirming the cookie" :0 *$ ? $GREP ".*$JA_COOKIE_FROM.+$jaCookieData" $JA_COOKIE_KEYS { dummy = "pm-jacookie.rc: Adding to whitelist" msg = "$JA_COOKIE_FROM" :0 hwc : $JA_COOKIE_WHITELIST$LOCKEXT | echo "$msg" >> $JA_COOKIE_WHITELIST ERROR = "known-user" } :0 E { # Ask to send again ERROR = "cookie-error" jaCookieKey = $jaCookieData jaCookieMail = "yes" } } :0 E { dummy = "pm-jacookie.rc: Unknown user. Generate new key" jaCookieNewUser = "yes" } } :0 * jaCookieNewUser ?? yes { saved = $ERROR INPUT = $JA_COOKIE_FROM INCLUDERC = $JA_COOKIE_RC jaCookieKey = $OUTPUT ERROR = $saved # restore value that got changed in subroutine jaCookieMail = "yes" jaCookieMsg = "$jaCookieDate $JA_COOKIE_FROM $jaCookieKey" dummy = `echo "$jaCookieMsg" >> $JA_COOKIE_KEYS` } dummy = "pm-jacookie.rc: If new user/mismatched key, maybe send mail [$jaCookieMail]" :0 * jaCookieMail ?? yes * jaCookieWhitelist ?? ^^^^ * JA_COOKIE_SEND ?? yes * ! jaCookieKey ?? ^^^^ *$ ! ^X-Loop:.*$JA_COOKIE_XLOOP *$ ! $JA_FROM_DAEMON { dummy = "pm-jacookie.rc: Request authentication $JA_COOKIE_FROM" # - If auto-mode is "on"; then put the key in the subject # - Sender only has to reply to message. jaCookieKey = "$JA_COOKIE_SUBJECT_TAG$jaCookieKey" :0 fhw * JA_COOKIE_AUTO_KEY ?? yes | $FORMAIL -I "Subject: $jaCookieSubject $jaCookieKey" # Add extra header as well to message that go past the next one :0 fhw | $FORMAIL -A "$JA_COOKIE_HEADER $jaCookieKey" :0 hbw c: $JA_COOKIE_CACHE$LOCKEXT | ( $FORMAIL -rk -b \ -A "X-Loop: $JA_COOKIE_XLOOP"; \ echo "You Authentication key is: $jaCookieKey"; \ echo "$JA_COOKIE_MSG"; \ ) | $SENDMAIL $SENDMAIL_FLAGS } dummy = "pm-jacookie.rc: end: $ERROR" # pm-store.rc ends here procmail-lib-2009.1202/lib/pm-jacookie1.rc000066400000000000000000000042271130547513300177650ustar00rootroot00000000000000# pm-jacookie1.rc -- Generate unique id from INPUT variable. # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # When given a string, this subroutine returns a unique number # representing a string, a cookie. # # Required settings # # (none) # # Call arguments (variables to set before calling) # # o INPUT, String from which the magic-cookie is calculated # o JA_COOKIE_CMD: shell command to read INPUT and return decimal # or hex cookie string as one continuous block of characters. # It decaults to HP-UX `cksum', but your system may have `md5' # or `chksum' # # Return values # # o Variable OUTPUT will contain the cookie. # # Example usage # # INPUT = "foo@site.com" # JA_COOKIE_CMD = "md5" # or chksum # INCLUDERC = $PMSRC/pm-jacookie1.rc # cookie = $OUTPUT # # Change Log: (none) id = "pm-jacookie1.rc" dummy = " ====================================================================== $id: init: " # ........................................................... &input ... # This is standard CRC 32 JA_COOKIE_CMD = ${JA_COOKIE_CMD:-"cksum"} # ........................................................... &do-it ... # Generate new key for this new user OUTPUT = `echo $INPUT | $JA_COOKIE_CMD` # - At least HP-UX cksum produces two values: CRC DATA-LEN # - We're only interested in the CRC part # :0 * OUTPUT ?? ^^\/[0-9a-f]+ { OUTPUT = $MATCH } dummy = "$id: end:" # pm-store.rc ends here procmail-lib-2009.1202/lib/pm-jacron.rc000066400000000000000000000134571130547513300174010ustar00rootroot00000000000000# pm-jacron.rc -- Procmail: Run cron once a day # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # # # Description # # Framework for all cron tasks that can be run once a day. # This is a wrapper recipe to your cron task list: when the day changes, # you cron includerc is called. # # Required settings # # PMSRC must point to source directory of procmail code. This recipe # will include # # o pm-javar.rc # o pm-jadate.rc # # Call arguments (variables to set before calling) # # o JA_CRON_RUN_FLAG, You _must_ define this flag file. # o JA_CRON_DATE_FILE, File where the date information, last cron run, # is kept. Defaults to $HOME/.yymmdd # o JA_CRON_RC, your includerc which is run when cron triggers. # # A file `JA_CRON_RUN_FLAG' which defaults to ~/.yymmdd.run is created # when your includerc, that contains list of cron tasks, is run. If new # mail arrives while your cron recipes are still running, you should # prevent invoking the cron again by checking if this file exists. # When all the cron tasks have been run, this flag file is removed. # Remember to use "w" flag in your cron recipes where necessary # to serialize the work. # # Return values # # (none) # # Usage example # # Save backups to separate directory, but do cleaning only once a day # We do not keep backups from mailing list messages # # LISTS = "(procmail|list-1|list-2)" # BACKUP_DIR = "$HOME/Mail/backup/." # # # Store backups: separate files to directory # # :0 c: # *$ ! $LISTS # $BACKUP_DIR # # # Run JA_CRON_RC once a day. It contains all daily cron tasks # # CRON_RC = $PMSRC/pm-jacron.rc # the framework # JA_CRON_RC = $PMSRC/pm-mycron.rc # the tasks to do # JA_CRON_RUN_FLAG = $HOME/.cron-running # define this! # # # Do not enter here if message arrived at the same day when # # the cron is already running. The CRON_RC takes care # # of deleting the file when cron has finished. # # :0 # *$ ! ? $IS_EXIST $JA_CRON_RUN_FLAG # { # INCLUDERC = $CRON_RC # } # # The *pm-jacron.rc* file may contain anything. For example to clean # the backup directory; you add these statements there # # # rm dummy: if ls doesn't return files, make sure rm has # # at least one argument. # # # # ls -t: list files; newest first # # # # sed: chop $max newest files from the listing, leaving the # # old ones # # max = 32 # # :0 hwic # | cd $BACKUP_DIR && $RM -f dummy `ls -t msg.* | $SED -e 1,${max}d` # # # End of file pm-mycron.rc # # Change log (none) # ............................................................ &init ... id = "pm-jacron.rc" dummy = " ======================================================================== $id: init: " # .......................................................... &public ... JA_CRON_DATE_FILE = ${JA_CRON_DATE_FILE:-$HOME/.yymmdd} JA_CRON_RC = ${JA_CRON_RC:-""} JA_CRON_RUN_FLAG = ${JA_CRON_RUN_FLAG:-${JA_CRON_DATE_FILE}.cron-running} # ........................................................ &settings ... :0 *$ ! ? $IS_EXIST $JA_CRON_RUN_FLAG { :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } dummy = "$id: Define date variables if not yet set" :0 *$ ! YYYY ?? ^^[0-9]+^^ { INCLUDERC = $PMSRC/pm-jadate.rc } error = "no" :0 *$ ! YYYY ?? ^^[0-9]+^^ { error = "$id: $JA_MSG_ERROR_FATAL Loading of pm-jadate.rc failed." } # ......................................................... &private ... yymmdd = $YYYY-$MM-$DD # ISO 18 # Create initial .yymmdd file if it doesn't exist. :0 *$ ! ? $IS_EXIST $JA_CRON_DATE_FILE * error ?? no { :0 hwic: $JA_CRON_DATE_FILE$LOCKEXT | echo $yymmdd > $JA_CRON_DATE_FILE } # Read previously saved value yymmdd_prev = "" :0 hwic * error ?? no yymmdd_prev=| $CAT $JA_CRON_DATE_FILE # ............................................................ do-it ... dummy = "$id: test if it is time to run cron?" # - If RC file is defined # - if different date then enter this block # - If cron flag is not up: another procmail instance is not # already running this cron recipe. :0 *$ JA_CRON_RC ?? [a-z] *$ ! yymmdd ?? ^^$yymmdd_prev^^ * error ?? no *$ ! ? $IS_EXIST $JA_CRON_RUN_FLAG { dummy = "$id: CRON-TRIGGERED" # Update timestamp to tell that we're running cron job now. :0 hwic: $JA_CRON_DATE_FILE$LOCKEXT | echo $yymmdd > $JA_CRON_DATE_FILE :0 hwic | $TOUCH $JA_CRON_RUN_FLAG INCLUDERC = $JA_CRON_RC # The user's task list for this day # Free the cron flag. Cron ended :0 hwic *$ ? $IS_EXIST $JA_CRON_RUN_FLAG | $RM -f $JA_CRON_RUN_FLAG } } dummy = "$id: end:" # end of file procmail-lib-2009.1202/lib/pm-jadaemon.rc000066400000000000000000000277561130547513300177120ustar00rootroot00000000000000# pm-jadaemon.rc -- Handle DAEMON messages by changing subject # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # When you send a message to a address that had delivery troubles, # you get a DAEMON message back explaining the error problem. I # usually want to save these daemon mesaages to a different folder # and check the folder from time to time. A typical daemon message # is like this (shortened) # # From: Mail Delivery Subsystem # Subject: Warning: could not send message for past 4 hours # # The original message was received at... # ----- Transcript of session follows ----- # Deferred: Connection timed out # ----- Original message follows ----- # [YOUR MESSAGE AS YOU SENT IT WITH HEADERS] # # Well, when I read the subjects, I do not like the standard error # messages, but I also like to know to which address the delivery # failed and what was the original subject. This small recipe changes # the daemon message's Subject to # # Subject BRIEF-ERROR-REASON, SENT-TO-ADDRESS, ORIGINAL-SUBJECT # # and from that you can immediately tell if you should be worried Eg. # if SENT-TO-ADDRESS was your friend's, then you want to take actions # immediately, but if it were your complaint to UBE message to # postmaster, you don't want to bother reading that daemon message. # Here are some real examples: # # fatal errors,postmaster,ABUSE (Was: Super Cool Site!) # Host unknown,postmaster,ABUSE (Was: A-Credit Information) # undeliverable,postmaster,Could you investigate this spam # Warning-Returned,friend,Have you looked at this # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # needs scrips # # o pm-javar.rc # # Call arguments (variables to set before calling) # # o `JA_DAEMON_SAVE'. This is by default `yes' which causes the # original subject to be saved under header field `X-Old-Daemon-Subject'. # If you don't want that extra header generated, set this variable to `no' # o `JA_DAEMON_REGEXP', which messages to trigger # # Return values # # o Variable ERROR will be set to "yes" if daemon message was handled # otherwise; value is "no" # # Usage example # # Just add this recipe somewhere in your .procmailrc. The place where # you would put this daemon message trapper subroutine is crucial: # think carefylly how you order your recipes. One suggested order # could be: backup important messages, cron-subroutine, # handle duplicates, DAEMON MESSAGES, plus addressed message, # server message (file server, ping responder...), MAILING LISTS, # send possible vacation replies only after all above, apply # kill file, detect mime, save private messages and las FILTER UBE. # # # PMSRC = $HOME/pm # RC_DAEMON = $PMSRC/pm-jadaemon.rc # DAEMON_MBOX = $HOME/Mail/junk.daemon.mbox # # ... # # INCLUDERC = $RC_DAEMON # # :0 : # If that was a daemon message, save it # * ERROR ?? yes # $DAEMON_MBOX # # Change Log: (none) dummy = " ======================================================================== pm-jadaemon.rc: init:" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # ........................................................... &input ... JA_DAEMON_SAVE = ${JA_DAEMON_SAVE:-"yes"} # ----- The following addresses had permanent fatal errors ----- # # # ----- Transcript of session follows ----- # ... while talking to 168.231.153.98: # 550 5.1.2 ... Host unknown (Name server: host not found) # <<< 501 healy!me@example.com... Refused # # ----- The following addresses had transient non-fatal errors ----- # # <<< 550 5.1.1 unknown or illegal alias: email.jdoe@example.com # 550 ... User unknown JA_DAEMON_REGEXP = ${JA_DAEMON_REGEXP:-"\ ^From.*(MAILER-DAEMON|abuse@|postmaster@|daemon@)\ |(Transcript of session follows\ |permanent fatal errors\ |MAILBOX NOT FOUND\ |Invalid recipient\ |Service unavailable\ |Message is too large\ |550.*User unknown\ |550.*illegal alias\ |message was not delivered\ |blocked using.*spamcop\ |quota exceed\ |501.*refused\ |Domain blacklisted\ |transient non-fatal errors\ |user.*doesn't exist\ |Deferred: Connection timed out\ )\ " # ......................................................... &output ... ERROR = "no" # ........................................................... &do-it ... errTo = "" charset = "[^ @(){}<>]" daemon = ! # Novell Mercury MTA send Broken message headers, The "From " is all wrong. # # From mmokrejs Wed Aug 14 16:48:53 2002 # Received: from SpoolDir by OKBDELL (Mercury 1.44); 14 Aug 02 16:33:29 +0100 (MET) # 14 Aug 02 16:33:51 +0100 (MET) # From: Mail Delivery System # Subject: Delivery failure notification # Message-ID: <5C4D0D00E16@mustela.lfmotol.cuni.cz> # X-Diagnostic: Possible loopback problem # X-Envelope-To: montana-request :0 *$ ()\/^From:$s+Mail Delivery System.* * ^X-Diagnostic: { daemon = "yes" } # If you wonder why ()\/ and non-sensical ".*" at the end is used, # it is only for logging purposes. It's easier if you can look from log file # what the regexp actually matched. :0 *$ ()\/$JA_DAEMON_REGEXP.* { daemon = "yes" } dummy = "Check for DAEMON status [$daemon]" :0 *$ daemon ?? ^^yes^^ { errText # Kill variable # Read the reason from MAIL DAEMON (subject field) :0 * B ?? THIS IS A WARNING MESSAGE { errText = "Warn-Returned," # ----- The following addresses had transient non-fatal errors ----- # :0 * B ?? The following addresses.*($)\/.*@ { match = $MATCH } } # ......................................... sendmail-error-codes ... :0 E * B ?? ()\/550.*User unknown { errText = "Err-Unknown," match = $MATCH } :0 E * B ?? ()\/554.*Mail loop detected { errText = "Err-Loop," match = $MATCH } # TO: foo@bar [552 Requested mail # operation aborted: Cannot be routed.] :0 E * B ?? ()\/.*552 .*mail operation.* { errText = "Err-Unknown," match = $MATCH } :0 E *$ $SUPREME^0 B ?? following addresses have delivery notifications *$ $SUPREME^0 B ?? has encountered a delivery problem. *$ $SUPREME^0 B ?? Mailbox disk quota exceeded *$ $SUPREME^0 B ?? did not reach the following recipient *$ $SUPREME^0 B ?? Your message was refused by recipient *$ $SUPREME^0 B ?? was not delivered to: *$ $SUPREME^0 B ?? Delivery of the email was stopped *$ $SUPREME^0 B ?? User mailbox exceed *$ $SUPREME^0 B ?? Mailbox full *$ $SUPREME^0 B ?? Our virus detector { errText = "Warn-Delivery," } :0 E * B ?? ()\/(not.*delivered.*($).*after.*hours\ |still undelivered after.*(hours|days)\ ).* { errText = "Warn-Returned," } # ...................................................... unknown ... :0 E *$ $SUPREME^0 H ?? ^Subject:.*(could not send|returned) *$ $SUPREME^0 B ?? ()\/(message.*undeliverable\ |could not be delivered\ |no longer a valid address\ |addresses had permanent fatal errors\ | User unknown\ ).* { # The message that you sent was undeliverable to the following: # postmaster (user not found) # This e-mail address, `abc', is no longer a valid address. You can # reach Mr Foo at his new email address: # # foo@bar.com # # # Subject: Returned mail: Cannot send message # The following addresses had permanent fatal errors errText = "err-Unknown," } # ........................................................ other ... :0 E * ^Subject:.*\/Host unknown { errText = "$MATCH," :0 * B ?? THIS IS A WARNING { errText = "Warn-$errText" } } :0 E * ^Subject:.*\/Too many hops { errText = "MaxHops," } :0 E B * Connection to.*failed { errText = "Err-connection," } # ........................................................ qmail ... # Hi. This is the qmail-send program at master.debian.org. # I'm afraid I wasn't able to deliver your message to the ... # This is a permanent error; I've given up. Sorry it didn't work out. # #
: # Sorry, no mailbox here by that name. (#5.1.1) :0 E * B ?? wasn't able to deliver your message to.*addresse { errText = "err-Unknown," :0 * B ?? it didn't work out.($)+\/.* { match = $MATCH } } # ................................................... Novel MTA ... :0 E *$ ^X-Diagnostic:$s+\/.* { errText = "err-Unknown," match = $MATCH } # .................................... daemon message known now? ... # If the previous recipes didn't set errText, # then this message was from a postmaster that sent it to # the spam-l or to some other mailing list where it's okay # to post copies of UBE. :0 * ! errText ?? ^^^^ { # Read the old subject from body of original message :0 B *$ $SUPREME^0 ^Subject: \/.* *$ $SUPREME^0 The subject of the message is: \/.* { errSubj = $MATCH } # Hm, no copy in the body of message? Look at headers then. :0 E *$ $SUPREME^0 match ?? $a { errSubj = $match } # Nothing matched, so take subject :0 E * ^Subject:()\/.* { errSubj = $MATCH } # To whom we tried to mail the message. Find it out # # login@site.com # | # This part will be derived, there must be leading space :0 * errTo ?? ^^^^ { :0 *$ match ?? [<]()\/$charset+ { errTo = "$MATCH," } :0 E B *$ ^To:.*\/$charset+@ *$ MATCH ?? ()\/$charset+ *$ MATCH ?? ^^\/[^@]+ { errTo = "$MATCH," } :0 E B *$ ()\/$charset+@ *$ MATCH ?? ^^\/[^@]+ { errTo = "$MATCH," } } dummy = "$NLpm-jadaemon.rc: recognized message: $errText ($errSubj)" # Now make new, combined, subject: # --> short error reason + original subject :0 fhw * JA_DAEMON_SAVE ?? yes * ^Subject: \/.* | ${FORMAIL:-formail} -I "X-Old-Daemon-Subject: $MATCH" :0 fhw | ${FORMAIL:-formail} -I"Subject: ${errText}${errTo}${errSubj}" ERROR = "yes" # Raise the flag } } dummy = "pm-jadaemon.rc: end: (DAEMON detect status = $ERROR)" # end of file pm-jadaemon.rc procmail-lib-2009.1202/lib/pm-jadate.rc000066400000000000000000000073151130547513300173510ustar00rootroot00000000000000# pm-jadate.rc -- Read date from the message hdrs: From_, Receved: # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This recipe will scan several headers to find the date string. # When suitable header is found and the parsing has succeeded, the # return variables are set. The Date values reflects the arrive time # of the message; not the sending time. If nothing works, a shell call # `date' is used as a last resort. # # Returned values # # YYYY = 4 digits # YY = 2 digits # MON = 3 characters # MM = 2 digits # DAY = 3 characters # DD = 2 digits # hh = 2 digits if available # mm = 2 digits if available # ss = 2 digits if available # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jadate1.rc # o pm-jadate3.rc # o pm-jadate4.rc # # Call arguments (variables to set before calling) # # (none) # # Usage example # # INCLUDERC = $PMSRC/pm-jadate.rc # # now we have all date variables that we need # # # $TODAY = $YYYY-$MM-$DD # # Change Log (none) # .................................................... &initialising ... id = "pm-jadate.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables, these actually come from the another subroutine, # but let's mention them here too # # DATE YYYY MM MON DD DAY hh mm ss ERROR = "yes" # ........................................................... &do-it ... # Try MDA From_ header first # From foo@bar.com Tue Nov 18 12:43:56 1997 fromRegexp = "...$s+...$s+$d+$s+$d$d:.*" dummy = "$id: From_ date test" :0 *$ ^From$s+$NSPC+\/$s+$fromRegexp { dummy = "$id: Standard From_ header matched" INPUT = $MATCH INCLUDERC = $PMSRC/pm-jadate3.rc # Date parser } # Get time from first header, which is in some systems is # Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200 dummy = "$id: Received date test" :0 *$ ! YYYY ?? $d *$ ^Received:.*;$s+\/...,$s+$d+$s+...$s$d$d$d$d.* { dummy = "$id: First Received header matched" INPUT = $MATCH INCLUDERC = $PMSRC/pm-jadate1.rc # Date parser } # Emacs Gnus add X-From-line to the message # Emacs Rmail adds Mail-from line to the message # This is same as From_ dummy = "$id: MUA date test" :0 *$ ! YYYY ?? $d *$ ^(X-From-Line|Mail-from):$s+$NSPC+\/$s+$fromRegexp { dummy = "$id: Other possible From_ header matched" INPUT = $MATCH INCLUDERC = $PMSRC/pm-jadate3.rc # Date parser } # Still no luck, I should add more tests to the above but I don't # know what. Call sh 'date' as a last resort # dummy = "$id: sh date test" :0 *$ ! YYYY ?? $d { dummy = "$id: Last chance, calling sh date " INCLUDERC = $PMSRC/pm-jadate4.rc } dummy = "$id: end:" # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-jadate1.rc000066400000000000000000000116751130547513300174360ustar00rootroot00000000000000# pm-jadate1.rc -- 'Tue, 31 Dec 1997' date parser from variable INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc parses date from variable `INPUT' which has string # # "Week, Daynbr Month Year" # # Example input # # "Tue, 31 Dec 1997" -- without comma # "Tue 31 Dec 1997" -- with comma # # Returned values # # YYYY = 4 digits # YY = 2 digits # MON = 3 characters # MM = 2 digits # DAY = 3 characters # DD = 2 digits # hh = 2 digits If available # mm = 2 digits If available # ss = 2 digits If available # TZ = 5 characters If available # # Variable ERROR is set to `yes' if it couldn't recognize the INPUT # and couldn't parse the basic YYYY, YY, MM, DD variables. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. # # Call arguments (variables to set before calling) # # INPUT = string-to-parse # # The INPUT can have anything after "Week, dayNbr Month Year", or # before it: you can pass a string like # "Thu, 13 Nov 1997 11:43:23 +0200". # # Usage example # # The first *Received* header will tell when the message was received # by your mailserver. We parse the date and avoid calling expensive # `date' command. # # PMSRC = $HOME/pm # RC_DATE_WDMY = $PMSRC/pm-jadate1.rc #Week-Day-Month-Year parser # # # Get time from first header, it ends like this: # # # # Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200 # # :0 # *$ ^Received:.*;$s+\/...,$s+$d.* # { # INPUT = $MATCH # # # Turn off the logging while executing this part # # VERBOSE=off INCLUDERC = $RC_DATE_WDMY VERBOSE=on # # :0 # * ERROR ?? yes # { # # Use some other way to get the time or shout loudly # } # } # # Change Log (none) # .................................................... &initialising ... id = "pm-jadate1.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables YYYY MM MON DD DAY hh mm ss TZ ERROR = "yes" # set defualt value # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 dummy = "$id: Parse date like [Tue, 31 Dec 1997]" dummy = "$id: INPUT = $INPUT" # show what we try to match :0 D *$ INPUT ?? $s*\/[SMTWF]$a$a[,$WSPC]+$d+$s+$a$a$a.* { INPUT = $MATCH :0 * INPUT ?? ^\/... { DAY = $MATCH } # Move to the DD MON section :0 *$ INPUT ?? [SMTWF]$a$a[,$WSPC]+\/$d.* { INPUT = $MATCH } :0 *$ INPUT ?? ^\/$d$d { DD = $MATCH } :0 E # else *$ INPUT ?? ^\/$d { DD = "0$MATCH" } :0 *$ INPUT ?? ^$d+$s+\/... { MON = $MATCH } # ........................................................ &year ... :0 *$ INPUT ?? ^$d+$s+...$s+\/.... { YYYY = $MATCH } # If this last recipe succeeds, then the whole string has been parsed. # :0 * YYYY ?? ..\/.. { YY = $MATCH ERROR = "no" } # ........................................................ &time ... # Change INPUT in = $INPUT :0 *$ INPUT ?? ^$d+$s+...$s+....$s+\/.* { INPUT = $MATCH } :0 *$ INPUT ?? ^\/$d$d { hh = $MATCH } :0 *$ INPUT ?? ^$d$d:\/$d$d { mm = $MATCH } :0 *$ INPUT ?? ^$d$d:$d$d:\/$d$d { ss = $MATCH } :0 *$ INPUT ?? ^$d$d:$d$d:$d$d$s+\/[-+].... { TZ = $MATCH } # Now reverse engineer to the numer, David Tamkin # technically one should use $\monthnym but here it doesn't matter # If user gave invalid input, will not match :0 * $ mm2nbr ?? $MON\/.. { MM = $MATCH } } dummy = "$id: end:" # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-jadate2.rc000066400000000000000000000066661130547513300174430ustar00rootroot00000000000000# pm-jadate2.rc -- 'YYYY-MM-DD' ISO date parser from variable INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc parses date in format "YYYY-MM-DD hh:mm:ss" # like `1997-12-01' and sets following variables whenever called # # YYYY = 4 digits # YY = 2 digits # MON = 3 characters # MM = 2 digits # DD = 2 digits # hh = 2 digits If avaliable # mm = 2 digits If avaliable # ss = 2 digits If avaliable # # Variable ERROR is set to `yes' if it couldn't recognize the INPUT # and couldn't parse the basic YYYY, YY, MM, DD variables. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. # # Call arguments (variables to set before calling) # # INPUT = string-to-parse # # Last string in INPUT that matches number sequence `NNNN-NN-NN' is # parsed. # # Usage example # # PMSRC = $HOME/pm # RC_DATE_ISO = $PMSRC/pm-jadate2.rc # ISO date parser # # INPUT = "This is 1800-10-11, a very old date" # # # Turn off the logging while executing this part # # VERBOSE="off" INCLUDERC=$RC_DATE_ISO VERBOSE="on" # # Change Log (none) # .................................................... &initialising ... id = "pm-jadate2.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables YYYY MM MON DD hh mm ss ERROR = "yes" # ........................................................... &do-it ... dummy = "$id: Parsing date like [YYYY-MM-DD]" dummy = $INPUT # show what we try to match :0 * INPUT ?? $ ().*\/$d$d$d$d-$d$d-$d$d.* { INPUT = $MATCH :0 * INPUT ?? ^\/.... { YYYY = $MATCH } :0 * INPUT ?? ^..\/.. { YY = $MATCH } :0 * INPUT ?? ^....-\/.. { MM = $MATCH } :0 * INPUT ?? ^....-..-\/.. { DD = $MATCH } # ........................................................ &time ... # Change INPUT in = $INPUT # this is no-op, but now we see the value in the logfile :0 *$ INPUT ?? ^....-..-..$s+\/.* { INPUT = $MATCH } :0 *$ INPUT ?? ^\/$d$d { hh = $MATCH } :0 *$ INPUT ?? ^$d$d:\/$d$d { mm = $MATCH } :0 *$ INPUT ?? ^$d$d:$d$d:\/$d$d { ss = $MATCH } # .................................................. &month-name ... # If user gave invalid YYYY-MM-DD spec, then the next recipe will # not match: eg 1111-22-33 :0 * $ nbr2mm ?? $MM\/... { MON = $MATCH ERROR = "no" } } dummy = "$id: end:" # end of file pm-jadate2.rc procmail-lib-2009.1202/lib/pm-jadate3.rc000066400000000000000000000105261130547513300174320ustar00rootroot00000000000000# pm-jadate3.rc -- 'Tue Nov 25 19:32:57' date parser from variable INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc parses date from variable INPUT which has string # # "Week, Month dayNbr hh:mm:ss yyyy", # # Example # # Tue Nov 25 19:32:57 1997 # # Returned values # # YYYY = 4 digits # YY = 2 digits # MON = 3 characters # MM = 2 digits # DAY = 3 characters # DD = 2 digits # hh = 2 digits # mm = 2 digits # ss = 2 sigits # # Variable ERROR is set to "yes" if it couldn't recognize the INPUT. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. # # Call arguments (variables to set before calling) # # INPUT = string-to-parse # # Usage example # # The first *Received* header will tell when the message was received # by the mailserver. Parse the date and avoid calling expensive `date' # command. # # PMSRC = $HOME/pm # RC_DATE_WMDT = $PMSRC/pm-jadate4.rc #Week-Month-Day-Time parser # # # Get time from X-From-Line: Which was added by my MDA # # X-From-Line: procmail-request@informatik.rwth-aachen.de \ # # Tue Nov 25 19:32:57 1997 # # :0 c # *$ ^X-From-Line:\/.* # { # INPUT = $MATCH # # # Turn off the logging while executing subroutine # # VERBOSE=off INCLUDERC = $RC_DATE_WMDT VERBOSE=on # # :0 # * ERROR ?? yes # { # # Use some other way to get the time or shout loudly # } # } # # Change Log (none) # .................................................... &initialising ... id = "pm-jadate3.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables # Kill following variables, listed one by one here: YYYY MM MON DD DAY hh mm ss ERROR = "yes" # set defualt value # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 dummy = "$id: Parse date like [Tue Nov 25 19:32:57 19:00:00 1997]" dummy = "$id: INPUT = $INPUT" # show what we try to match :0 D * INPUT ?? $ $s*\/[SMTWF]$a$a[,$WSPC]+$a$a$a$s+$d+$s+$d$d:.* { INPUT = $MATCH :0 D * INPUT ?? ^\/[A-Z].. { DAY = $MATCH } :0 D *$ INPUT ?? ^...[,$WSPC]\/[A-Z].. { MON = $MATCH } :0 *$ INPUT ?? ^...[,$WSPC]...$s+\/$d$d { DD = $MATCH } :0 E # else *$ INPUT ?? ^...[,$WSPC]...$s+\/$d { DD = "0$MATCH" } # ........................................................ &time ... # Move to hh:mm:ss section :0 *$ INPUT ?? ^...[,$WSPC]...+$s$d+$s+\/.* { INPUT = $MATCH } :0 *$ INPUT ?? ^\/$d$d { hh = $MATCH } :0 *$ INPUT ?? ^..:\/$d$d { mm = $MATCH } :0 *$ INPUT ?? ^..:..:\/$d$d { ss = $MATCH } # ........................................................ &year ... :0 *$ INPUT ?? ^..:..:..$s+\/$d$d$d$d { YYYY = $MATCH } # If this last recipe succeeds, then the whole string has been parsed. :0 * YYYY ?? ^..\/.. { YY = $MATCH ERROR = "no" } # Now reverse engineer to the numer, David Tamkin # technically one should use $\monthnym but here it doesn't matter # If user gave invalid input, will not match :0 *$ mm2nbr ?? $MON\/.. { MM = $MATCH } } dummy = "$id: end:" # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-jadate4.rc000066400000000000000000000074121130547513300174330ustar00rootroot00000000000000# pm-jadate4.rc -- make RFC 'Mon, 1 Dec 1997 17:41:09' and parse values # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine calls shell command date once and prses the values. # This should be your last resort if you haven't got the date values # by any other means. This subroutine assumes that the DATE command # knows the following % specifier formats (HP-UX) # # Y NNNN year # h MON month # d NN day # a WEEK Like "Mon" # H NN hour # M NN min # S NN sec # # Returned values # # DATE = RFC date in format "Mon, 1 Dec 1997 17:41:09" # This is same as what you would see in From_ # # YYYY = 4 digits # YY = 2 digits # MON = 3 characters # MM = 2 digits # DAY = 3 characters # DD = 2 digits # hh = 2 digits # mm = 2 digits # ss = 2 sigits # # Variable ERROR is set to "yes" if values couldn't be set # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jadate1.rc # # Call arguments (variables to set before calling) # # (none) # # Usage example # # The First Received line will tell when the message was received by # the MDA. If thata fails, then get date from the system. If you send # test messages to # yourself, you don't usually put From_ header in # it and thus there is # no date information in 'dry run' tests. # # # Get time from first eader, which is always same in my system # # Received: ... ; Thu, 13 Nov 1997 11:43:50 +0200 # # INCLUDERC = $PMSRC/pm-javar.rc # to get $s $d definitions # TODAY # Clear it # # :0 # *$ ^Received:.*;$s+\/...,$s+$d.* # { # INPUT = $MATCH # INCLUDERC = $PMSRC/pm-jadate1.rc # TODAY = "$YYYY-$MM-$DD" # } # # # Check that variable did get set, if not then we have to call # # another date subroutine: Call shell then to find out date # # # # You could also do this with ':0 E', but this is more # # educational # # :0 # *$ ! $TODAY^0 # { # INCLUDERC = $PMSRC/pm-jadate4.rc # Get date from Shell then # TODAY = $YYYY-$MM-$DD # } # # Change Log (none) # .................................................... &initialising ... id = "pm-jadat4.rc" dummy = " ======================================================================== $id: init: " # ..................................................... &output-vars ... # output variables, these actually come from the another subroutine, # but let's mention them here too # DATE YYYY MM MON DD DAY hh mm ss # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 dummy = "$id: Calling shell to get date" date = `$DATE "+%a, %d %h %Y %H:%M:%S"` INPUT = $date INCLUDERC = $RC_DATE1 # ...And parse into return variables dummy = "$id: end:" # end of file pm-jadate4.rc procmail-lib-2009.1202/lib/pm-jadate5.rc000066400000000000000000000120631130547513300174320ustar00rootroot00000000000000# pm-jadate5.rc -- 'Fri Jun 19 18:51:56 1998' date parser from var INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc parses date from variable INPUT which has string # # "WeekDay Month dayNbr Year" # # Example input # # "Fri Jun 19 18:51:56 1998" -- without comma # "Fri, Jun 19 18:51:56 1998" -- with comma # # Returned values # # YYYY = 4 digits # YY = 2 digits # MON = 3 characters # MM = 2 digits # DAY = 3 characters # DD = 2 digits # hh = 2 digits If available # mm = 2 digits If available # ss = 2 digits If available # TZ = 5 characters If available # # Variable ERROR is set to "yes" if it couldn't recognize the INPUT # and couldn't parse the basic YYYY,YY,MM,DD variables. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. # # Call arguments (variables to set before calling) # # INPUT = string-to-parse # # The INPUT can have anything after "Week, dayNbr Month Year", or # before it: you can pass a string like # "Fri Jun 19 18:51:56 1998 11:43:23 +0200". # # Usage example # # The first *Received* header will tell when the message was received # by your mailserver. We parse the date and avoid calling expensive # `date' command. # # PMSRC = $HOME/pm # RC_DATE_WDMY = $PMSRC/pm-jadate5.rc #Week-Day-Month-Year parser # # # Get time from first header, it ends like this: # # :0 # *$ ()\/From .* # { # INPUT = $MATCH # # Turn off the logging while executing this part # # VERBOSE=off INCLUDERC = $RC_DATE_WDMY VERBOSE=on # # :0 # * ERROR ?? yes # { # # Use some other way to get the time or shout loudly # } # } # # Change Log (none) # .................................................... &initialising ... id = "pm-jadate5.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables # Kill following variables YYYY MM MON DD DAY hh mm ss TZ # Set to default ERROR = "yes" # set defualt value # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 dummy = "$id: Parse: Fri Jun 19 18:51:56 1998" dummy = "$id: INPUT = $INPUT" # show what we try to match :0 D *$ INPUT ?? ()\/[SMTWF]$a$a[,$WSPC]+$a$a$a$s$d+$s+.* { INPUT = $MATCH :0 * INPUT ?? ^\/... { DAY = $MATCH } :0 *$ INPUT ?? ^...[,$WSPC]+\/... { MON = $MATCH } # Move to the DD MON section :0 *$ INPUT ?? ^...[,$WSPC]+...$s+\/.* { INPUT = $MATCH } # ........................................................ &date ... :0 *$ INPUT ?? ^\/$d$d { DD = $MATCH } :0 E # else *$ INPUT ?? ^\/$d { DD = "0$MATCH" } # ........................................................ &time ... # Change INPUT in = $INPUT # just for logging purposes :0 *$ INPUT ?? ^$d+$s+\/.* { INPUT = $MATCH } :0 *$ INPUT ?? ^\/$d$d { hh = $MATCH } :0 *$ INPUT ?? ^$d$d:\/$d$d { mm = $MATCH } :0 *$ INPUT ?? ^$d$d:$d$d:\/$d$d { ss = $MATCH } :0 *$ INPUT ?? ^$d$d:$d$d:$d$d$s+\/[-+].... { TZ = $MATCH } # ........................................................ &year ... :0 *$ INPUT ?? ^$d+:$d+:$d+$s+\/.... { YYYY = $MATCH } # If this last recipe succeeds, then the whole string has been parsed. # :0 * YYYY ?? ..\/.. { YY = $MATCH ERROR = "no" } # Now reverse engineer to the numer, David Tamkin # technically one should use $\monthnym but here it doesn't matter # If user gave invalid input, will not match :0 * $ mm2nbr ?? $MON\/.. { MM = $MATCH } } dummy = "$id: end:" # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-jadup.rc000066400000000000000000000102701130547513300172160ustar00rootroot00000000000000# pm-jadup.rc -- Procmail: Handle duplicates; store to separate folder # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This recipe stores duplicate messages to separate folder # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jastore.rc # # Call arguments (variables to set before calling) # # o JA_ID_CACHE, Where to keep the Message-Id cache. # o JA_ID_CACHE_SIZE, how big cache, defualt is 8192 # o JA_ID_MBOX, where to store duplicate messages # when delivering message to duplicate mbox. # o JA_ID_IGNORE, if set to "yes", then ignore duplicate check # # Return values # # o Variable ERROR is set to "yes" if duplicate message was trapped, # otherwise value is "no" # # Usage Example # # For simple usage, just put this somewhere after backup recipes # # RC_DUP = $PMSRC/pm-jadup.rc # ... # INCLUDERC = $RC_DUP # # When you are testing messages, you send them over and over to # .procmailrc; which means that same message should not be trapped by # duplicate check. You can call `procmail' with option "-a test" which will # set pseudo variable `$1'. The recipe below sets flag `JA_ID_IGNORE' # to "yes" if test is on going and the duplicate filter should be # bypassed. # # RC_DUP = $PMSRC/pm-jadup.rc # ARG = $1 # Copy pseudo variable to $ARG # # :0 # * ARG ?? test # { # JA_ID_IGNORE = "yes" # } # # # Some microsoft product is known to send same message ids # # over and over. If we detect one, tunr off the duplicate test, # # because it would trash every message. # # # # :0 # * ! ^X-msmail # * ! ^Message-ID: * # { # JA_ID_IGNORE = "yes" # } # # # Run this command every time a duplicate message is found. # # It writes a small log entry to MY_LOG # # INCLUDERC = $RC_DUP # # :0 hwic: # * ERROR ?? yes # | echo " [duplicate]" >> $BIFF # # Change Log: (none) # ............................................................ &code ... id = "pm-jadup.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables ERROR = "no" # .......................................................... &public ... JA_ID_CACHE = ${JA_ID_CACHE:-"$HOME/pm-msgid.cache"} JA_ID_CACHE_SIZE = ${JA_ID_CACHE_SIZE:-8192} JA_ID_MBOX = ${JA_ID_MBOX:-"junk.duplicates"} JA_ID_IGNORE = ${JA_ID_IGNORE:-"no"} # ........................................................... &do-it ... # We need regional lock, because `formail' is run in condition statement. jaDupLOCKFILE = $LOCKFILE # save old lockfile LOCKFILE = ${JA_ID_CACHE}.lock :0 * ^Message-Id: * JA_ID_IGNORE ?? no * ? $FORMAIL -D $JA_ID_CACHE_SIZE $JA_ID_CACHE { ERROR = "yes" # Flag duplicate to caller MBOX = $JA_ID_MBOX INCLUDERC = $PMSRC/pm-jastore.rc } LOCKFILE = $jaDupLOCKFILE # restore value dummy = "$id: end: (DUPLICATE status = $ERROR)" # end of file procmail-lib-2009.1202/lib/pm-jaempty.rc000066400000000000000000000040561130547513300175710ustar00rootroot00000000000000# pm-jaempty.rc -- check if message body is empty # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This simple includerc will define variable BODY_EMPTY to "yes" or # "no" when called like this You can file empty messages to separate # folder based on this value # # INCLUDERC = $PMSRC/pm-jaempty.rc # # :0 # * BODY_EMPTY ?? yes # the-empty-mail-folder # # This is more designed to be part of other modules. If you just want # to check for empty message, a simpler recipe like this might be # better: # # INCLUDERC = $PMSRC/pm-javar.rc # # :0 B: # if body has only whitespace characters # *$ ! $NSPC # the-empty-mail-folder # # Required settings # # (none) # # Change Log (none) # ............................................................ &init ... id = "pm-jaempty.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # ........................................................... &do-it ... BODY_EMPTY = "yes" # Every empty line or signarure start is a -1 # # Every non-empty line that has characters is +10 # :0 *$ B ?? -1^1 ^$s*$|^-- * B ?? 10^1 ^.*[a-z] { # no-op. We just count the score value. } SCORE = $= :0 *$ ${SCORE}^0 { BODY_EMPTY = "no" } dummy = "$id: end:" # end of file pm-jaempty.rc procmail-lib-2009.1202/lib/pm-jafrom.rc000066400000000000000000000046071130547513300174000ustar00rootroot00000000000000# pm-jafrom.rc -- get message's best FROM field without calling `formail' # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc extracts the most likely FROM address from the # message. The order of the search is Reply-to, From_, Sender, From # and if none found, then as a last resort, call `formail'. You would # usually use the returned value for logging purposes. # # Avoiding extra formail call could be usefull if you receive lot # of messages per day. # # Example input # # (none) # # Returned values # # OUTPUT, containing the derived FROM field # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. You nee procmail 3.11pre7 in # order to use this subroutine. (due to formail -z switch) # # Call arguments (variables to set before calling) # # (none) # # Usage example # # INCLUDERC = $PMSRC/pm-jafrom.rc # FROM = $OUTPUT # now we have the 'best' FROM field # # Change Log (none) # .................................................... &initialising ... id = "pm-jafrom.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables OUTPUT # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 dummy = "$id: Get message's FROM field." :0 *$ ! ^Reply-to: *\/$NSPC.* *$ ! ^From: *\/$NSPC.* *$ ! ^Sender: *\/$NSPC.* *$ ! ^From *\/$NSPC+ { OUTPUT = `formail -zxFrom:` } :0 E { OUTPUT = $MATCH } dummy = "$id: end:" # end of file pm-jafrom.rc procmail-lib-2009.1202/lib/pm-jafwd.rc000066400000000000000000000307511130547513300172140ustar00rootroot00000000000000# pm-jafwd.rc -- Controlling forwarding remotedly # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Overview of features # # o Requires latest procmail (formail -z switch) # o You can send forward-on and forward-off control # messages via email to control the forwarding in remote site. # # Description # # This includerc makes it possible to control your message forwarding # via simple remote email message. Thanks to Era Eriksson and Timothy # J Luoma who gave the initial idea to this forwarding module in the # procmail mailing list 1997-10-07. # # Activating the forwarding by hand # # If you want to activate the forwarding from the local site where # this module is, then you could simply write the forward address # to the file pointed by *JA_FWD_FILE* which is `~/.forward-address' # by default. # # % echo Me@somewhere.com > ~/.forward-address # # and when you no longer need forwarding, then remove that file. # But really, this module is not used for that purpose, because it is # lot easier to write # # :0 # ! Me@somewhere.com # # as a first statement in your .procmailrc when you want to forward # your mail to another account. # # Activating the forwarding by remote email # # Suppose you're on the road and suddenly realize that you want your # mail forwarded to the current account, then you send following # control message # # Subject: forward-on password new-address@bar.com # To: my-account@bar.com # From: onTheRoad@some.com # # That message is is enough to get the mail forwarded to the address # new-address@bar.com This script will respond to address From that # the current forwarding is now pointing to address # "new-address@bar.com". # # Deactivating forwarding by remote email # # The message is very similar, but the Subject header says # # Subject: forward-off password # # And no other fields are checked. Not even Reply-To. In this case # the confirmation message is sent directly back to From address. # # Activating forwarding via body message # # If for some reason you have no control over the headers of email, # eg when you send GSM-Mail message from your phone to your account: # # EMAIL foo@bar.com FORWARD-ON PASSWORD new-address@bar.com # # The email message looks like this: # # From: GenEmail # Date: Thu Sep 17, 11:42am +0200 # To: "'Foo.Bar'" # Subject: Message 03384874987 # # FORWARD-ON PASSWORD new-address@bar.com # # Instead of looking at the `Subject' field, you can get this module # to look at the first words in the body field. See variable # `JA_FWD_CONTROL_FIELD' which you want to set to "body". # # Restricting the control message aceptance # # If you only have persistent accounts, then you should set the # *JA_FWD_FROM_MUST_MATCH* to match those addresses that you have. # The following setting says that only control messages sent from # these addresses are accepted. Nobody else can't change your # forwarding settings. # # JA_FWD_FROM_MUST_MATCH = ".*(acc1@a.com|acc2@b.com)" # # Hm, that's not a bullet proof, because someone may in theory forge # the From address. You probably should also set this variable to # point to accounts where the mail can be legally forwarded to. Then, # even if the imposter forges the From address; he can't get the # email forwarded anywhere else than to the valid locations. # # JA_FWD_TO_MUST_MATCH = $JA_FWD_FROM_MUST_MATCH # # Consider also setting *JA_FWD_PASSWORD_CASE* to Procmail flag # `D' which causes your control word "forward-on" and password # to be case sensitive. # # Diagnostics # # If you don't receive confirmation message, then your control # message was ill formed or you're not in the *JA_FWD_FROM_MUST_MATCH* # list. There is no notification sent on failure, so that no attacker # can draw conclusions. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # # Installation # # You should preset all necessary variables prior adding the # includerc command to your .procmailrc. Here is one simple setup # # #JA_FWD_SENDMAIL = "tee $HOME/test.mail" # Uncomment if testing # JA_FWD_COPY = no # no copies stored while forwarding # JA_FWD_PASSWORD_CASE= "D" # case sensitive # JA_FWD_PASSWORD = "MyMagicString" # JA_FWD_FROM = $FROM # This is already known. # INCLUDERC = $PMSRC/pm-jafwd.rc # # Comments from the author # # Please realise that when you set the forwarding from a remote site, # be very carefull when you type in the forward address or your mail # ends up to somebody else's mailbox. Also I recommend that you keep # *JA_FWD_COPY* to *yes* so that your local account always keep the # copy of forwarded message. # # A step further would conventionally encrypt(1)'ing your forwarded # messages. This way even your top secret messages would be mostly safe # even if they end up to someone else's mailbox. # # File layout # # The layout of this file is managed by Emacs packages folding.el/{{{}}} # tinybm.el/&tags and tinytab.el for the 4 tab text placement. # # Change Log (none) # {{{ Variables # .................................................... &initialising ... id = "pm-jafwd.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ....................................................... &variables ... # If you're testing, set this to "tee FILE", and the sent confirmation # messages are stored to your disk and not actually mailed. JA_FWD_SENDMAIL = ${JA_FWD_SENDMAIL:-"sendmail -oi -t"} # File to hold the forward address. When forward is off, this file does # not exist. JA_FWD_FILE = ${JA_FWD_FILE:-"$HOME/.forward-address"} # The password needed after the control command. JA_FWD_PASSWORD = ${JA_FWD_PASSWORD:-"password"} # If you want case sensitive control messages and passwords, # set this variable to procmail flag "D". Then commands like below # are different. You should use flag `D' for your own security. # # forward-on password # Forward-on password JA_FWD_PASSWORD_CASE = ${JA_FWD_PASSWORD_CASE:-""} # Set this to account names and addresses that you use if you want some # protection. The control messages can be sent only from the matched # addresses only. The default "." accepts control message from anywhere # and to be forwarded anywhere. JA_FWD_FROM_MUST_MATCH = ${JA_FWD_FROM_MUST_MATCH:-"."} JA_FWD_TO_MUST_MATCH = ${JA_FWD_TO_MUST_MATCH:-"."} # Should the messages stored locally to this account too while forwarding # messages? a good idea is to keep this "yes", because you never know if # the forward address was faulty. JA_FWD_COPY = ${JA_FWD_COPY:-"yes"} # The accepted control messages in Subject field JA_FWD_ON = ${JA_FWD_ON:-"forward-on"} JA_FWD_OFF = ${JA_FWD_OFF:-"forward-off"} # Initialize these variables unless they're already set. please set # before this module, so that you save extra formail call, if you have # already read the value. # # JA_FWD_FROM = $FROM JA_FWD_FROM = ${JA_FWD_FROM:-`$FORMAIL -zxFrom:`} # From which header to find the password information. # # o "header" Look Subject field. # o "body" Look first words in the body of message # JA_FWD_CONTROL_FIELD = ${JA_FWD_CONTROL_FIELD:-"subject"} # This has only meanng if `JA_FWD_CONTROL_FIELD' is set to "body" # # "^^" "forward-on password" must be at the very beginning # of the body # ".*" "forward-on password" can be anywhere in the body JA_FWD_CONTROL_REGEXP = ".*" # If the address where we're forwarding bounces, make sure # we don't get into loop. JA_FWD_XLOOP = ${JA_FWD_XLOOP:-"$LOGNAME@$HOST"} # }}} # {{{ Code dummy = "Check forward-off control message" # ..................................................... &state-check ... forward = "" address = "" dummy = "$id: Check if control message is in the Subject" :0 * JA_FWD_CONTROL_FIELD ?? subject *$ ^From:$JA_FWD_FROM_MUST_MATCH { :0 $JA_FWD_PASSWORD_CASE *$ ^Subject: $JA_FWD_OFF ${JA_FWD_PASSWORD}$ { forward = "off" } :0 E $JA_FWD_PASSWORD_CASE *$ ^Subject: $JA_FWD_ON ${JA_FWD_PASSWORD} \/.* *$ MATCH ?? $JA_FWD_TO_MUST_MATCH { forward = "on" address = "$MATCH" } } dummy = "$id: Check if control message is in the body" :0 E * JA_FWD_CONTROL_FIELD ?? body *$ ^From:$JA_FWD_FROM_MUST_MATCH { :0 $JA_FWD_PASSWORD_CASE *$ B ?? $JA_FWD_CONTROL_REGEXP$JA_FWD_OFF ${JA_FWD_PASSWORD} { forward = "off" } :0 E $JA_FWD_PASSWORD_CASE *$ B ?? $JA_FWD_CONTROL_REGEXP$JA_FWD_ON ${JA_FWD_PASSWORD} \/.* *$ MATCH ?? $JA_FWD_TO_MUST_MATCH { forward = "on" address = "$MATCH" } } # ............................................................. &off ... dummy = "$id: check forward OFF" :0 * forward ?? off { :0 hwic * ? $IS_EXIST $JA_FWD_FILE | $RM $JA_FWD_FILE # Kill all fields except the From and make reply to that address. subject = "Forward is now off." :0 wc | ( $FORMAIL -X From: | \ $FORMAIL -rt -I"Subject: $subject" \ ) | $JA_FWD_SENDMAIL } # .............................................................. &on ... # It's important that we don't forward mailer daemon messages # of self bounces. The X-Loop was attached by us and while # the FROM_DAEMON would already trigger bounce message, we double # check with X-Loop dummy = "$id: check forward ON $address" :0 E * forward ?? on *$ ! ^X-Loop: $JA_FWD_XLOOP *$ ! $JA_FROM_DAEMON { # Beware invalid address. The required @ character prevents from # at least some mistakes. :0 c *$ address ?? [^$WSPC]+@ | echo "$address" > $JA_FWD_FILE # - formail -rt will use Reply-To but we also CC to the 'From:' address. # - If the From and Reply to are the same, then this sends two messages # but that's not a bad thing. # - The `A' says that this recipe is executed only if the # previous recipe put the `address' to `JA_FWD_FILE' subject = "Forwarding to [$address]" :0 Ahwc | ( $FORMAIL -IReply-To: | \ $FORMAIL -rt \ -I"Subject: $subject" -I"CC: $JA_FWD_FROM"; \ -i"X-Loop: $JA_FWD_XLOOP" \ echo "Forwarding has been activated" \ ) | $JA_FWD_SENDMAIL } # .................................................... do-forwarding ... # Now do the forwarding # File tests: # # s => file exists and has a size greater than zero # r => file must be readable by us dummy = "$NL$NL$id: Check if forward is activated $NL" :0 * forward ?? ^^^^ *$ ? $IS_NOT_EMPTY $JA_FWD_FILE *$ ? $IS_READABLE $JA_FWD_FILE { # If the copy option is on, store the mail also locally # and send a copy to forwarded address. # # The `E' Receipe only forwards and does not keep local copy. :0 *$ JA_FWD_COPY ?? yes { :0 c ! `$CAT $JA_FWD_FILE` } :0 E ! `$CAT $JA_FWD_FILE` } dummy = "$id: end:" # }}} # pm-jafwd.rc ends here procmail-lib-2009.1202/lib/pm-jalist.rc000066400000000000000000001445121130547513300174100ustar00rootroot00000000000000# pm-jalist.rc -- Subroutine to detect mailing LIST from message. # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine tries to detect and derive the mailing list name as # it appears in some of the known methods that ezlm, smarlist, # listserv, majordomo etc. normally use. After this subroutine has # been applied to message the variable `LIST' contains the mailing # list name. Subroutine adaptively finds new new mailing lists # from the messages. # # The alternative to subscribing to many mailing lists is to read # them from web archives. Even better way is to use NNTP server at # http://www.gmane.org which allows you to post as you would to a # regular newsgroup. Consider using the NNTP interface and you may # save you from receiving lot of messages that can already be found # from Gmane's server. # # Quick start # # If you just want to jump in and use this module and you # noteice that some list isn't trapped, please set # # o JA_LIST_HEADER_REGEXP to match the From: field # # If you want to make some list more unique, like if name "Alert" # was detected as a list name, please set # # o JA_LIST_MAKE_UNIQUE to match the list name, like "Alert". # After that the list name will be converted to HOST-LIST format. # # Sendmail plus type method for list subscription # # If you can use sendmail type PLUS addressing capabilities, you may # not be interested in this module, because you have an alternative # way to handle mailing list messages. The extra information after # "+" is available to procmail scripts via `$ARG' pseudo variable # when procmail is the LDA. Let's suppose you want to subscribe to # procmail mailing list and want to save all messages to folder # list.procmail, then you'd subscribe with address: # # login+list.procmail@site.com # # If your email host doe snot provide the plus addressing then it the # traditiona approach have been to add a piece of recipe to # `~/.procmailrc' to catch each list. But that's manual work for # every list. When you use this subroutine, you no longer need to # write separate mailing list recipes to your `~/.procmailrc' every # time you subscribe to a new mailing list. The detection of a new # list will happen automatically. # # What you need to know before using this module # # There is lot of heuristics going on in this module and one thing # that you must note: # # If 'To:' domain is same as `From/Sender:/Reply-to:' domain # then it is considered a mailing list message. # # This causes certain messages to be treated as mailing list messages. # The module can't possibly know that the following is not from # mailing list, because it doesn't know "what is mailing list", only # "how it probably looks like it". This is definitedly categorized as # mailing list message, because `From' and even `Reply-to' has the same # domain `foo.bar.net' as in `To'. # # To: support@foo.bar.net # From: message@foo.bar.net # Reply-to: support@foo.bar.net # Subject: Vmail See message to Eric # # You must prevent checking messages like this by surrounding call # to this subroutine with a check statement: # # # Do not check these messages # # noList = "From.*(foo.bar.net|support.my.com)" # # :0 # *$ ! $noList # { # INCLUDERC = $RC_LIST # # ... save messsag by examining variable LIST (which see) # } # # Ask for help # # If you find mailing lists that this subroutine does not detect, but # which could have been detected by looking the headers in standard # way, please send a email to maintainer. There may be cases where it # is impossible to detect the mailing list and in those cases you # just has to carve a new entry to your `~/.procmailrc'. # When you keep your procmail log running, you may see message # # *** potential list *** # # Which is an indication that some new recipe could be added to # to this subroutine to detect that mailing list. If the message # you received _was_ from a mailing list, please send all the headers # to the maintainer so that support can be added. # # Further reading # # You can search for mailing list that interests you at: # # http://www.lsoft.com/lists/listref.html # # Python based mailing list manager; the mailman: # # http://www.list.org/ # # Code note: Errors-To # # Bill Houle sent interesting headers which caused to add # more heuristic than was feasible to solve the list detection. # From the below headers it is practically impossible to derive the # original list name. So, the list name is artificially constructed # by combining Reply-To's LOGIN with Errors-To field's first host # name # # Reply-To: news@doodle.foo.net # Errors-To: bounced@doodle.foo.net # # The list name formed is "news-doodle". So, If you happen to see # an odd name like this which doesn't remind the original list # name, it may be due to poor headers that have no clue about # the real name. No problem, check below how you would convert # this name to better mailbox name. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will followign extra module, which must have been installed. # # o pm-javar.rc # # Variable JA_LIST_FROM_TO_IGNORE # # This is regexp of sender addresses to ignore so that the if To and # From are identical, it is not considered a list messages. This is # typical for system generated messages that take form: # # From: root@host (Cron Daemon) # To: root@host # # Variable JA_LIST_SAVE # # If set to "yes" then the list name information detected is saved to # separate header. The `LIST_DETECTED' is the original grabbed word from # the headers and the 'LIST' is the final name after possible # list name conversions. According to RFC the X- can be user for # user headers. # # X-List-Detected: $LIST_DETECTED mapped to $LIST # # Variable JA_LIST_KILL_POSTFIX # # If grabbed `LIST' match this regexp at the end of list name, then # the postfix match will be removed. It is traditional that many # list names are like list1-info, list2-beta, list3-L and ut would # be preferable to see names like list1, list2 and list3. The # default value will ditch "-(info|beta|L)". # # Variable JA_LIST_KILL_PREFIX # # Just like the postfix variable. If this string is matched at the # beginning of the LIST, it is removed. # # Variable JA_LIST_DISREGARD_EMAIL # # In some cases this list detection recipe "thinks" that the address # picked is the list sender. You may have a dedicated address where # all you mailing list mails arrive and you have named it like # mailing-list@me.here.at, which will effectively trigger: Ah, # you have -list in email address, so this message must be from # mailing list name 'mailing'. Of course it is not and you have to # disallow the heuristics to make such assumption by defining a # regexp that rejects a possible choice. For the above example, you # would define: # # JA_LIST_DISREGARD_EMAIL = "posting-list@me.here.at" # # If you have several such addresses, just add them to the # variable separating with normal regular expression "|" OR # statement. # # Variable JA_LIST_HEADER_REGEXP # # This is *optional* variable, which you can set to match regexp of # the mailing list domain address if it slipped through the tests # in this module. There are some lists that send messages that don't # carry enough information in headers to determine their list status. # If you narrow the group by setting JA_LIST_HEADER_REGEXP, then for # example lists like these, that identify themselves only through # two headers, can be found: # # Reply-To: dispatch-faq@cnet.com # From: CNET Digital Dispatch # # For that list you would set # # JA_LIST_HEADER_REGEXP = "(@cnet\.com)" # # Don't worry. all the other list detection recipes has already # been tried, so this is last test that are carried out and variable # JA_LIST_HEADER_REGEXP helps eliminating possible mishist # # You don't need set this variable to include all mailing list # domains. Only to those ones that were not trapped. The default # value for this is: # # "(amazon\.com|bookpool\.com)" # # Variable JA_LIST_MAKE_UNIQUE # # If you're subscribed to many mailing lists, that simply tell that # they are *news* or *newsletter*, it will be impossible to # differiantiate A *news* from B *news*. This variable holds regular # expression that, if matched, prepend the first host name to the # beginning of list name, thus making the list unique: # # news@some.com --> some-news # news@here.com --> here-news # # The default value matches lists that contain word *news*, but you # may need to set this to more matches. # # Variable JA_LIST_CONVERSION # # Note: before using this feature, make sure your `LINEBUF' # is big enough, say 4096 or otherwise the variable's content # is truncated. # # Many times the grabbed `LIST' name is not what you would like to # use for your mailbox name. You want to make the name perhaps # more shorter, more descriptive or categorize the messages according # to hierarchy. Let's say that you have subscribed to following mailing # lists: # # LIST LIST name Description of mailing list # (as grabbed) you want # ------------------------------------------------------------- # jde java.jde Java Development Env # java java.lang Java programming # FLAMENCO flamenco Flamenco music # tango-l tango Argentine Tango dancing # tm-en-help tm-en Emacs TM mime package mailing list # w3-beta w3 Emacs WWW mailing list # # First, remember that the variable `JA_LIST_KILL_POSTFIX' is first # applied, so the actual `LIST' appears as follows: # # jde, java, FLAMENCO, tango, tm-en, w3 # # Ok, now we apply the conversion table by defining it as follows. # The grabbed LIST name is first, then comes space(s), new name # _and_ terminating colon. Repeat this for each list you want to # convert. # # LIST CONVERSION[,LIST CONVERSION ...] # # This gives us table below: notice that entries tango-l, w3-beta # were not included, because the `JA_LIST_KILL_POSTFIX' already got # rid of the postfixes. Also note how the uppercase match FLAMENCO is # converted to more suitable lowercase mailbox name. After you have # set up this variable you can start saving messages to folders. # # JA_LIST_CONVERSION = "\ # jde java.jde,\ # java java.lang,\ # FLAMENCO flamenco,\ # " # # The list conversion is done with pure procmail means, so it is very # fast. It also means that the conversion is limited to FROM-STRING # TO-STRING syntax. No wild cards or regular expressions are allowed. # # If you consider using an external process, like `sed' or `perl' # to convert the grabbed list name to something else (when # `JA_LIST_CONVERSION' method was not enough); think again. For # each incoming mailing list message you launch external process. # It is not unusual to receive 700 messages from various mailing # lists a day, it can be imagined how much load any external # process would add to the server. Use the grabbed mailing list # name and `JA_LIST_CONVERSION' table if you care about system # load. # # If you have many mailing lists that use uppercase names, it may be # tedious to add each mailing list name to `JA_LIST_CONVERSION'. # Possible alternative is to use very efficient `tr' program # to convert characters to lowercase. Again; think twice, # because any extra process could be avoided if `JA_LIST_CONVERSION' # was used. # # :0 # * ! LIST ?? ^^^^ # { # :0 D # still uppercase list name? # * LIST ?? [A-Z] # { # LIST = `echo $LIST | tr A-Z a-z` # } # # :0 : # list.$LIST # } # # List name is not always the same # # One important thing to keep in mind is that when mailing list # manager sends out list messages, the headers may change. # This means that the list name grabbed previously changes too. # This is unfortunate, but it sometimes happens. Let's see an example. # I was previously receiving messages from Cygwin mailing list named # `gnu-win32' # # To: , "Foo Bar" # # However, one day that same list was grabbed under name "cygwin", due # to new header # # Mailing-List: contact cygwin-help@sourceware.cygnus.com; run by ezmlm # Now I had two list names that both should be going to the same # mailbox. No worries, just add new entry to the translate # table to convert the new list name to mailbox name: # # JA_LIST_CONVERSION = "\ # gnu-win32 cygwin32,\ # cygwin cygwin32,\ # " # # Example: basic installation # # Here is recipe to save all your mailing list to separate folders. # If you subscribe to new lists or unsubscribe to lists, you don't # need to change anything. The grabbed list name will appear # in variable `LIST' # # RC_LIST = $PMSRC/pm-jalist.rc # name the subroutine # # ... # # # Handle all mailing lists with one subroutine and recipe # # following it. Set also JA_LIST_CONVERSION before # # calling this subroutine to cnvert the found list names. # # INCLUDERC = $RC_LIST # imap = # Kill var. Set to "/" to enable # # :0 # if list name was grabbed # * LIST ?? [a-z] # { # dummy = "Saving mailing list: $LIST" # # :0 w: # ${imap+".INBOX."}list.$LIST$imap # } # # What's that IMAP thing there, you may wonder. Normally # procmail delivers to standard mailbox, so the name is # something like '$MAILDIR/list.abc'. For IMAP, the delivery # must happen using principle "one file, one message", so # procmail must deliver to a directory. That's what the added # `$imap' is there for. It is also customary that IMAP folders # are prefixed with ".INBOX", so the actual name becomes # `$MAILDIR/.INBOX.list.abc'. For IMAP there should also # be proper `MAILDIR=$HOME/Maildir' setting. # # Change Log (none) # # [Not updated any more - See project's ChangeLog file] # # 1998-06-16 dattier@wwa.com (David W. Tamkin) in list.procmail # Message-Id: replied to my # my first announcement of list detection module. I used to use # `expr' to delete -(help|owner) suffixes in complicated cases, # but David showed that procmail could do that also. # # Now this subroutine does not use shell anywhere and is therefore # as lightweight as possible and suitable for heavy mailing lists. # # 1998-06-30 Teresa Nunes reported that # more list were not trapped. Added new rule to match servers # that use "@lists." id. Added "estimation" rule. # # 1998-08-10 Teresa Nunes reported that # more list were not trapped and # sent cases which he labelled "Probably nothing can be done for this # and this...". Well, suprise to your both. All the examples could # be detected and list name derived. # # 1998-11 and 199-12 Bill Houle sent # me numerous new mailing ist message headers that improved detecting # new mailing lists format a great deal. Thank you very much. # # 1999-01 Bill Houle Still kept # subscribing to mailing list that were not triggered by this module :-) # Thank Bill for the samples. # # 1999-04 Tony Lam suggested adding # X-List-Detected header and storing the original grabbed word # to LIST_DETECTED. He also suggested new Received: "for" header # check for possible mailing list names that contains dash(-). # .................................................... &initialising ... dummy = " ======================================================================== pm-jalist.rc: init:" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # .......................................................... &public ... # tango-l, spam-list-d (discussion) # These pre/postfix regexps and they must _not_ contain leading slashes: # # "-(help|beta)" Wrong # "(help|beta)" Right JA_LIST_KILL_PREFIX = ${JA_LIST_KILL_PREFIX:-"\ (return|owner|info|beta|help|announce|users|subscribers)"} JA_LIST_KILL_POSTFIX = ${JA_LIST_KILL_POSTFIX:-"\ (return|owner|info|beta|help|request|digest\ |announce|users|subscribers|maint\ |unjoin|join\ |discuss\ |errors\ |on|off|[ld])"} # See installation JA_LIST_CONVERSION = ${JA_LIST_CONVERSION:-""} JA_LIST_HEADER_REGEXP = ${JA_LIST_HEADER_REGEXP:-"\ (amazon\.com|bookpool\.com)"} # If we detect plain list name line "news" "announce" or "daily", # that is too general, because same name can come from several sites. JA_LIST_MAKE_UNIQUE = ${JA_LIST_MAKE_UNIQUE:-"\ ^^(news(letters?|[0-9]+)?\ |talk(tous)?\ |unjoin|join\ |announce(ments?)?\ |daily|scripts?\ |modules?)\ ^^"} JA_LIST_DISREGARD_EMAIL = ${JA_LIST_DISREGARD_EMAIL:-""} # Messages that have identical From-To and match this regexp are ignored. JA_LIST_FROM_TO_IGNORE = ${JA_LIST_FROM_TO_IGNORE:-\ "(root|postmaster|webmaster|abuse|spam)"} # returned value LIST_DETECTED # Kill variable LIST # Kill variable # ........................................................... &check ... pfx = "( *(){}$WSPC?&,@\"\'=]" # THIS LINE: Emacs font-lock.el fix to close previous quote(") # Words that are included in the list name, like "food-discuss" trigger = "(\ [ld]\ |admin\ |announce\ |apps\ |beta\ |digest\ |discuss\ |errors\ |help\ |info\ |join\ |maint\ |off |on |owner\ |return\ |request\ |subscribers\ |unjoin\ |users\ )" from = "(X-From-Line:|X-From:|From:|From )" from1 = "(X-From-Line:|X-From:|From:)" to = "((Apparently-)?To:)" email = $abc+@$abc+ agent = (owner|info|errors) rc_email = $PMSRC/pm-jaaddr.rc # .................................................... &setting-vars ... dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::::::: #FROM" # This variable is used as a hint to get a unique list name. # If not set, then define sender name from $from. unique_from = "" sender_field = "" sender_addr = "" sender_addr2 = "" sender_site = "" sender_domain = "" sender_sub1 = "" sender_account = "" :0 *$ $SUPREME^0 ^(Sender:|$from1)\/.* *$ $SUPREME^0 ^From \/.* { sender_field = $MATCH # Call subroutine save=$VERBOSE VERBOSE = "off" INPUT = $MATCH INCLUDERC = $rc_email VERBOSE=$save sender_addr = $ADDRESS # foo@a.b.com sender_addr2 = $ACCOUNT@$DOMAIN # foo@b.com sender_account = $ACCOUNT # foo sender_domain = $DOMAIN # b.com sender_site = $SITE # a.b.com sender_sub1 = $SUB1 unique_from = $sender_field } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::::::: #TO" to_field = "" to_addr = "" to_addr2 = "" to_site = "" to_account = "" to_domain = "" to_sub1 = "" :0 * ^To:\/.* { to_field = $MATCH saved = $VERBOSE VERBOSE = "off" INPUT = $to_field INCLUDERC = $rc_email VERBOSE = "$saved" to_addr = $ADDRESS to_addr2 = $ACCOUNT@$DOMAIN to_account = $ACCOUNT to_domain = $DOMAIN to_site = $SITE to_sub1 = $SUB1 } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::::: #REPLY" reply_field = "" reply_addr = "" reply_addr2 = "" reply_account = "" reply_site = "" reply_domain = "" reply_sub1 = "" :0 * ^Reply-To:\/.* { reply_field = $MATCH saved = $VERBOSE VERBOSE = "off" INPUT = $reply_field INCLUDERC = $rc_email VERBOSE = "$saved" reply_addr = $ADDRESS reply_addr2 = $ACCOUNT@$DOMAIN reply_account = $ACCOUNT reply_domain = $DOMAIN reply_site = $SITE reply_sub1 = $SUB1 } cc_field = "" cc_addr = "" cc_addr2 = "" cc_account = "" cc_site = "" cc_domain = "" cc_sub1 = "" dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::::: #CC" :0 * ^CC: \/[^,]+ { cc_field = $MATCH saved = $VERBOSE VERBOSE = "off" INPUT = $cc_field INCLUDERC = $rc_email VERBOSE = "$saved" cc_addr = $ADDRESS cc_addr2 = $ACCOUNT@$DOMAIN cc_account = $ACCOUNT cc_domain = $DOMAIN cc_site = $SITE cc_sub1 = $SUB1 } # ....................................................... µsoft ... dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: #MICROSOFT" # Microsoft mailing lists # # From BackOfficeEditor_004060@news.newswire.microsoft.com # From: "Microsoft TechNet" :0* LIST ?? ^^^^ *$ ^$from.*@news.*.microsoft { :0 *$ ^$from.*$pfx+\/$abc+_$d+@ *$ MATCH ?? ()\/$a+ { LIST = $MATCH } } # ................................................. &targetted-catch ... dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: #LSV" # X-LSV-ListID: SPAM-L :0 * LIST ?? ^^^^ *$ ^X-LSV-ListID:$s+\/$abc+ { LIST = $MATCH } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: #List-Id" # -- The first supreme matches both these cases # # List-Id: A user list for the exim MTA # List-ID: # -- The second supreme mathes this # # List-ID: # List-Id: gnome-print-list.gnome.org dummy = "pm-jalist.rc: List-ID" :0 * LIST ?? ^^^^ *$ $SUPREME^0 ^List-ID:.*<\/$abc+ *$ $SUPREME^0 ^List-ID:.*$pfx\/$abc+> *$ $SUPREME^0 ^List-ID:$s*\/$abc+ { LIST = $MATCH } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: #List-* " # More similar headers that can be used ... # # Precedence: bulk # List-Help: # List-Unsubscribe: # List-Post: # List-Subscribe: # # Precedence: list # List-Help: # List-Subscribe: # List-Unsubscribe: # # List-Post: # List-Owner: dummy = "pm-jalist.rc: Other List-* headers" :0 * LIST ?? ^^^^ *$ $SUPREME^0 ^List-Post:.*<\/$abc+ *$ $SUPREME^0 ^List-Post:.*$pfx\/$abc+> *$ $SUPREME^0 ^List-(Un)?Subscribe:.*$pfx\/$abc+> { LIST = $MATCH } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: Mailman" # X-Mailman-Version: 1.0 # Precedence: bulk # List-Id: LeoCAD Development List # X-Loop: docwhat@gerf.org :0 * ! * LIST ?? ^^^^ * ^X-Mailman-Version: * ^List-Id:[^<]+<\/[^>]+ { dummy = "pm-jalist.rc: Mailman MATCH is $MATCH" LIST = `echo $MATCH | sed 's/\./@/'` dummy = "$is: Mailman LIST is $LIST" } # ..................................................... mailing-list ... # X-Mailing-List: archive/latest/17987 # X-Mailing-List: archive/latest/954 # X-Mailing-List: archive/latest/119 # X-Mailing-List: # Mailing-List: contact jde-help@sunsite.auc.dk; run by ezmlm # Mailing-List: contact pgp-users-help@joshua.rivertown.net; run by ezmlm # X-Mailing-List: archive/latest/22876 dummy = "pm-jalist.rc: :::::::::::::::::::::::: X-Mailing-List1" dummy = "pm-jalist.rc: X-Mailing-List AGENT-" :0 * LIST ?? ^^^^ *$ ^(X-)?Mailing-List:$pfx$agent-\/$abc+@ { LIST = $MATCH } dummy = "pm-jalist.rc: X-Mailing-List non-greedy match" :0 * LIST ?? ^^^^ *$ ^(X-)?Mailing-List:${pfx}\/$abc+@ { LIST = $MATCH } dummy = "pm-jalist.rc: X-Mailing-List greedy match" :0 * LIST ?? ^^^^ *$ ^(X-)?Mailing-list:.*${pfx}\/$abc+@ { LIST = $MATCH } # .................................................... &list-headers ... dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::: list-* [$LIST]" # A great of good set of headers to pick list name from # # List-Software: Lyris Server version 2.54, # List-Subscribe: # List-Owner: # List-Help: # X-List-Host: ActiveState Tool Corp. # Reply-To: "Christopher Maujean (Volt Computer)" # Sender: perl-win32-users-admin@lyris.activestate.com # Precedence: bulk # X-Lyris-To: [foo@example.com] # X-Lyris-MemberID: 45971 # X-Lyris-MessageID: 32936 # X-listname: perl-win32-users # X-ListMember: [foo@example.com] :0 * LIST ?? ^^^^ *$ ^X-Listname:$s+\/$abc+ { LIST = $MATCH } :0 * LIST ?? ^^^^ *$ ^List-Owner:$pfx$agent-\/$abc+@ { LIST = $MATCH } # List-Unsubscribe: # List-Unsubscribe: unsubscribe network-computing-newsletter :0 * LIST ?? ^^^^ *$ $SUPREME^0 ^List-Unsubscribe: +unsubscribe$pfx\/$abc+ *$ $SUPREME^0 ^List-Unsubscribe:$pfx\/$abc+ { LIST = $MATCH :0 * ^List-Unsubscribe:\/.* { unique_from = $MATCH } # Check if there is Reply-To and narrow "leave-jscript-146465L" to # "jscript" by searching common match. :0 *$ $SUPREME^0 ^Reply-To:.*[<]\/$abc+ *$ $SUPREME^0 ^Reply-To:.*$pfx\/$abc+ { replyToListName = $MATCH dummy = "pm-jalist.rc: is replyToListName included in List-Unsubscribe?" :0 *$ LIST ?? $replyToListName { LIST = $replyToListName } } } # ........................................................ &triggers ... dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: TO #TRIGGER" # Just impossible to know that this is list....without -discuss keyword # From list-relay@mlist.ucsd.edu Fri Jan 22 20:13:07 1999 # Sender: foo@bar.com # From: foo@bar.com # To: :0 * LIST ?? ^^^^ *$ ^To:$pfx\/$abc+-$trigger@ { LIST = $MATCH unique_from = $to_field } # ...................................................... envelope-to ... # X-Envelope-to: tango-L@mitvma.mit.edu dummy = "pm-jalist.rc: TRY X-Envelope-to" :0 * LIST ?? ^^^^ *$ ^X-Envelope-to:${pfx}\/$abc+ { LIST = $MATCH } # ........................................................... sender ... # Sender: Discussion of Any Aspect of the Argentine Tango # # Sender: Open discussion of TI Graphing Calculators # # Sender: owner-ding@hpc.uh.edu # Sender: Flamenco discussion group # Sender: owner-ntemacs-users@cs.washington.edu # ((((( NOTE ))))) # This would match # # Sender: owner-announce@perl.org --> LIST = "announce" # # Which is prevented with JA_LIST_KILL_POSTFIX test # # The SUPREME will match first Sender field, then any field that has # agent properties like owner- ... dummy = "pm-jalist.rc: :::::::::::::::::::::::: Sender" :0 * LIST ?? ^^^^ *$ $SUPREME^0 ^Sender:$pfx$agent-\/$abc+ *$ $SUPREME^0 ^[-a-z]+:$pfx$agent-\/$abc+ *$ ! MATCH ?? ^^$JA_LIST_KILL_POSTFIX^^ { LIST = $MATCH :0 *$ ^Sender:\/.* { unique_from = $MATCH } } dummy = "pm-jalist.rc: TRY sender1a" :0 * LIST ?? ^^^^ *$ ^Sender:.*${pfx}\/$abc+-L\> { LIST = $MATCH } dummy = "pm-jalist.rc: TRY sender1b" :0 * LIST ?? ^^^^ *$ ^Sender:.*${pfx}\/$abc+@listserv { LIST = $MATCH } # Sender: semi-gnus-en-owner@meadow.scphys.kyoto-u.ac.jp dummy = "pm-jalist.rc: sender postfix words in list name" :0 * LIST ?? ^^^^ *$ ^Sender:${pfx}\/$abc+-$agent { LIST = $MATCH } # Reply-To: "AIP Public" # Sender: public-admin@lists.association.org dummy = "pm-jalist.rc: sender lists.domain" :0 * LIST ?? ^^^^ *$ ^Sender:.*\/${abc}+@lists\. { LIST = $MATCH } # ............................................................. From ... dummy = "pm-jalist.rc: :::::::::::::::::::::::: From-Owner 1" :0 * LIST ?? ^^^^ *$ ^$from.*${pfx}\/$abc+-$agent { LIST = $MATCH } dummy = "pm-jalist.rc: :::::::::::::::::::::::: From-Owner 2" :0 * LIST ?? ^^^^ *$ ^$from.*$pfx\/$agent-$abc+@ { LIST = $MATCH } dummy = "pm-jalist.rc: :::::::::::::::::::::::: From-Owner 3 TRIGGER" # To: Planet IT Members:; # Subject: Join Planet IT's New Systems-Management Technology Center # From: Planet IT Announcements # Errors-To: anchovy+cmp-planetit010899-1@mx.lodo.infobeat.com :0 * LIST ?? ^^^^ *$ $SUPREME^0 ^$from.*$pfx.*\/${abc}+-$trigger@ *$ $SUPREME^0 ^$from.*$pfx.*\/${trigger}-$abc+@ { LIST = $MATCH } # We can't do anything automatic to detect this list. User must # set JA_LIST_HEADER_REGEXP to match @motleyfool.com, then the # FoolWatch: from Subject line it taken. # From: foolexpress@motleyfool.com # Received: (qmail 1528 invoked by uid 536); 17 Dec 1998 02:31:49 -0000 # Message-ID: <19981217023149.1527.qmail@mail3.motleyfool.com> # Date: 16 Dec 1998 21:31:49 -0500 # Subject: FoolWatch: Downsizing Tidal Wave? and Rule Breaker on Amazing Amazon # Subject: Fool Watch: # To: foo@bar.com dummy = "pm-jalist.rc: TRY FromLogin 2" :0 * LIST ?? ^^^^ *$ $SUPREME^0 ^Subject: +\/$abc$abc$abc$abc+: *$ $SUPREME^0 ^Subject: $abc$abc$abc$abc+ +\/$abc$abc$abc$abc+: *$ MATCH ?? ()\/[^:]+ *$ $JA_LIST_HEADER_REGEXP { LIST = $MATCH } # This is tough. We pick the host names from the From address and try to # see if those exist in the Subject line. SIDEWALK can be found # # The regexp ^Subject:.* +\/$abc$abc$abc$abc+: makes sure there is # some list name with colon. Simple "re:" won't do, but "Alert:" does. # From: talktous@sandiego.sidewalk.com # To: # Subject: Sidewalk Ticket Alert: Handel's "Messiah," Jingle Ball dummy = "pm-jalist.rc: TRY From-Subject 1" :0 # host 1 after @ * LIST ?? ^^^^ *$ ^Subject:.* +\/$abc$abc$abc$abc+: *$ ^$from.*@\/$abc+ *$ ^Subject:.*$\MATCH { tmp = $MATCH :0 *$ ^$from.*\/$S+@.*$tmp *$ MATCH ?? ()\/[^@]+ { LIST = $MATCH :0 *$ ^()\/$from.*@.*$tmp { unique_from = $MATCH } } } dummy = "pm-jalist.rc: TRY From-Subject 2" :0 # host 2 after @ * LIST ?? ^^^^ *$ ^Subject:.* +\/$a$a$a$a+: *$ ^$from.*@$a+\.\/$a+\.$a+ *$ MATCH ?? ()\/$a+ *$ ^Subject:.*$\MATCH { # We can use this "sidewalk", because it's sub-domain and UNIQUE # would pick. We want something outside... tmp = $MATCH # Get the login. find the correct FROM that contains TMP, then extract # the login :0 *$ ^$from.*\/$S+@.*$tmp *$ MATCH ?? ()\/[^@]+ { LIST = $MATCH :0 *$ ^()\/$from.*@.*$tmp { unique_from = $MATCH } } } dummy = "pm-jalist.rc: TRY From-Subject 3 words" # Try to match three same words from both SUBJECT and FROM: # # To: foo@bar.com # Subject: Silicon Alley Daily for Monday, January 4, 1999 # From: Silicon Alley Daily # Errors-To: daily-errors+1.0.92574.foo#bar.com@bounce.sar.infobeat.com # # Notice that here are 2 common words # # Subject: Silicon Alley Reporter Net TV Show @ 4 p.m. # From: Silicon Alley Daily # # Ignore messages that come from daemon, like # # From: Mail Delivery System # Subject: Mail delivery failed: returning message to sender :0 * LIST ?? ^^^^ *$ ! $JA_FROM_DAEMON *$ ! $JA_FROM_MAILER *$ ^Subject: +\/$S+ +$S+ *$ ^$from1\/$s*$\MATCH.* *$ ^Subject: +\/$S+ +$S+ .* { tmp = $MATCH # save "Silicon alley Daily" status = "read-more" :0 # Record the correct FROM line *$ ^()\/$from.*$tmp.* { unique_from = $MATCH } # Now make list name. Note that first "]" character must end reading # words # # Subject: [this list] dummy = " *** WORD 1" :0 *$ tmp ?? ^^()\/$S+ { part = $MATCH :0 * part ?? ()\/[a-zA-Z0-9_-]+ { LIST = $MATCH } :0 *$ part ?? \]^^ { status = "stop" } } dummy = " *** WORD 2" :0 * status ?? read-more *$ tmp ?? ^^$S+ +\/$S+ { part = $MATCH :0 * part ?? ()\/[a-zA-Z0-9_-]+ { LIST = $LIST-$MATCH } :0 *$ part ?? \]^^ { status = "stop" } } dummy = " *** WORD 3" :0 * status ?? read-more *$ tmp ?? ^^$S+ +$S+ +\/$S+ { part = $MATCH :0 * part ?? ()\/[a-zA-Z0-9_-]+ { LIST = $LIST-$MATCH } } } # ................................................ FromLogin-Subject ... # Check if LOGIN is found from SUBJECT # # From: newsletter@x10.com # To: # Subject: X-10 Newsletter: FREE Sticka Switches dummy = "pm-jalist.rc: :::::::::::::::::::::::: From-Login" :0 * LIST ?? ^^^^ *$ ^$from.*${pfx}\/$abc+ *$ ^Subject:.*$MATCH: { LIST = $MATCH } # ....................................................... subscriber ... # To: "internet-subscribers" # From: # Subject: Amazon.com Delivers Internet :0 * LIST ?? ^^^^ *$ ^To:.*\/($abc.*subscriber|subscriber.*$abc) *$ $JA_LIST_HEADER_REGEXP { LIST = $MATCH } # ........................................................... X-list ... # X-Listserver: ListSTAR v1.1 by StarNine Technologies, a Quarterdeck Company # X-List-Subscribe: # X-List-Help: # List-Subscribe: # The list name can't be deternined by $trigger, but we can # estimate that if # # Sender = To, then it's list # OR # Reply-To = To # # Reply-To: Alpha K9s # Sender: Alpha K9s # From: "Mark A. Winters" # To: ALPHAK9S@APPLE.EASE.LSOFT.COM dummy = "pm-jalist.rc: :::::::::::::::::::::::: Using heuristics" # ....................................................... sender ... dummy = "pm-jalist.rc: ****** Checking Sender" :0 * LIST ?? ^^^^ * sender_addr ?? [a-z] * to_addr ?? [a-z] { dummy = "pm-jalist.rc: to_addr $to_addr ?? sender_addr $sender_addr" # We try first with exact matches, then with only the top level domain # # addr = site.this.com # addr2 = this.com :0 *$ $SUPREME^0 to_addr ?? ()\/$\sender_addr *$ $SUPREME^0 to_addr ?? ()\/$\sender_addr2 *$ $SUPREME^0 to_addr2 ?? ()\/$\sender_addr *$ $SUPREME^0 to_addr2 ?? ()\/$\sender_addr2 *$ MATCH ?? ()\/$abc+@ { :0 *$ ! sender_addr ?? $JA_LIST_FROM_TO_IGNORE { dummy = "pm-jalist.rc: Sender is identical to To." unique_from = $to_addr2 LIST = $MATCH } } # To: humor@NewHumor.com # Sender: ListManager@NewHumor.com # # But, it must not be person-to-person message, that's why # JA_LIST_HEADER_REGEXP addition. dummy = "pm-jalist.rc: sender_addr [$sender_addr] ?? to_site [$to_site] [$to_addr]" :0 E *$ $JA_LIST_HEADER_REGEXP *$ sender_addr ?? $\to_site *$ to_addr ?? ()\/$abc+ { dummy = "pm-jalist.rc: Sender address matched To domain." LIST = $MATCH } } # ..................................................... reply-to ... dummy = "pm-jalist.rc: :::::::::::::::::::::::: Reply-to" :0 * LIST ?? ^^^^ * ^Reply-To:\/.* *$ to_addr ?? ()\/$abc+ { # ................................. Reply-To identical to To ... # To: web-consultants@just4u.com # Reply-To: web-consultants@just4u.com dummy = "pm-jalist.rc: Check if Reply-To identical to To." dummy = "pm-jalist.rc: [$to_addr] ?? [$reply_addr]" :0 *$ $SUPREME^0 to_addr ?? ()\/$\reply_addr *$ $SUPREME^0 to_addr ?? ()\/$\reply_addr2 *$ $SUPREME^0 to_addr2 ?? ()\/$\reply_addr *$ $SUPREME^0 to_addr3 ?? ()\/$\reply_addr2 *$ MATCH ?? ()\/$abc+@ { unique_from = $to_addr2 LIST = $MATCH } # ............................... Reply-To identical to From ... dummy = "pm-jalist.rc: Check if Reply-To identical to From." dummy = "pm-jalist.rc: [$sender_addr] ?? [$reply_addr]" :0 E *$ sender_addr ?? $\reply_addr *$ MATCH ?? ()\/$abc+@ *$ $JA_LIST_HEADER_REGEXP { dummy = "pm-jalist.rc: MAYBE LIST, Reply-To is identical to From address." LIST = $MATCH } # Hm, not identical addresses; but partially. # # Reply-To: dispatch-faq@cnet.com # From: CNET Digital Dispatch dummy = "pm-jalist.rc: SENDER/REPLY acc [$sender_account] ?? [$reply_account]" :0 E *$ $SUPREME^0 sender_account ?? ()\/$reply_account *$ $SUPREME^0 reply_account ?? ()\/$sender_account *$ $JA_LIST_HEADER_REGEXP { LIST = $MATCH } # Well: howabout site names then? # # From: TripMiles # Reply-to: feedback@thetrip.com dummy = "pm-jalist.rc: SENDER/REPLY domain [$sender_domain] ?? [$reply_adomain]" :0 E *$ $SUPREME^0 sender_domain ?? ()\/$\reply_domain *$ $JA_LIST_HEADER_REGEXP { LIST = $reply_sub1-$reply_account } } # ...................................................... Error-To ... dummy = "pm-jalist.rc: :::::::::::::::::::::::: Errors-to" :0 * LIST ?? ^^^^ *$ ^Errors-To:.*\/$email * MATCH ?? @()\/.* { errors_domain = $MATCH # Hmmm The address is not identical, but maybe there is Errors-To # Header that we could use for tracking a list context ? # # To: list-member@foo.com # Reply-To: news@fusion.nww.com # Errors-To: bounced@fusion.nww.com dummy = "pm-jalist.rc: Errors-To [$errors_domain] reply_addr [$reply_addr]" :0 * ! reply_addr ?? ^^^^ *$ reply_addr ?? $\errors_domain { unique_from = $reply_addr :0 *$ reply_addr ?? ()\/$abc+ { LIST = $MATCH } } dummy = "pm-jalist.rc: Errors-To [$errors_domain] reply_addr [$sender_addr]" :0 E * ! sender_addr ?? ^^^^ *$ sender_addr ?? $\errors_domain { unique_from = $sender_addr :0 *$ sender_addr ?? ()\/$abc+ { LIST = $MATCH } } dummy = "pm-jalist.rc: Errors-To [$errors_domain] to_addr [$to_addr]" :0 E * ! to_addr ?? ^^^^ *$ to_addr ?? $\errors_domain { unique_from = $to_addr :0 *$ to_addr ?? ()\/$abc+ { LIST = $MATCH } } } dummy = "pm-jalist.rc: :::::::::::::::::::::::: From-newsletter" # From: newsletter@x10.com # Subject: X-10 Buyer's Alert: Super-Saver Weekend Deals - up to 60% OFF! :0 E *$ ^$from:.*newsletter@ { LIST = "newsletter" :0 *$ ^()\/$from:.*newsletter@.* { unique_from = $MATCH } } # ................................................. named LIST in CC ... dummy = "pm-jalist.rc: :::::::::::::::::::::::: TO-CC mailing List" # Somebody is replying direct, but also sending to list with CC: # # To: Foo Bar # Cc: procmail mailing list # # Also find # # JAVAL-L :0 * LIST ?? ^^^^ *$ ^(To|CC):\//*(.*mailing$s+list|\<$S+-L\>).* *$ MATCH ?? ()\/[^$WSPC<]+@ { LIST = $MATCH } dummy = "pm-jalist.rc: :::::::::::::::::::::::: TO-CC postfix match" # Try to find POSTFIX address somewhere in header # To:foo@example.com # Cc: winNT Emacs list :0 * LIST ?? ^^^^ *$ ()[<, ]\/$abc+-$trigger@ { LIST = $MATCH } # ..................................................... X-ListMember ... # some lists are announce only and they contain "null". Pick name from # X-ListMember field # # To: ora-news@list.ora.com # From: Ora-News # Reply-To: # X-ListMember: me@here.com [ora-news@list.ora.com] dummy = "pm-jalist.rc: :::::::::::::::::::::::: X-ListMember" dummy = "pm-jalist.rc: check SENDER ?? TO_FIELD [$sender] ?? [$to_field] " # See if DOMAIN if same in both From and To # See if ACCOUNT is found from FROM field :0 * LIST ?? ^^^^ * X-ListMember *$ ^To:.*@\/$abc+ *$ ^$from.*$MATCH *$ ^To:.*$pfx\/$abc+ *$ ^$from.*$MATCH { LIST = $MATCH } # ...................................................... &ListServer ... # From: ListServer@wrox.com # Message-Id: <199812301439.IAA13867@neuman.interaccess.com> # Date: 30 Dec 1998 08:37:27 -0600 # Subject: Wrox Press Newsletter, 12/29/98 # To: foo@bar.com :0 * LIST ?? ^^^^ *$ ^$from1.*ListServer@\/[^.]+ { LIST = $MATCH # grab server :0 # Grab fist word too *$ ^Subject: $LIST +\/$S+ { LIST = $LIST-$MATCH } } # .......................................................... &digest ... # From foo@bar.com # From: sans@clark.net # To: foo@bar.com # Subject: SANS Digest Vol 2, No. 11 dummy = "pm-jalist.rc: :::::::::::::::::::::::: DIGEST" # The \/$from.* is just for logging purposes :0 * LIST ?? ^^^^ * ! ^Subject:.*re: * ^()\/$from.* * ^Subject: +\/.*digest () *$ MATCH ?? ()\/$abc+ +digest *$ MATCH ?? ()\/$abc+ *$ ^$from.*$MATCH@ { LIST = $MATCH # The $from can match multiple from fields, like # # From foo@bar.com # From: sans@clark.net # # And we want to force reading UNIQUE from "From:", otherwise the # $from would take the "From ". See Unique recipe and SUPREME. :0 *$ ^()\/$from.*$MATCH.* { unique_from = $MATCH } } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: #NEWS" # From: sender@thetrip.com # Reply-to: feedback@thetrip.com # Subject: TheTrip.com Newsletter # # Sender: SERVERWATCH # From: SERVERWATCH # Subject: Serverwatch News - January 22, 1999 :0 * LIST ?? ^^^^ * ! ^Subject:.*(Re:|fwd) *$ ^Subject:$s+\/$S+$s+news(letter)?.* *$ ^Subject:$s+\/$S+ { LIST = $MATCH } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: #[LIST]" # This must be last, because relying on the [] syntax is last resort. # Many users indicate the nature of message in the first word, like # # [off topic] # [bug] # # And those are not list names. But then again this is: # # Message-Id: <199903031849.NAA19835@defender.perl.org> # From: TPI News Pumpking # To: TPI News List # Subject: [TPI News] March 03, 1999 # Sender: owner-announce@perl.org # Precedence: bulk # Reply-To: news@perl.org # X-Debug: List=(announce@perl.org) x = $abc word = "($x$x$x$x?$x?$x?$x?$x?$x?$x?)" # maximum size of the word :0 * LIST ?? ^^^^ *$ ^Subject: +\[\/$word($s+$word)?\] *$ $JA_LIST_HEADER_REGEXP { tmp = $MATCH :0 *$ tmp ?? ()\/$x+ { LIST = $MATCH } :0 # second word *$ tmp ?? $x$s+\/$x+ { LIST = "$LIST-$MATCH" } } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: @LIST.COM" # To: :0 * LIST ?? ^^^^ *$ ()\/$abc+@list\.* * MATCH ?? ()\/[^@]+ { LIST = $MATCH } dummy = "pm-jalist.rc: ::::::::::::::::::::::::::::::::: FOR list-name" # Suggestion by Tony Lam # # To: nm-interest@foo.com, nm-consulting@foo.com # # 1. if header matches the following, extract the full email # address from the match: # # for <[a-z0-9]+-[a-z0-9]+.*>; # # 2. if the extracted email address is also found in any of the # To/Cc, extract the portion before @ as the name of alias # # (3. BTW, if step 2 fails, the mesage is very likely an ube) # :0 * LIST ?? ^^^^ *$ for($SPCL)+[<]()\/[a-z0-9]+-[a-z0-9]$S+@ { tmp = $MATCH :0 *$ (To|CC):\/.*$MATCH { unique_from = $MATCH LIST = $tmp } } # ...................................................... experiments ... # Many times domain name has server "list" if it's running mailing list # Try to catch some of them if previous ones failed. dummy = "pm-jalist.rc: :::::::::::::::::::::::: Last try [$LIST]" :0 * LIST ?? ^^^^ { :0 * ()\/list server.* { dummy = "pm-jalist.rc: ==== potential list ==== $MATCH" } :0 E *$ ()\/(From|X-From-Line|Sender:|CC:|To:).*\.lists?.*\ |(From|X-From-Line|Sender:|CC:|To:).* list$S*@.* { dummy = "pm-jalist.rc: ==== potential list ==== $NL $MATCH" } :0 E * ()\/(From|Sender:|CC:).*(Majordomo|listserv).* { dummy = "pm-jalist.rc: ==== potential list ==== $NL $MATCH" } :0 E * ()\/Errors-To:.* { dummy = "pm-jalist.rc: ==== potential list ==== $MATCH" } :0 E *$ ()\/^Reply-To:(.*\ :0 *$ ^Reply-To.*list@\/$a+ { LIST = list-$MATCH } } :0 E * ()\/^Subject.*\ { dummy = "pm-jalist.rc: ==== potential list ==== $MATCH" } :0 E * ()\/Mailing-list:.* { dummy = "pm-jalist.rc: ==== potential list ==== $MATCH" } } # ............................................................ clean ... dummy = "pm-jalist.rc: Cleaning matched list: ($LIST)" :0 * ! LIST ?? ^^^^ { :0 # delete "@" from the end of string * LIST ?? @ * LIST ?? ^^\/[^@]+ { LIST = $MATCH } :0 # delete "mailto:" from the beginning of string * LIST ?? mailto:\/.* { LIST = $MATCH } # Remove numbers # mailto:leave-jscript-146465L --> mailto:leave-jscript # 1. Check if it has numbers at the end # 2. Match everything until last - # 3. Remove last - :0 * LIST ?? ().*[-][0-9]+.^^ * LIST ?? ()\/.*[-] * MATCH ?? ()\/.*[^-] { LIST = $MATCH } # ................................................. postfix deletion ... # The regexp says: # 1) see if these keywords are there # 2) Read everything up till last dash and store it to MATCH # 3) Match up till not including final dash :0 *$ LIST ?? ()-${JA_LIST_KILL_POSTFIX}^^ * LIST ?? ^^\/.*- * MATCH ?? ^^\/.*[^-] { LIST = $MATCH } # .............................................. prefix deletion ... dummy = "pm-jalist.rc: prefix deletion" :0 *$ LIST ?? ^^${JA_LIST_KILL_PREFIX}-\/.* { LIST = $MATCH } # ....................................................... unique ... dummy = "pm-jalist.rc: make unique list name: $NL$NL $unique_from" :0 *$ LIST ?? $JA_LIST_MAKE_UNIQUE *$ $SUPREME^0 unique_from ?? ()\/$abc+@$abc+ *$ $SUPREME^0 ^()\/$from.*${pfx}$abc+@$abc+ { host = $MATCH save = $VERBOSE VERBOSE = "off" INPUT = $host INCLUDERC = $rc_email VERBOSE = "$save" # list.shopguidenews.com, we can't accept "list" as match, so we # use "shopguidenews" :0 * SUB1 ?? [a-z] { LIST = $SUB1-$LIST } :0 E { LIST = $host-$LIST } } # ............................................. converting list name ... dummy = "pm-jalist.rc: :::::::::::::::::::::::: List conversion" LIST_DETECTED = $LIST dummy = "pm-jalist.rc: Searching for conversion in array JA_LIST_CONVERSION" dummy = $JA_LIST_CONVERSION :0 *$ JA_LIST_CONVERSION ?? $LIST$s+\/[^$WSPC,]+ { LIST = $MATCH } :0 * JA_LIST_SAVE ?? yes { :0 fhw | ${FORMAIL:-formail} \ -I "X-List-Detected: $LIST_DETECTED mapped to $LIST" } } dummy = "pm-jalist.rc: end: grabbed list ($LIST)" # end of file pm-jalist.rc procmail-lib-2009.1202/lib/pm-jamime-decode.rc000066400000000000000000000216511130547513300206030ustar00rootroot00000000000000# pm-jamime-decode.rc -- decode MIME body contents; quoted-printable, base64 # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Documentation # # The original father of the decoding scheme used here was # presented by Peter Galbraith in # procmail mailing list somewhere at the end of 1997. # # This subroutine supposes that the header has MIME header # Content-Type: text/plain and performs quoted-printable or # base64 decoding on the whole message. Note, that if you # receive messages that have many mime attachments, then this # recipe is not suitable for it. # # Procmail is *not* designed to handle mime attachments and this # recipe only applies to whole _body_. # # The `pm-jamime-*.rc' is really stretching the limits and any # serious work should be delegated to other tools. Alternatives: # # o A Perl MIME module which will allow you to manipulate MIME # body parts rather elegantly. See # http://www.perl.com/CPAN-local/authors/Eryq/ for MIME-tools. # o mimedecode at ftp://ftp.dde.dk/pub/mimedecode.c # # Notes # # Perl or Python is not used, because both are CPU intensive. It # would be too expansive for accounts or environments receiving # hundreds of mails per day (like from several mailing lists). # # RFC 2047 gives possiblity to use MIME iso-8859-1 extensions # for mail headers. # # Subject: Re: [PIC]: RSA =?iso-8859-1?Q?encryption=B7=B7?= # Subject: =?iso-8859-1?Q?=5BEE=5D:TV_&_video_IC=B4s_!!?= # # There is also base64 possibility (although rare): # # Subject: =?iso-8859-1?B?zvLi5fI6ICAgICAgTVBMQUIzLjQw?= # # In worst possible case there is even multiple ISO encoded # strings in subject. Yes, this is valid, the continued line # includes spaces at front to keep it with original just like # in `Received:' headers. This subroutine will not touch headers # that have multiple ISO tags - procmail is too limited for that. # # Subject: AW: Re: AW: neue =3D?ISO-8859-1?Q?M=3DF6glichkeiten_=3D28was_=3D=C4hn?=3D # =3D?ISO-8859-1?Q?lichkeiten_von_=3DDCbungen=3D29?=3D # # Required settings # # Variable `PMSRC' must point to source directory of procmail code. # This subroutine will include # # o pm-javar.rc, pm-jamime.rc # o Programs `$MIME_BIN', `$MIME_BIN_QP' and `$MIME_BIN_64' # must have been installed (see pm-javar.rc). # # Call arguments (variables to set before calling) # # o `JA_MIME_DECODE_TREAT_SUBJECT', default "yes". Decode # Subject header by removing mime. # o `JA_MIME_DECODE_TREAT_FROM', default "no". Decode # From header by removing mime. # o `JA_MIME_DECODE_TREAT_BODY', default "no". Decode # body of message by removing quoted-printable from a # message that contains only one part. Messages with multiple # parts are not handled. # # Return values # # o `PM_JAMIME_COMPLEX_SUBJECT' is set to "yes". # This flag is set to indicate that some other program # should handle the message. If Subject header contains ISO # encoding several times, it cannot be handled by this module. # # Examples # # Instead of testing the existence of text/plain in the body, # you can force decoding by settings JA_MIME_DECODE_REGEXP to # ".*". # # RC_MIME_DECODE = $PMSRC/pm-jamime-decode.rc # # :0 # * condition # { # JA_MIME_DECODE_REGEXP = ".*" # } # # INCLUDERC = $RC_MIME_DECODE # call subroutine. # # # Change Log (none) dummy = " ======================================================================== pm-jamime-decode.rc: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } :0 * ! MIME_VER ?? [0-9] { INCLUDERC = $PMSRC/pm-jamime.rc } # .......................................................... &public ... # User configurable sections JA_MIME_DECODE_TREAT_SUBJECT = "yes" # Set to "no" to disable JA_MIME_DECODE_TREAT_FROM = "no" # Set to "yes" to enable JA_MIME_DECODE_TREAT_BODY = "no" # Set to "yes" to enable JA_MIME_DECODE_REGEXP = ${JA_MIME_DECODE_REGEXP:-\ "^Content-Type: *text/plain"} # ........................................................... &do-it ... # Run conversion if it was quoted printable. # Also reflect correct MIME header JA_MIME_DECODE_HEADER = ${JA_MIME_DECODE_HEADER:-\ "X-Mime-Header-Decoded"} dummy = "pm-jamime-decode.rc: handle quoted printable" PM_JAMIME_COMPLEX_SUBJECT # Return value if too complex subject jamimeHandledSubject = "no" # Kill variables jamimeSubject jamimeSubjectRest :0 * JA_MIME_DECODE_TREAT_SUBJECT ?? yes * ^Subject: \/.* { jamimeSubject = $MATCH jamimeISO = "\?iso-8859-[1-9]\?[QB]\?.+\?=" :0 *$ jamimeSubject ?? $jamimeISO()\/.* { # ".*" is actually minimum match. See pm-doc.sf.net jamimeSubjectRest = $MATCH } :0 *$ jamimeSubjectRest ?? $jamimeISO() { # This Subejct line contains ISO encoding several times. # This is out of our league. Can't hanle it, so quit. jamimeSubject JAMIME_COMPLEX_SUBJECT = "yes" } } :0 * ! jamimeSubject ?? ^^^^ { str = $jamimeSubject decoder = $MIME_BIN_QP type = "quoted-printable" :0 * ^Subject:.*\?B\? { type = "base64" decoder = $MIME_BIN_64 } # NOTE "?" is not wildcard "as is" in sed. clean = \ ` echo "$str" \ | $SED \ -e 's/^\(.*\)?\(iso\|ISO\)-\{0,1\}8859-[1-9]?[QB]?\(.*[^?]\)?=/\1\2/g' \ -e 's/=0D//g' \ -e 's/=0A//g' \ -e 's/=B7//g' \ -e 's/_/ /g' \ | $decoder ` handledSubject = "yes" :0 fhw * ! clean ?? ^^^^ | $FORMAIL \ -i "Subject: $clean" \ -I "${JA_MIME_DECODE_HEADER}-Subject: $type" } # Too bad Procmail does not have subroutines. This recipe is # identical to "Subject" check above. # # Note, that 'From' header is different from the 'Subject' header # in respect to the ISO encoding. Look closely where '?=' ends: # # Subject: =?ISO-8859-1?Q?=C4hnlichkeiten_von_=DCbungen?= # From: =?ISO-8859-1?Q?Holger_Hoffst=E4tte?= jamimeHandledFrom = "no" :0 * JA_MIME_DECODE_TREAT_FROM ?? yes *$ ^From: +()\/=\?iso-8859-[1-9]\?[QB]\?.+\?=.* *$ ^From: +()\/.*=\?.+[>] { str = $MATCH decoder = $MIME_BIN_QP type = "quoted-printable" :0 * ^Subject:.*\?B\? { type = "base64" decoder = $MIME_BIN_64 } clean = \ ` echo "$str" \ | $SED \ -e 's/=?\(iso\|ISO\)-\{0,1\}8859-[1-9]?[QB]?\(.*[^?]\)?=/\2/g' \ -e 's/=0D//g' \ -e 's/=0A//g' \ -e 's/=B7//g' \ | $decoder ` jamimeHandledFrom = "yes" # Make sure there is before replacing anything :0 fhw * clean ?? [>] | $FORMAIL \ -i "From: $clean" \ -i "${JA_MIME_DECODE_HEADER}-From: $type" } # Touch only real mime messages and text/plain # $MIME_BIN_QP does not handle separate MIME sections :0 * JA_MIME_DECODE_TREAT_BODY ?? yes *$ $JA_MIME_DECODE_REGEXP { :0 fbw * ^Content-Transfer-Encoding: *quoted-printable | $MIME_BIN_QP :0 A fhw | $FORMAIL -I "Content-Transfer-Encoding: 8bit" :0 fbw * ^Content-Transfer-Encoding: *base64 | $MIME_BIN_64 :0 A fhw | $FORMAIL -I "Content-Transfer-Encoding: 8bit" } dummy = "pm-jamime-decode.rc: end:" # End of file pm-jamime-decode.rc procmail-lib-2009.1202/lib/pm-jamime-kill.rc000066400000000000000000000635211130547513300203150ustar00rootroot00000000000000# pm-jamime-kill.rc -- General MIME attachment killer (vcards, html) # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # Note: If you think this module can do miracles, it cannot. # MIME messages are very complex in structure and all this module # can do is to detect *simple* attachements. It cannot be used # as - all purpose - all detecting - MIME attachement killer. # But the part it can do, is done efficiently, because most of the # things are accomplished using procmail and resource friendly # `awk'. # # There are meny programs that add additional information to the # messages. Microsoft's mail program is one which may include # a 7k application/ms-tnef attachment to the end of # message. Many other programs may do the same. This was the idea # in 1997 when this module was written; to get rid of the extra # cruft which should not land in the mailbox. # # This recipe works like this: If email's structure is # # --boundary # message-text (maybe quoted-printable) # --boundary # some-unwanted-mime-attachment # --boundary # # then the attachment is killed from the body. The message-text part # is also decoded if it was quoted printable. This leaves clean text # with no MIME anywhere. MIME headers have will be modified as needed # due to conversion from multi part and possibly quoted printable to # plain text and the final message looks like: # # message # # But if email's structure is anything else, like if there were 3 # mime sections: # # --boundary # message-text (maybe quoted-printable) # --boundary # some-attachment # --boundary # some-unwanted-mime-attachment # --boundary # # then the "unwanted" part is emptyed by replacing with one empty # line. The message structure stays the same, but the killed # "some-unwanted-mime-attachment" part is labelled as text/plain # so that the MUA (Mail User Agent; the email reader program) # can decode the MIME message correctly. # # Applications for other mime attachments # # The following cases are ncluded on in this module. You need to # separately the behavior before this module will start working. # # o Lotus Notes attachment. # o Microsoft Express attachement. It sends a copy of message in HTML # format. # o Mozilla's Netscape attachement. It sends a copy of message in HTML. # o `Vcard' attachments. # o Openmail attachment. It sends 10-20 line base64 attachments # WINMAIL.DAT. # # Example of lotus notes attachment # # Subject: message # From: foo@bar.com # X-Lotus-FromDomain: XXX COMPANIES # Mime-Version: 1.0 # Boundary="0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw" # Content-Type: multipart/mixed; # Boundary="0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw" # # --0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw # Content-type: application/octet-stream; # name="PIC10898.PCX" # Content-transfer-encoding: base64 # # eJ8+IjsQAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcA # b3NvZnQgTWFpbC5Ob3RlADEIAQ2ABAACAAAAAgACAAEEkAYAyAEAAAEAAAAQ # # # # --0__=cieg4oHxUNf2h3evyOXIsHTGDpFfaZilTDCFhpZSgsw-- # # Example of MS Explorer's ms-tnef message # # Subject: message # From: foo@bar.com # MIME-Version: 1.0 # Content-Type: multipart/mixed; # boundary="---- =_NextPart_000_01BD04D4.A5AC6B00" # Lines: 158 # # ------ =_NextPart_000_01BD04D4.A5AC6B00 # Content-Type: text/plain; charset="iso-8859-1" # Content-Transfer-Encoding: quoted-printable # # # # ------ =_NextPart_000_01BD04D4.A5AC6B00 # Content-Type: application/ms-tnef # Content-Transfer-Encoding: base64 # # eJ8+IjsQAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcA # b3NvZnQgTWFpbC5Ob3RlADEIAQ2ABAACAAAAAgACAAEEkAYAyAEAAAEAAAAQ # # # # ------ =_NextPart_000_01BD04D4.A5AC6B00-- # # Example of MS Express's HTML message # # MIME-Version: 1.0 # Content-Type: multipart/alternative; # boundary="----=_NextPart_000_003A_01BD16E2.C97E27B0" # X-Mailer: Microsoft Outlook Express 4.72.2106.4 # X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2106.4 # # This is a multi-part message in MIME format. # # ------=_NextPart_000_003A_01BD16E2.C97E27B0 # Content-Type: text/plain; # charset="iso-8859-1" # Content-Transfer-Encoding: quoted-printable # # # # ------=_NextPart_000_003A_01BD16E2.C97E27B0 # Content-Type: text/html; # charset="iso-8859-1" # Content-Transfer-Encoding: quoted-printable # # # ------=_NextPart_000_003A_01BD16E2.C97E27B0-- # # Example of Netscape's HTML attachment # # X-Mailer: Mozilla 4.04 [en] (X11; U; Linux 2.0.33 i686) # MIME-Version: 1.0 # Content-Type: multipart/alternative; # boundary="------------69D9D579CF587DC8BB26C49C" # # # --------------69D9D579CF587DC8BB26C49C # Content-Type: text/plain; charset=us-ascii # Content-Transfer-Encoding: 7bit # # # # --------------69D9D579CF587DC8BB26C49C # Content-Type: text/html; charset=us-ascii # Content-Transfer-Encoding: 7bit # # # --------------69D9D579CF587DC8BB26C49C-- # # Example of Netscape's vcard attachment. # # Content-Type: text/x-vcard; charset=us-ascii; name="vcard.vcf" # Content-Transfer-Encoding: 7bit # Content-Description: Card for Laird Nelson # Content-Disposition: attachment; filename="vcard.vcf" # # begin: vcard # fn: Laird Nelson # n: Nelson;Laird # org: Perot Systems Corporation # adr: 101 Main Street;;;Cambridge;MA;02142;USA # email;internet: ljnelson@unix.amherst.edu # title: Software Engineer # tel;work: (617) 303-5059 # tel;fax: (617) 303-5293 # tel;home: (978) 741-3126 # note;quoted-printable:Information is for reference only;=0D=0A= # please do not abuse it. # x-mozilla-cpt: ;0 # x-mozilla-html: TRUE # version: 2.1 # end: vcard # # Required settings # # To handle base64 encoded messages, package called `metamail' must # have been installed to system. It provides program `mimencode' # which is used through variable $MIME_BIN (see pm-javar.rc). # # Variable $PMSRC must point to source directory of procmail code. # This subroutine will include # # o pm-javar.rc # o pm-jamime.rc # # Call arguments (variables to set before calling) # # First of all, this is primarily a framework recipe to kill any kind # of attachment. If you do not set `JA_MIME_TYPE' before calling # this recipe, recipe will try to determine the right value by itself. # If the automatic detection fails you _need_ to preset the value # of `JA_MIME_TYPE' beforehand. # # o `JA_MIME_TYPE' is a case sensitive AWK *REGEXP*. Always use # *lowercase* letters in this regexp because the line is lowercased # before match is made. This regexp determines if the kill # recipe is applied to the message or not. Suggested default # value: "text/html". If empty (not set), the heuristics # tries to set it for MS explorer, MS express, Netscape, # Lotus Notes etc. # o `JA_MIME_KILL_RE', additional *REGEXP* to kill lines from the # message. Value is case sensitive awk regexp and by default matches # Lotus notes tag: name="XXX.PCX". # o `JA_MIME_EXTRA_HEADER', name of header added to the message # if the MIME portion was killed. Default value is # "X-Mime-Type-Killed". # # It may be possible that some messages are malformed and that # they do not contain proper "boundary" definition string in the # header. There have been messages that have text/html # attachments, but no proper Mime headers. For those cases there # is additional variable that will kill all text up till # matching line regardless of message content. # # o `JA_MIME_KILL2_RE' is set to "text/html|application/ms-tnef". # Update this to match attchements you receive. Set variable to # "" if you don't want to change the body of non-compliant MIME # message. # # That variable is the last resort if the standard MIME detection # failed. There must have been some problem in the sender's MUA that # composed message. It's dangerous, so make sure you don't set it # lightly. # # Possible conflict with the awk # # If you see an error message in the log file saying that awk failed: # # procmail: Executing awk, # ... # procmail: Error while writing to "awk" # procmail: Rescue of unfiltered data succeeded # # it means that the system's standard `awk' doesn't support the # variable passing syntax. Do the following test: # # % awk '{print VAR; exit}' VAR="value" /etc/passwd # # It should print "value". If not, then see if you have `gawk' or # `mawk' in the system. Try whcih awk understands the variable passing # syntax. The only change needed is to define variable AWK # somewhere at the top of `~/.procmailrc'. # # AWK = "gawk" # Better than standard "awk" # # WARNING: In some systems the `gawk' is not real GNU awk, but a # symlink to somewhere alse. E.g. in SunOs/Solaris you may find this # setup, which is unsufficient. For Solaris, the GNU awk is available # at http://www.blastwave.org # # $ which gawk # $ gawk --version # # $ ls -l /usr/local/bin/gawk # /usr/local/bin/gawk -> /usr/bin/nawk # # Warnings # # You should know that the variable `JA_MIME_KILL_RE' is used to wipe # any lines that match that regexp. This is due to MIME structure # where continuing header lines exist in the body: # # ------=_NextPart_000_003A_01BD16E2.C97E27B0 # Content-Type: text/plain; # charset="iso-8859-1" << kill this line too # # If you want to be absolutely sure that anything valuable won't be # accidentally killed (like a code line in programming language scripts), # you should set this variable to nonsense value that newer matches: # # JA_MIME_KILL_RE = "match_it_never_I_hope" # # Usage example: Customizing the attachment killing # # Suppose you receive new `application/ms' type attachment that the # default settings doesn't cover. This is a new mime type and you # have to instruct this module to kill it. Add this and similar # tests for other mime types: # # myCustomMimeType = "application/ms" # must be all lowercase # # :0 # *$ $myCustomMimeType # { # PM_JA_MIME_TYPE = $myCustomMimeType # } # # INCLUDERC = $PMSRC/pm-jamime-kill.rc # # Usage example # # To kill text/html or pdf, postscript and others add something # like this to `~/.procmailrc'. It demonstrates how the correct # MIME types are detected: # # # ..................................................... # # 1) Uncomment following line if your standard "awk" is broken # # # AWK = "gawk" # # # ..................................................... # # 2) Set correct value for attachment killing # # :0 # * ^X-Lotus-FromDomain: # { # # Kill Lotus notes .pcx attachments # JA_MIME_TYPE = "application/octet-stream" # } # # :0 # * H ?? ^From:.*foo@example.com # * B ?? ^Content-Type:.*text/html # { # # Kill html attachments # JA_MIME_TYPE = "text/html" # } # # # ..................................................... # # 3) Call module # # INCLUDERC = $PMSRC/pm-jamime-kill.rc # # Change Log (none) # .................................................... &initialising ... id = "pm-jamime-kill.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } :0 * ! MIME_VER ?? [0-9] { INCLUDERC = $PMSRC/pm-jamime.rc } # .......................................................... &public ... # User configurable sections # If linebuf is too small, then AWK scripts can't be called JA_MIME_KILL_LINEBUF = ${JA_MIME_KILL_LINEBUF:-524280} JA_MIME_KILL_RE = ${JA_MIME_KILL_RE:-"\ name=.*(pcx|PCX)|charset=|This is.*MIME"} JA_MIME_KILL2_RE = ${JA_MIME_KILL2_RE:-"\ Content-Type: +(text/html|application/ms-tnef|x-vcard)"} # If set, this header will contain the MIME type ("text/html" etc.) # which was killed JA_MIME_EXTRA_HEADER = ${JA_MIME_EXTRA_HEADER:-"X-Mime-Type-Killed"} # .................................................... &set-defaults ... # Set default value, unless user has set this previously. :0 * JA_MIME_TYPE ?? ^^^^ { dummy = "$id: automatic JA_MIME_TYPE detection" # The (safe) default value. Will be changed below JA_MIME_TYPE = "application/ms-tnef" :0 * ^Content-Type:.*image/()\/(jpeg|tiff|png|gif|bmp) { JA_MIME_TYPE = "image/$MATCH" } :0 E * ^X-Lotus-FromDomain: { JA_MIME_TYPE = "application/octet-stream" dummy = "$id: Type: Lotus Notes" } :0 E * ^X-Mailer: (Microsoft.*Express|mozilla) { JA_MIME_TYPE = "text/html" dummy = "$id: Type: MS Express,Netscape" } :0 E * ^X-Mailer:.*mozilla * B ?? begin:.*vcard { JA_MIME_TYPE = "text/x-vcard" dummy = "$id: Type: Netscape vcard" } :0 E * B ?? application/x-openmail { JA_MIME_TYPE = "application/x-openmail" dummy = "$id: Openmail attachment found" } # Remove executables :0 E * B ?? application/x-msdownload * MIME_B_ATTACHMENT ?? \.(hqx|com|exe|pif) { JA_MIME_TYPE = "application/x-msdownload" dummy = "$id: MS *.exe attachment found" } } # - If user set JA_MIME_KILL_RE, make sure that value is not empty, # because awk doesn't like empty regexps # - Subtitute the value with something that doesn't match. :0 *$ JA_MIME_KILL_RE ?? ^^^^ { JA_MIME_KILL_RE = "_do_not___match_" } :0 # This must have value *! LINEBUF ?? [0-9] { LINEBUF = 8192 } jaMimeKillLINEBUF = $LINEBUF # save old value # ........................................................... &do-it ... # Prevent calling sh -c here. This speeds up procmail jaMimeKillSHELLMETAS = $SHELLMETAS # save original value jaMimeKillModified = "no" # Flag jaMimeKillMsg # Kill variable SHELLMETAS # kill variable dummy = "JA_MIME_TYPE [$JA_MIME_TYPE]" dummy = "MIME_BOUNDARY [$MIME_BOUNDARY]" dummy = "Check if running the kill recipe, SHELL= $SHELL" :0 * ! JA_MIME_TYPE ?? ^^^^ * ! MIME_BOUNDARY ?? ^^^^ * H ?? ^Content-Type:.*multipart *$ B ?? ^Content-Type:$s+$JA_MIME_TYPE { # If there were only 3 mime tags, then then message is in format # # boundary-tag # message # boundary-tag # unwanted-mime-part # boundary-tag # # a) make sure count is 3 # b) make sure we have the boundary string LINEBUF = $JA_MIME_KILL_LINEBUF :0 * MIME_BOUNDARY_COUNT ?? ^^3^^ { dummy = "$NL$NL$id: exactly 3 boundary strings" # - AWK removes the mime boundary strings, so we must remember # if the message had quoted printable. The variable MIME_B_QP # contain the qp information. # # Program logic (effectively a state machine) # - First blank line is header end. Print header verbatim. # - Keep track of seen boundaries: 1, 2, 3 # - When EAT (text/html) portion is found, kill text up # till next boundary marker # # We need the "i" flag because awk quits before it has read # all the input :0 fbw i | $AWK \ ' \ /^[ \t]*$/ { \ print; \ header = 0; \ } \ \ header { \ print; \ next; \ } \ \ $0 ~ RE { \ boundary++; \ } \ \ { \ if ( killUntil ) \ { \ if ( boundary < killUntil ) \ { \ next; \ } \ killUntil = 0; \ } \ \ line = tolower($0); \ \ if ( ! found && match($0, EAT) > 0 ) \ { \ found++; \ killUntil = boundary + 1; \ } \ \ if ( match($0, RE) > 0 ) {next} \ if ( match($0, KILL) > 0 ) {next} \ if ( match($0, "^Content-") > 0 ) {next} \ \ print; \ } \ ' RE="$MIME_BOUNDARY" \ EAT="^Content-Type:.*$JA_MIME_TYPE" \ KILL="$JA_MIME_KILL_RE" # -- If AWK succeeded -- # The body is no more multipart/mixed. Correct headers or # the MUA may get confused :0 a { # Why Rewrite Mime-Version: # # Lotus notes adds the boundary string to this header, but # because we have already removed all boundary strings from the # body, we must clear this header. # # Call to replace Mime-Version header wipes the `boundary=` tag :0 fhw | $FORMAIL \ -I "Content-Type: text/plain" \ -I "Mime-Version: $MIME_VER" jaMimeKillMsg = "$JA_MIME_TYPE" jaMimeKillModified = "yes" # Yes, we changed body } } # Note: 1997-12-30 # # - This works fine for ms-tnef, but it may be dangerous with # Lotus notes, because it's attachment is a general # "application/octec-stream". # - Report me the problems if you encounter them with Lotus Notes. # # There was more than 2 mime parts: just remove the base64 block. # # - raise suppress flag if we find mime. Also change the mime type. # - set flag back to 0 when the ending tag is found # - print the lines when flag is 0 # # The ms-tnef is now converted to: # # ------ NextPart_000_01BD04D4.A5AC6B00 # Content-Type: text/plain; # # ------ NextPart_000_01BD04D4.A5AC6B00-- # dummy = "$NL$NL$id: _not_ exactly 3 boundary strings" :0 fbw * ! MIME_BOUNDARY_COUNT ?? ^^3^^ | $AWK \ ' { \ line = tolower($0); \ \ if ( match(line, HDR) > 0 ) \ { \ flag = 1; \ print "Content-Type: text/plain;"; \ } \ \ if ( match($0, RE) ) \ { \ flag = 0; \ } \ \ if ( flag == 0 ) \ { \ print; \ } \ } \ ' RE="$MIME_BOUNDARY" HDR="$JA_MIME_TYPE" LINEBUF = $jaMimeKillLINEBUF } # ..................................................... &invalid-mime ... # This is last resort, if message looks like MIME, but it isn't # because it doesn't have headers: # # MIME-Version: 1.0 # Content-Type: multipart/alternative; boundary="...." dummy = "$NL$NL$id: last resort, kill up till regexp" # Non-mime compliant messages # # The only way to kill attachment is to use approximation. # If we do not have the boundary string (i.e. this not mime), # then apply this recipe. dummy = "$id: MIME_BOUNDARY $MIME_BOUNDARY" :0 * MIME_BOUNDARY ?? ^^^^ * JA_MIME_KILL2_RE ?? [a-z] *$ B ?? $JA_MIME_KILL2_RE { LINEBUF = $JA_MIME_KILL_LINEBUF # Well we could use SED here, but then there is a problem with # "/" delimiter in sed. The awk solution accepts REGEXP as is # as you don't have to play with funny quoting # # sed -e "'"/$regexp/q"'" # # or something like that... (the above is untested) :0 fbw | $AWK \ ' { \ if ( match($0,RE) > 0 ) {exit} \ print \ } \ ' RE="$JA_MIME_KILL2_RE" :0 A { jaMimeKillMsg = "Forced kill by JA_MIME_KILL2_RE" jaMimeKillModified = "yes" } LINEBUF = $jaMimeKillLINEBUF } # ............................................................... &qp ... # Run conversion if it was quoted printable. # Also reflect correct MIME header dummy = "$id: handle quoted printable" :0 fhw * jaMimeKillModified ?? yes * ! jaMimeKillMsg ?? ^^^^ * ! JA_MIME_EXTRA_HEADER ?? ^^^^ | $FORMAIL -I "$JA_MIME_EXTRA_HEADER: $jaMimeKillMsg" :0 fbw * jaMimeKillModified ?? yes * MIME_B_QP ?? yes * MIME_BIN_QP ?? [a-z] | $MIME_BIN_QP # If the previous recipe succeeded, then fix the headers to indicate # decoding. :0 A fhw | $FORMAIL -I "Content-Transfer-Encoding: 8bit" SHELLMETAS = $jaMimeKillSHELLMETAS # Restore original value dummy = "$id: end:" # end of file pm-jamime-kill.rc procmail-lib-2009.1202/lib/pm-jamime-recode.rc000066400000000000000000000125041130547513300206160ustar00rootroot00000000000000# pm-jamime-recode.rc -- re-encode MIME Header: Subject, From as quoted-printable # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Documentation # # This subroutine supposes that message has been handled by # 'pm-jamime-decode.rc'. The purpose is to restore *Subject* and # *From* headers back to quoted printable format so that # messages can be savely saved through IMAP system which may not # handle 8-bit messages. If message is stored directly to # mailbox and the used Mail user Agent has no problems with # dealing 8-bit characters, this module is not needed. # # An example where this subroutine could be applied: # # o Feed message to `pm-jamime-decode.rc' # o Feed message `pm-jasubject.rc' (to clean multiple Re: Re: Fwd ..) # o Restore From/Subject encodings with `pm-jamime-recode.rc' # o Save message to mailbox # # Notes # # Perl or python is not used, because both are CPU intensive. # It would be too expansive for accounts or environments # receiving hundreds of mails per day (like from several mailing # lists). # # Required settings # # Variable `PMSRC' must point to source directory of procmail code. # This subroutine will include # # o pm-javar.rc # o pm-jamime.rc # o Program `$MIME_BIN_QP_E' # must have been installed (see pm-javar.rc). # o pm-jamine-decode.rc must have been called and message must # contain headers `X-Mime-Header-Decoded-*' # # Call arguments (variables to set before calling) # # o `JA_MIME_RECODE_TREAT_SUBJECT', default "yes". Decode # Subject header by removing mime. # o `JA_MIME_RECODE_TREAT_FROM', default "no". Decode # From header by removing mime. # # Return values # # (none) # # Examples # # To fix Subject header and then make it 7bit clean again. Note, # this may not be exactly what you want. The pm-jamime-decode.rc # file does a little more than From/Header handling (also modifies # message body). Read documentation of each file before using # following example # # INCLUDERC = $PMSRC/pm-jasubject.rc # INCLUDERC = $PMSRC/pm-jamime-decode.rc # INCLUDERC = $PMSRC/pm-jamime-recode.rc # # Change Log (none) dummy = " ======================================================================== pm-jamime-recode.rc: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } :0 * ! MIME_VER ?? [0-9] { INCLUDERC = $PMSRC/pm-jamime.rc } # .......................................................... &public ... # User configurable sections JA_MIME_RECODE_REGEXP = ${JA_MIME_RECODE_REGEXP:-\ "^Content-Type: *text/plain"} JA_MIME_RECODE_TREAT_SUBJECT = "yes" # Set to "no" to disable JA_MIME_RECODE_TREAT_FROM = "no" # Set to "yes" to enable # ........................................................... &do-it ... # Run conversion if it was quoted printable. # Also reflect correct MIME header # Must be same header than in pm-jamime-decode.rc JA_MIME_RECODE_HEADER = "X-Mime-Header-Decoded" JA_MIME_RECODE_HEADER_SUBJECT = ${JA_MIME_RECODE_HEADER}-Subject JA_MIME_RECODE_HEADER_FROM = ${JA_MIME_RECODE_HEADER}-From # Hard coded, do not change. We DO not know what chacters are in there, # so we just use this encoding stanza and hope for the best. JA_MIME_RECODE_CHARSET_BEG = "=?iso-8859-1-?Q?" JA_MIME_RECODE_CHARSET_END = "?=" dummy = "pm-jamime-recode.rc: handle quoted printable" handledSubject = "no" :0 * JA_MIME_RECODE_TREAT_SUBJECT ?? yes *$ ^$JA_MIME_RECODE_HEADER_SUBJECT * ^Subject: +\/.* { str = $MATCH bin = $MIME_BIN_QP_E beg = $JA_MIME_RECODE_CHARSET_BEG end = $JA_MIME_RECODE_CHARSET_END # NOTE: not all sed (SunOS) know \t shortcuts. new = \ ` echo "$str" \ | $bin \ | ${SED:-sed} \ -e "s/^\(.*\)$/$beg\\1$end/" \ -e 's/ /_/g' \ ` handledSubject = "yes" :0 fhw * ! new ?? ^^^^ | $FORMAIL \ -I "Subject: $new" \ -I "$JA_MIME_RECODE_HEADER_SUBJECT:" } # This part is identical to above (Procmail does not have subroutines) handledFrom = "yes" :0 * JA_MIME_RECODE_TREAT_FROM ?? yes *$ ^$JA_MIME_RECODE_HEADER_FROM * ^From: +\/.* { str = $MATCH bin = $MIME_BIN_QP_E beg = $JA_MIME_RECODE_CHARSET_BEG end = $JA_MIME_RECODE_CHARSET_END new = \ ` echo "$str" \ | $bin \ | ${SED:-sed} \ -e "s/^\(.*\)$/$beg\\1$end/" \ -e 's/ /_/g' \ ` handledFrom = "yes" :0 fhw * ! new ?? ^^^^ | $FORMAIL \ -I "From: $new" \ -I "$JA_MIME_RECODE_HEADER_FROM:" } dummy = "pm-jamime-recode.rc: end:" # End of file pm-jamime-recode.rc procmail-lib-2009.1202/lib/pm-jamime-save.rc000066400000000000000000000405771130547513300203260ustar00rootroot00000000000000# pm-jamime-save.rc -- save message's MIME attachement (one file) to a file # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Documentation # # This module saves _one_ simple file attachment (MIME) from he # message. The message must define following MIME headers. If # "filename=" does not exists, then the message is ignored. # # Mime-Version: # Content-Type: # Content-Disposition: attachment; filename="file.txt" # # The last line can also be in separate line, provided that it # is indented according to standard rules: # # Mime-Version: # Content-Type: # Content-Disposition: attachment; # filename="file.txt" # # Procmail is not very suitable for saving MIME attachments and # you should not think that this the right tool for you. # If you receive anything more than 1 attachment, this recipe # does nothing, because that's out of our league and you need some # more heavy weight mime tools. E.g. Perl CPAN has MIME libraries. # # _Note_: when the attachment is in the body, it is simply written # to a disk and the location in message is replaced with test: # # Extracted to file:/users/foo/junk/.file.txt. # # The existing mime headers that surround the attachment are # lect untouched, so don't try to press your Mail Agent's MIME buttons # at that point. There is no such file in that spot # if you set `JA_MIME_SAVE_DEL' to `yes'. # # Required settings # # PMSRC must point to source directory of procmail code. This # subroutine includes library: # # o pm-javar.rc # o pm-jamime.rc # o pm-jamime-decode.rc # o pm-jadate.rc (which will call other pm-jadate*.rc files) # # Call arguments (variables to set before calling) # # o `JA_MIME_SAVE_DIR', point this to directory where you # want to store attachments. # o `JA_MIME_SAVE_DECODE', set this to "yes", if you want that # attachment is decoded before written to disk. This usually # opens quoted printable or base64 encoding. # o `JA_MIME_SAVE_DEL', set this to "yes", if you want to remove # the attachment from the body of the message after it has # been filed. Be vary careful if you use this option. If you # keep backup cache of incoming mail, then you might try "yes". # o `JA_MIME_SAVE_OVERWRITE', set this to "yes" if it's okay to # overwrite to an existing filename found from attachment. # If you get periodic attachments always with same name, then # you would want to set this to yes. # # Core dump note # # Because procmail uses LINEBUF when filtering messages, a core # dump may happen if the attachment being filtered is bigger than # the LINEBUF. The current setting accepts 524K attachments, but if # you expect to get bigger than that, you want to increase # `JA_MIME_SAVE_LINEBUF'. # # Possible conflict with your awk # # Awk is used because it is much more system load friendly than perl. # If you see an error message in the log file saying that awk failed: # # procmail: Executing awk, # ... # procmail: Error while writing to "awk" # procmail: Rescue of unfiltered data succeeded # # it means that the system's standard awk doesn't support the # variable passing syntax. To verify that this is the case, run # following test: # # % awk '{print VAR; exit}' VAR="value" /etc/passwd # # The proper awk should print "value". If not, then see if you have # `nawk' or `gawk' in your system, which should understand the # variable passing syntax. To change the AWK, you need to set # following variable somewhere at the top of your *.procmailrc* # # AWK = "gawk" # if that works better than standard "awk" # # Return values (none) # # Change Log (none) dummy = " ======================================================================== pm-jamime-save.rc: init:" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } :0 * ! MIME_VER ?? [0-9] { INCLUDERC = $RC_MIME } :0 * ! YYYY ?? [0-9] { INCLUDERC = $RC_DATE } :0 # if has no value, set it *$ ! LINEBUF ?? $d { LINEBUF = 1024 } jaMimeSaveLinebuf = $LINEBUF # .......................................................... &public ... # User configurable sections JA_MIME_SAVE_DIR = ${JA_MIME_SAVE_DIR:-"$HOME"} JA_MIME_SAVE_DECODE = ${JA_MIME_SAVE_DECODE:-"no"} JA_MIME_SAVE_DEL = ${JA_MIME_SAVE_DEL:-"no"} JA_MIME_SAVE_LINEBUF = ${JA_MIME_SAVE_LINEBUF:-524280} JA_MIME_SAVE_OVERWRITE = ${JA_MIME_SAVE_OVERWRITE:-"no"} # ........................................................... &do-it ... dummy = "pm-jamime-save.rc: HEADER; $MIME_H_ATTACHMENT" :0 * MIME_H_ATTACHMENT ?? [a-z] { jaMimeSaveFile = $MIME_H_ATTACHMENT :0 * JA_MIME_SAVE_DECODE ?? yes { # decode regardless of body content JA_MIME_DECODE_REGEXP = ".*" INCLUDERC = $RC_MIME_DECODE } # ..................................................... filename ... :0 * JA_MIME_SAVE_OVERWRITE ?? no *$ ? $IS_EXIST $JA_MIME_SAVE_DIR/$jaMimeSaveFile { # Kill variable jaMimeSaveDate :0 *$ YYYY ?? $d { jaMimeSaveDate = "$YYYY-$MM-$DD" :0 *$ hh ?? $d { jaMimeSaveDate = "$jaMimeSaveDate-$hh$mm" } jaMimeSaveFile = "$jaMimeSaveDate.$jaMimeSaveFile" # Still not unique? :0 *$ ? $IS_EXIST $JA_MIME_SAVE_DIR/$jaMimeSaveFile { :0 fhw | $FORMAIL -I "X-jaMimeSave-Error: (file exists) $jaMimeSaveFile" # kill variable to prevent next recipe from running jaMimeSaveFile } } } # .................................................... write out ... :0 * jaMimeSaveFile ?? [a-z] { :0 bwc: # do not modify body * JA_MIME_SAVE_DEL ?? no | $CAT > $JA_MIME_SAVE_DIR/$jaMimeSaveFile # Write out the attachment and replace body # with reference to the file. :0 E { :0 *$ LINEBUF ?? ^^([5-9]$d$d$d$d$d|$d$d$d$d$d$d$d)^^ { # User has set bigger linebuf than our default } :0 E { LINEBUF = $JA_MIME_SAVE_LINEBUF } :0 fbw: | ( $CAT > $JA_MIME_SAVE_DIR/$jaMimeSaveFile; echo "Saved to $JA_MIME_SAVE_DIR/$jaMimeSaveFile" ) LINEBUF = $jaMimeSaveLinebuf } } } dummy = "pm-jamime-save.rc: BODY check" :0 E * MIME_B_ATTACHMENT ?? [a-z] * MIME_B_ATTACHMENT_FILE_COUNT ?? ^^1^^ { dummy = "pm-jamime-save.rc: BODY ENTERED: only some limited operations." jaMimeSaveFile = $MIME_B_ATTACHMENT # Try to locate the header where the content type is defined for # file attachment. Note: there is no typo in the regexp, the # caret(^) matches newline. # # Content-Type: application/octet-stream # Content-Disposition: attachment; filename="file.txt" # Content-Transfer-Encoding: 7bit dummy = "pm-jamime-save.rc: Check contentType BODY 1" :0 *$ B ?? ^Content-Type:$s+\/.*\ ^Content-Disposition:.*($MIME_B_ATTACHMENT\ |^$s+.*$MIME_B_ATTACHMENT) * MATCH ?? \/.* { contentType = $MATCH } dummy = "pm-jamime-save.rc: Check contentType BODY 2" :0 E *$ B ?? ^Content-Type:$s+\/.*\ ^Content-Transfer-Encoding:.*\ ^Content-Disposition:.*($MIME_B_ATTACHMENT\ |^$s+.*$MIME_B_ATTACHMENT) * MATCH ?? \/.* { contentType = $MATCH # The last "Content-Disposition" match allows two cases # # 1. Content-Disposition: attachment; filename="file.txt" # # 2. Content-Disposition: attachment; # filename="file.txt" :0 *$ B ?? ^Content-Type:.*\ ^Content-Transfer-Encoding:$s\/.*\ ^Content-Disposition:.*($MIME_B_ATTACHMENT\ |^$s+.*$MIME_B_ATTACHMENT) * MATCH ?? \/.* { contentEncoding = $MATCH } } # We expect that the headers come in this order. # If they don't, then we can't know the encoding. # We don't even try anything else: Procmail is not the right tool # for complete MIME handling. dummy = "pm-jamime-save.rc: Check contentEncoding BODY" :0 * contentEncoding ?? ^^^^ *$ B ?? ^Content-Type:.*\ ^Content-Disposition:.*\ ^Content-Transfer-Encoding:$s+\/.* { contentEncoding = $MATCH } :0 E * contentEncoding ?? ^^^^ *$ B ?? ^Content-Type:.*\ ^Content-Transfer-Encoding:$s+\/.* { contentEncoding = $MATCH } :0 * contentEncoding ?? ^^^^ *$ B ?? ^Content-Type:.*\ ^Content-Transfer-Encoding:$s+\/.* { contentEncoding = $MATCH } # ............................................... fix mixed-part ... # In most typical message, sender "says" something in text/plain and # then adds an atatchement # # But, due to order of the MIME headers we may have picked the # text/plain. Change it to application/octet-stream if found. # # Mime-Version: 1.0 # Content-Type: multipart/mixed; boundary="----------118D218634724256" # # ------------118D218634724256 # Content-Type: text/plain; charset=us-ascii # Content-Transfer-Encoding: 7bit # # # ------------118D218634724256 # Content-Type: application/octet-stream; name="Ass_rake.dbf" # Content-Transfer-Encoding: base64 # Content-Disposition: attachment; filename="Ass_rake.dbf" dummy = "pm-jamime-save.rc: Check contentType ($contentType) text/plain => application" :0 * contentType ?? text/ *$ B ?? ^Content-Type:$s+\/application.* { contentType = $MATCH dummy = "pm-jamime-save.rc: finding Transfer-Encoding for application/*" :0 *$ B ?? ^Content-Type:$s+application.*\ ^Content-Transfer-Encoding:$s\/.* { contentEncoding = $MATCH } } # ............................................... check filename ... # Change filename if there is already that file dummy = "pm-jamime-save.rc: check filename" # Kill variable jaMimeSaveDate :0 *$ YYYY ?? $d { jaMimeSaveDate = "$YYYY-$MM-$DD" :0 *$ hh ?? $d { jaMimeSaveDate = "$jaMimeSaveDate-$hh$mm" } jaMimeSaveFile = "$jaMimeSaveDate.$jaMimeSaveFile" # Still not unique? :0 *$ ? $IS_EXIST $JA_MIME_SAVE_DIR/$jaMimeSaveFile { :0 fhw | $FORMAIL -I "X-jaMimeSave-Error: (file exists) $jaMimeSaveFile" # kill variable to prevent next recipe from running jaMimeSaveFile } } # ........................................................ &save ... # 1) Locate the positions where the attachment starts # 2) When found, start looking for empty line which ends the mime # headers. GO is set to 1, when attachment starts # 3) Attachment ends when mime boundary is hit. Actually # it ended one line before that, which was a empty line. jaMimeSaveShellmetas = $SHELLMETAS LINEBUF = $JA_MIME_SAVE_LINEBUF SHELLMETAS :0 fbw * MIME_BOUNDARY_COUNT ?? [1-9] * jaMimeSaveFile ?? [a-z] | $AWK \ ' BEGIN { found = 0; go = 0 } \ { \ if ( match($0, MATCH) > 0 ) \ { \ found++; \ } \ if ( found && match($0, "^[ \t]*$") ) \ { \ go = 1; \ next; \ } \ if ( match($0, MIME) > 0 ) \ { \ go = 0; \ } \ if ( go ) \ { \ if ( DELETE == "yes") \ { \ if ( urlFlag == 0 ) \ { \ urlFlag = 1; \ printf "\nextracted to file:%s\n\n", FILE; \ } \ } \ else \ { \ print; \ } \ print $0 >> FILE; \ next; \ } \ print; \ } \ ' DELETE="$JA_MIME_SAVE_DEL" \ MIME="$MIME_BOUNDARY" \ COUNT="$MIME_BOUNDARY_COUNT" \ MATCH="Disposition:.*$MIME_B_ATTACHMENT" \ FILE="$JA_MIME_SAVE_DIR/$jaMimeSaveFile" LINEBUF = $jaMimeSaveLinebuf SHELLMETAS = $jaMimeSaveShellmetas # ....................................................... decode ... dummy = "pm-jamime-save.rc: Encoding($contentEncoding) of $jaMimeSaveFile" :0 *$ jaMimeSaveFile ?? $a *$ contentEncoding ?? $a { jaMimeSaveFile2 = "$jaMimeSaveFile.raw"; :0 wc * contentEncoding ?? base64 | $CAT $JA_MIME_SAVE_DIR/$jaMimeSaveFile \ | $MIME_BIN_64 > $JA_MIME_SAVE_DIR/$jaMimeSaveFile2 \ && $MV $JA_MIME_SAVE_DIR/$jaMimeSaveFile2 \ $JA_MIME_SAVE_DIR/$jaMimeSaveFile :0 Ewc * contentEncoding ?? quoted-printable | $CAT $JA_MIME_SAVE_DIR/$jaMimeSaveFile \ | $MIME_BIN_QP > $JA_MIME_SAVE_DIR/$jaMimeSaveFile2 \ && $MV $JA_MIME_SAVE_DIR/$jaMimeSaveFile2 \ $JA_MIME_SAVE_DIR/$jaMimeSaveFile } } dummy = "pm-jamime-save.rc: end:" # End of file pm-jamime-save.rc procmail-lib-2009.1202/lib/pm-jamime.rc000066400000000000000000000155011130547513300173570ustar00rootroot00000000000000# pm-jamime.rc -- subroutine to read mime boundary etc. variables # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Documentation # # This includerc reads MIME boundary string from the message # if it exists. The boundary string is typically found from # Content-Type header. # # Mime-Version: 1.0 # Content-Type: multipart/mixed; boundary=9i9nmIyA2yEADZbW # # In addition it will define few other mime variables. See the # returned values. You use these variables later in your MIME # message processing. # # Mime Notes # # 1998-07-28 Brett Glass reported in PM-L that # there was security exploit in long attachment filenames: # http://www.xray.mpe.mpg.de/mailing-lists/procmail/1998-07/msg00248.html # # And here is the url to the matter: # # http://www.sjmercury.com/business/microsoft/docs/security0728.htm # # # When you use this module to detect mime messages, you can check the # filename length with recipe: # # # Recipe after calling $RC_MIME, this module, # # re = ".........." # regexp with 10 matches # too_long = "$re$re$re$re" # allow 40 characters maximum # # :0 # *$ $SUPREME^0 MIME_H_ATTACHMENT ?? $re # *$ $SUPREME^0 MIME_B_ATTACHMENT ?? $re # { # dummy = "** Dangerously long mime attachment filename" # dummy = "** $MIME_H_ATTACHMENT $MIME_B_ATTACHMENT" # # :0 : # /var/spool/mail/MimeDanger # } # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # # Call arguments (variables to set before calling) # # (none) # # Return values # # o Variable MIME is set to "yes" or "no" if messages has mime version # string # o MIME_VER contains the mime version string from the header. # o MIME_TYPE contains the Content-Type from the header. # o MIME_CTE contains Content-Transfer-Encoding from the header. # o MIME_H_QP is "yes" if Content-Transfer-Encoding: quoted-printable # is in the header. # o MIME_B_QP is "yes" if Content-Transfer-Encoding: quoted-printable # is found from the body. # o MIME_BOUNDARY contains the boundary string, which is used to # differentiate mime sections in the body. # o MIME_BOUNDARY_COUNT is the number of boundary strings found # from the body. The value is 3 if there is two mime sections, # and 4 if 3 etc. MIME_BOUNDARY_COUNT -1 = count of sections. # o MIME_H_ATTACHMENT, contains the filename if there was attachement # filename in the header. Content-Disposition: attachment; # filename="..." # o MIME_B_ATTACHMENT. `body' file attachment. Note however that # this is the match of first string in the body. There may be # several attachments. MIME_B_ATTACHMENT_FILE_COUNT tells you # how many filenames are in the body. # # Usage example # # INCLUDERC = $PMSRC/pm-jamime.rc # # Change Log (none) # ............................................................ &code ... dummy = " ======================================================================== pm-jamime.rc: init:" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables MIME = "no" # set default value MIME_H_QP = "no" MIME_B_QP = "no" MIME_VER MIME_CTE MIME_TYPE MIME_BOUNDARY MIME_BOUNDARY_COUNT # ........................................................... &do-it ... # The WSPC ?? ( ) is there just double checking that we REALLY read # the pm-javar.rc. We must not set any MIME variables if that wasn't # read. :0 * ^Mime-Version: *\/[0-9.]+ * WSPC ?? [ ] { MIME = "yes" MIME_VER = $MATCH :0 * ^Content-Type: +\/.* { MIME_TYPE = $MATCH } :0 *$ ^Content-Transfer-Encoding:$s+\/.* { MIME_CTE = $MATCH :0 * MIME_CTE ?? quoted-printable { MIME_H_QP = "yes" } } :0 *$ B ?? ^Content-Transfer-Encoding:$s+quoted-printable { MIME_B_QP = "yes" } # What is the MIME tag in this message? # # Content-Type: multipart/mixed; # boundary="---- =_NextPart_000_01BD04D4.A5AC6B00" # # Note that in the text, this string may not be excatly like this, # Eg. in my messages there was "--" prepended to the tag. # :0 * boundary *= *\"\/[^\";]+ { MIME_BOUNDARY = $MATCH } # Hm, the boundary string was not surrounded by double quotes. # Search this kind of boundary string then: # # Content-Type: multipart/mixed; boundary=9i9nmIyA2yEADZbW :0 E * boundary *= *\/[^\";]+ { # " Don't mind this, a dummy double quote to help Emacs # to end starting quote below. Otherwise syntax colour # highlighting would go beserk. MIME_BOUNDARY = $MATCH } dummy = "pm-jamime.rc: Do we have the boundary string?" :0 *! MIME_BOUNDARY ?? ^^^^ { # Count how many mime sections there are in the message. # MIME_BOUNDARY_COUNT -1 = count of mime sections. :0 *$ B ?? 1^1 $\MIME_BOUNDARY { } MIME_BOUNDARY_COUNT = $= } # Mime-Version: 1.0 (generated by tm-edit 7.106) # Content-Type: application/octet-stream # Content-Disposition: attachment; filename="file.txt" # Content-Transfer-Encoding: 7bit # # Note: the second regexp assumes "filename=file.txt" mimeAttachementRegexp1 = "filename$s*=$s*[\"']\/[^\"\']+" mimeAttachementRegexp2 = "filename$s*=$s*\/.*" :0 *$ H ?? ^Content-Disposition:.*attachment$s*;$s*\/.* *$ $SUPREME^0 MATCH ?? $mimeAttachementRegexp1 *$ $SUPREME^0 MATCH ?? $mimeAttachementRegexp2 { MIME_H_ATTACHMENT = $MATCH } :0 E *$ B ?? ^Content-Disposition:.*attachment$s*;$s*\/.* *$ $SUPREME^0 MATCH ?? $mimeAttachementRegexp1 *$ $SUPREME^0 MATCH ?? $mimeAttachementRegexp2 { MIME_B_ATTACHMENT = $MATCH :0 *$ B ?? 1^1 ^Content-Disposition:.*attachment.*filename { } MIME_B_ATTACHMENT_FILE_COUNT = $= } } dummy = "pm-jamime.rc: end:" # pm-jamime-tag.rc ends here procmail-lib-2009.1202/lib/pm-janetmind.rc000066400000000000000000000133351130547513300200710ustar00rootroot00000000000000# pm-janetmind.rc -- handle http://minder.netmind.com/ messages # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # ** THIS MODULE IS OBSOLETE. THE NETMIND SERVICE NO LONGER EXISTS ** # # http://minder.netmind.com/ # # ...Netmind, or The URL-minder is a free, automatic Web-surfing robot # that keeps track of changes to Web pages that are important to you. # When the URL-minder detects changes in any of the Web pages you # have registered, it sends you e-mail. an effective way to test if # the address is known to Internet. You could use this information to # see if some automated reply to a address can be sent. # # # In another words, if you're interested in some URL; say an FAQ page # and any updates to them, you can tell Netmind to monitor the page # changes for you and it send a message back every time page changes. # # This recipe "pretty formats" the announcement sent by Netmind # by stripping the message to bare minimum. You usually aren't interested # in 4k message which includes "Note from our sponsors", "Try the free # online demo" etc. The things saved from the announcement message are: # # o The changed url, which is moved to subject # o Cancellation url pointer # o url to the lists of your monitored urls # o your id number # # [Note] # # Please let Netmind send you one "pure" message first so that you # have a huch what it originally looks like. Then plug int his module # and see how the original message is reduced. # # [Thank you] # # The Doctor What # 1998-03-12 send me a patch, where a)body message is more informative # b) URL is now included in the body for auto-click browsers c) # mime headers were removed. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o If you se variable JA_NETMIND_SUBJECT to "yes", then the changed # url http pointer is put to subject line. # # Usage example # # INCLUDERC = $PMSRC/pm-janetmind.rc # reformat the message # # :0: # drop to folder # * netmind # url.mbox # # Change Log (none) # .................................................... &initialising ... id = "pm-janetmind.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # Are we allowed to change the Subject? JA_NETMIND_SUBJECT = ${JA_NETMIND_SUBJECT:-"no"} # ........................................................... &do-it ... # catch both "From" and "From:" header lines :0 * ^From.*netmind\. { # ............................................... change subject ... # Get the changed page and put it into subject line: you see immediate # what page has changed when you browse your mailbox summary. subject = "" :0 *$ ^Subject:\/.* *$ MATCH ?? ()\/$a.* { subject = $MATCH } :0 *$ 1^1 B ?? new changes in:$SPCL+\/.* *$ 1^1 B ?? changed page, +visit:($)\/.* *$ MATCH ?? ()\/$a.* { TheUrl = $MATCH :0 fhw * JA_NETMIND_SUBJECT ?? yes | $FORMAIL -I "Subject: $MATCH" } # .................................................. change body ... # The message from URL-minder is roughly 4k and lot of the information # is useless. There is "note from out sponsor", how to stop requesting # messages etc. # To retrieve the password pass = "" :0 * B ?? ()\/http.*netmind.*responder.* { pass = $MATCH } # To update your account visit update = "" :0 *$ B ?? ().*update.*account.*($)\/.* { update = $MATCH } # Save the cancel information cancel = "" :0 *$ B ?? ^To$s+cancel.*this.*($)\/.* { cancel = $MATCH } # Save "NetMind List" pointer: list of monitored urls cancelAll = "" :0 *$ B ?? ^To$s+cancel.*all.*($)\/.* { cancelAll = $MATCH } # .......................................................... body ... # modify the body only if we got enough matches dummy = "$id: changing message contents" :0 * update ?? [a-z] * cancel ?? [a-z] * cancelAll ?? [a-z] { # Remove the mime headers, the message is no longer MIME. :0 fhw | $FORMAIL -I "Content-Type:" -I "Mime-Version:" # Avoid multiple echo commands and put message into one string msg = "Subject : $subject${NL}Changed : $TheUrl${NL}Update : $update" msg = "$msg${NL}${NL}Cancel this: $cancel${NL}Cancel all : $cancelAll" :0 fbw | echo "$msg$NL" } :0 E #else statement { dummy = "$id: $JA_MSG_ERROR the message format has changed" dummy = "$id: $JA_MSG_ERROR send copy to maintainer of the module" } } dummy = "$id: end:" # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-janslookup.rc000066400000000000000000000304301130547513300203000ustar00rootroot00000000000000# pm-janslookup.rc -- run nslookup on variable INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine runs `nslookup' on given INPUT address. This may be # an effective way to test if the address is known to Internet. You # could use this information to determine if some automated reply to # a address can be sent. The know truth is that you can't validate # whole email address # # to_someone@foo.com # # but you can validate "foo.com"; that's the closest you get. # # [Warning: If you don't use cache feature...] # # Do not however use this module to regularly check _all_ incoming # from addresses with this subroutine for possible bogus UBE # addresses, because calling nslookup # # o may be slow, building to connection and querying the results # may take several seconds. (some times, usually it's quote fast) # o consumes quite a lot resources. # # You can however check _some_ messages that are likely UBE to verify # your doubts. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jaaddr.rc # # Call arguments (variables to set before calling) # # o INPUT, the address (only strict domain part) which is checked. # Eg. "this.domain.com". See examples for more. # If this string contains "@" character, then additional # subroutine pm-jaaddr.rc is called to extraxt the domain name # INPUT = "John Doe " --> INPUT = "site.com" # o JA_NSLOOKUP_CACHE, filename. If exists, cache is used and updated. # o JA_NSLOOKUP_FORCE, if "yes", then cache is not used but a forced # nslookup is performed. # o JA_NSLOOKUP_OPT, is currently empty, but you could see if you # you want to use "-querytype=MX". However this option may give # you response: "No mail exchanger (MX) records available", # which is flagged as nslookup failure. # o JA_NSLOOKUP_SERVER, optional, the server to user for nslookup # # If the cache file can be read: # # o Each entry has format "address.com ns-error". The error # indication is added to the line if the nslookup failed when # address was checked. Otherwise line contains "address.com". # o The cache is always checked first. If there is no entry matching # the current address, only then is nslookup called and new entry # added to cache. # # Return values # # o Variable ERROR will be set to "yes" if nslookup failed or # to "no" if nslookup succeeded. It can also contain "maybe" if # nslookup returned "No address (A) records available" # o ERROR_MATCH contains one line lookup failure reason. # # Following conditions trigger "maybe" and no "ns-error" is written # into the cache. # # o "No address (A) records available for xxx" # # Usage example # # If you are going to check some header field, like From:, please # explode the content with pm-jaaddr.rc first. Suppose you have # string: # # "From: foo@ingrid.sps.mot.com (Yoshiaki foo)" # # You have to derive the address from string and pass the site name: # Read From: field and address from it. # # PMSRC = $HOME/pm # RC_NSLOOKUP = $PMSRC/pm-janslookup.rc # name the subroutine # # :0 # * MAYBE_UBE ?? yes # * ^From:\/.* # { # INPUT = $MATCH # INCLUDERC = $RC_NSLOOKUP # to nslookup # # :0 # * ERROR ?? yes # { # # Hm, nslookup failed, can't send anything back to this # # address # } # } # # Second example, check if the address is reachable before sending reply # # INPUT = `$FORMAIL -rt -x To:` # INCLUDERC = $RC_NSLOOKUP # # :0 # * ERROR ?? no # { # # okay, at least site address seems to be reachable # } # # # Change Log (none) # .................................................... &initialising ... dummy = " ======================================================================== pm-janslookup.rc: init: INPUT = $INPUT" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # If user gave string that had Email, explode it automatically # INPUT = "John doe " --> "site.com" :0 * INPUT ?? @ { INCLUDERC = $PMSRC/pm-jaaddr.rc # - explode INPUT string INPUT = $SITE # - the address is only fed } # ...................................................... &input-vars ... # o INPUT contains the address to check # o JA_NSLOOKUP_CACHE is optional # Set to empty "" if you don't wan't to use cache in some particular # cases JA_NSLOOKUP_CACHE = ${JA_NSLOOKUP_CACHE:-"$HOME/.nslookup.cache"} # other options JA_NSLOOKUP_FORCE = ${JA_NSLOOKUP_FORCE:-"no"} JA_NSLOOKUP_OPT = ${JA_NSLOOKUP_OPT:-"-querytype=MX"} JA_NSLOOKUP_SERVER = ${JA_NSLOOKUP_SERVER:-""} NSLOOKUP = ${NSLOOKUP:-"nslookup"} # Add `-silent' in Linux TOUCH = ${TOUCH:-"touch"} # binary to create cache file # ..................................................... &output-vars ... # output variables ERROR = "yes" ERROR_MATCH # ........................................................... &do-it ... # ErrorWord is not really ment for user configurable, but # as you can see, it is coded that way in case you would like to # use some other error word. ErrorWord = ${ErrorWord:-"nlookup-error"} dummy = "pm-janslookup.rc: do the work" # The string must have one dot somewhere, otherwise it is not a domain :0 *$ INPUT ?? $NSPC+\.$NSPC+ { topDomain = "xxx-dummy-regexp" cache = "no" entry = "no" :0 * INPUT ?? ()\/[^.]+\.[^.]+^^ { topDomain = $MATCH # xxx.foo.com --> foo.com } # If variable is not empty, suppose that user wants to use cache :0 * ! JA_NSLOOKUP_CACHE ?? ^^^^ * JA_NSLOOKUP_FORCE ?? no { cache = "yes" :0 hwic # Create file if it doesn't exist. * ! ? $IS_EXIST $JA_NSLOOKUP_CACHE | $TOUCH $JA_NSLOOKUP_CACHE } dummy = "pm-janslookup.rc: Test if cache is in use" :0 * cache ?? yes *$ ? $IS_READABLE $JA_NSLOOKUP_CACHE { # Convert regexp to "safe" format, escapeping regexp # metacharacters. See pm-tips.txt regexp = "$\INPUT" :0 # kill leading "()" * regexp ?? ^^\(\)\/.* { regexp = "$MATCH" } # b) search hostname and SPACE like in: "this.site.com nlookup-error" # a) or "this.site.com" line = `$EGREP "^$regexp( | *$)" $JA_NSLOOKUP_CACHE` :0 # was this address in cache? *$ line ?? $INPUT { entry = "yes" } dummy = "pm-janslookup.rc: Test if cache line does _not_ include $ErrorWord" :0 * entry ?? yes *$ ! line ?? $ErrorWord { ERROR = "no" } } # Cache is not used OR there was no line in the cache dummy = "pm-janslookup.rc: Test if we call nslookup" :0 * entry ?? no { stat = `$NSLOOKUP $JA_NSLOOKUP_OPT "$INPUT" $JA_NSLOOKUP_SERVER` # If nslookup succeeds, at least HP-UX 9/10, ULTRIX and SUN # return some of these choices upon success: # # Non-authoritative answer: # Name: uta.fi # # Or # # Non-authoritative answer: # geocities.com preference = 0, mail exchanger = ... # # Or # # Name: foo.com # Address: 209.54.94.60 # # Or # # Authoritative answers can be found from: # foo.com # origin = xx.foo.com # # Or # Non-authoritative answer: # foo.com mail exchanger = 0 mx1.foo.com. # # Or ^($)$topDomain # # This needs some explaining. When procmail captures # the `nslookup' command it does it wrong for some unknown reason # for some mail hosts. The captured output is: # # procmail: Assigning "stat=Name Server: zeus.tele.nokia.fi # Address: 131.228.134.50 # # umd.umich.edu # origin = tiamat.umd.umich.edu # mail addr = hostmaster.tiamat.umd.umich.edu # serial = 970727 # refresh = 28800 (8 hours) # retry = 14400 (4 hours) # expire = 2419200 (28 days) # minimum ttl = 14400 (4 hours)" # # notice? The line "Authoritative answers can be found from:" # is not there while it is if I run the same command is # run from command line. # |Authoritative answers can be found from:($).* :0 * stat ?? ()\/No +address.*available.* { # *** No address information is available for ... ERROR_MATCH = $MATCH ERROR = "yes" } :0 E *$ stat ?? ()\/answer:($)(Name:)? *$INPUT\ |(Name: *$INPUT)|from:($) +$topDomain\ |($) *$topDomain { ERROR = "no" } # ............................................. Linux/Cygwin ... # Win32/Cygwin nslookup returns this answer # prompt> nslookup -querytype=MX cs2.tpu.fi # # Non-authoritative answer: # Server: nsX.koti.tpo.fi # Address: 212.63.10.250 # # cs2.tpu.fi MX preference = 0, mail exchanger = xxx.tpu.fi # cs2.tpu.fi MX preference = 10, mail exchanger = yyy.tpu.fi # cs2.tpu.fi MX preference = 20, mail exchanger = zzz.funet.fi # # fi nameserver = HYDRA.HELSINKI.fi # fi nameserver = NS-SE.ELISA.NET # fi nameserver = PRIFI.FICORA.fi # fi nameserver = NS1-FIN.GLOBAL.SONERA.fi # fi nameserver = T.NS.VERIO.NET # fi nameserver = NS.UU.NET # xxx.tpu.fi internet address = 193.167.70.45 # yyy.tpu.fi internet address = 193.167.70.20 # mail.funet.fi internet address = 193.166.0.98 # mail.funet.fi internet address = 193.166.0.97 # HYDRA.HELSINKI.fi internet address = 128.214.4.29 # PRIFI.FICORA.fi internet address = 193.229.4.44 dummy="Win32/Cygwin nslookup check" :0 *$ stat ?? internet address = .*$topDomain { ERROR = "no" } # .................................................. message ... msg = "" :0 * ERROR ?? yes { msg = $ErrorWord } :0 * ERROR ?? maybe { msg = "maybe" } # .............................................. write cache ... dummy = "pm-janslookup.rc: Test if '$INPUT' should be added to cache" :0 hwic: * cache ?? yes | echo "$INPUT $msg" >> $JA_NSLOOKUP_CACHE } } :0 E { dummy = "pm-janslookup.rc: $JA_MSG_ERROR invalid INPUT" } dummy = "pm-janslookup.rc: end: input: $INPUT error: $ERROR" # end of file pm-janslokup.rc procmail-lib-2009.1202/lib/pm-jaorig.rc000066400000000000000000000237071130547513300173770ustar00rootroot00000000000000# pm-jaorig.rc -- Extract embedded original message (simple recipe) # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Documentation # # This subroutine digs embedded message from the body and replaces # current message with it. Copy the message to folder before calling # this subroutine if you need original. # # NOTE: This is _simple_ tool and the sole purpose is to derive # simple embedded messages. Write full fledged perl script if you # want better extracting features. The used AWK inside this procmail # recipe will fail to find 30% of the cases, mostly due to non-standard # way of including the message. The recognized formats are as follows. # Anything that differs from these are ignored or incorrectly parsed. # # o Message is embedded left flushed "as is". With full headers or # Minimum of `From:' `Subject' `Received' # o The embedded message is quoted with `>' with optional _one_ # space. # # Where you would use this module # # If you're subscribed to mailing lists that regularly sent copies of # original message to the list, like forwarding spam to SPAM-L # mailing list at http://bounce.to/dmuth, then you'd like to # extract the original embedded message which you can then feed to # your UBE filter to test if the shield holds. # # # subscribe SPAM-L # # This recipe takes simplistic approach and tries it's best to # extract embedded message. Idea for this recipe comes from Era # Eriksson's posting "recipe to turn list postings back into original # spam" 1998-06-25 in Procmail mailing list. # # o Body must contain headers # o Remove all `>' quotations. # o extract everything to the end of message. (There are no means # to get rid of the attached signatures that ot forwarding poster # or list server may have attached. # # How the message is extracted # # When this recipe ends, the current message has been modified so that # it _is_ _the_ _original_ _message_. Like if you would receive: # # HEADER-1 # The poster # body-1 # his comments # HEADER-2 # The original embedded message # body-2 # body-1 # And poster's signature or mailing list footer # # The message now looks like # # HEADER-2 # body-2 # body-1 # # And you can save this as original message or feed it to your # UBE filter and test if it detects it. # # Code note: procmail or awk core dump # # For some reason procmail kept dumping core I write the code in # more nicer format like below, but if I made it compact, then it # didn't dump core. Go figure. I'm not pleased that I had to sacrafice # clarity, but there was no other way. # # [The good style] [The forced compact style] # if () if () { statement } # { # statement # } # # I have no explanation why this # happens, the same AWK code would work just fine most of the cases and # then came this message `x' and caused dumping the code, if I feed # some other message, I didn't get core dump. Total mystery to me. # Don't let the log message fool you, this had nothing to do # regexp "^[> ]*From:.*[a-zA-Z]". If I deletd one line from AWK # script, it worked ok, if I added it back the core dump happened with # that message `x' # # procmail: Assigning "pfx=[> ]*" # procmail: No match on "^[> ]*From:.*[a-zA-Z]" # Segmentation fault (core dumped) # # Required settings # # PMSRC must point to source directory of procmail includerc code. # This subroutine needs module(s): # # o pm-javar.rc # # Call arguments (variables to set before calling) # # (none) # # Usage Example # # Let's assume that you want to feed all forwarded UBE that is # posted to spam-l mailing list to your filter and see if it needs # improving by checking the logs later. The forwarded UBE to the list # is labelled "SPAM:" in the subject line. # # $RC_LIST = $PMSRC/pm-jalist.rc # mailing list detector # $RC_ORIG = $PMSRC/pm-jaorig.rc # extract original # $RC_UBE = $PMSRC/pm-jaube.rc # UBE filter # # ... # # INCLUDERC = $RC_LIST # defines variable `LIST' # # :0 # * ! LIST ^^^^ # { # :0 # spam-l mailing list # * LIST ?? spam # * Subject: +SPAM: # { # INCLUDERC = $RC_ORIG # Change it to UBE message # # # Ok, next feed it to filter, set some variables first # # Log = Short log; What filters were applied to message # # mbx = If message was trapped, save it here # # JA_UBE_LOG = "$PMSRC/pm-ube.log" # JA_UBE_MBOX = "junk.ube.ok.mbox" # # INCLUDERC = $RC_UBE # # :0 : # If comes here, filter failed # junk.ube.nok.mbx # } # # :0 : # save normal list messages # list.$LIST # } # # # # Change Log (none) # ............................................................ &init ... id = "pm-jaorig.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # .......................................................... &detect ... pfx = "[> ]*" :0 *$ B ?? ^${pfx}From:.*$a *$ B ?? ^${pfx}Subject:.*$a *$ B ?? ^${pfx}Received: +from { # Remove all original headers from the message, # AWK will shift up the headers in the body :0 fhw | echo "" :0 # make sure LINEBUF has value or procmail dumps core *$ ! LINEBUF ?? $d { LINEBUF = 8192 } # Set bigger LINEBUF. Otherwise procmail/awk may dump core when # a big message is handled. savedLinebuf = $LINEBUF LINEBUF = 524280 savedShell = $SHELLMETAS SHELLMETAS # How it works: # # *) Because AWK can't do multi line matches, we have to use two flags: # `prevHead' is set to 1 as soon as header line is detected. # _BUT_ in order to start header, it must follow with next # header immediately. The `head' is set to 1 only if previous # line was header. # # --> when `head' is raised, then main starts printing the message # # *) do case insensitive match and filter out certain lines. # # *) `Received:' Header is immediate indication of message. # # *) Remove `>' quotation # # *) Print embedded message # # variable `end' is set as soon as there is end of headers. # we fix continued non-header start lines by preceding them # with two spaces. (Forwarded message to spam-l was all left # flushed, thus breaking the proper RFC header continuation) # Var `end' tells when we must not fix lines any more. # :0 fhbw | $AWK \ ' \ /^[>]* ?([A-Z][-a-zA-Z]+:|^From )/ \ { if( prevHead && !head) {print prev; head=1} } \ \ { \ str = tolower($0); \ if ( match(str, "forwarded message") > 0) { next } \ if ( match(str, "received: +from|return-path:")>0) { head = 1 } \ \ if ( head == 1 ) \ { \ sub("^[>]",""); \ if ( match($0,"^[ ]*$") ) { end = 1 } \ if ( !end ) { sub("^ +","")} \ if ( !end && match($0,"[A-Z][-a-zA-Z]+:|^From ") < 1) \ { $0 = " " $0; } \ print; \ } \ \ prevHead = 0; \ if ( match($0, "^[>]* ?([A-Z][-a-zA-Z]+:|^From )") > 0 ) \ { prevHead = 1; prev = $0; } \ } \ ' LINEBUF = $savedLinebuf SHELLMETAS = $savedShell # Add a From_ line if it doesn't have one. :0 fhw *$ ! ^^From$s+ | $FORMAIL } dummy = "$id: end:" # End of file pm-jaorig.rc procmail-lib-2009.1202/lib/pm-japing.rc000066400000000000000000000072241130547513300173700ustar00rootroot00000000000000# pm-japing.rc -- reply shortly to message "Subject: ping"; account ok # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # When I'm on remote site and I don't seem to get throught # with telnet or even with Unix ping(1), I want to know if the # at least the mail server is up. I can send a ping message and the # auto responder will reply immediately. # # Sometimes, when you send a message to a person, it would be nice, # if you could test that the destination address is valid, before # sending a message to a black hole. If the receiver had ping # service running; like this, then you would know that you spelled the # the right address. (after wondering two weeks; why you don't get # response). Nowadays `finger(1)' command seems to be blocked many times. # # This recipe answers to simple ping message like this: # # To: you@site.com # Subject: ping # # Recipe sends a short message back to the sender. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jastore.rc # # Call arguments (variables to set before calling) # # (see Usage) # # Usage example # # JA_PING_MBOX = $HOME/Mail/spool/ping.spool # INCLUDERC = $PMSRC/pm-japing.rc # # Change Log (none) # .................................................... &initializing ... id = "pm-japing.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # ........................................................... &input ... JA_PING_MBOX = ${JA_PING_MBOX:-"junk.ping"} JA_PING_XLOOP = ${JA_PING_XLOOP:-"$LOGNAME ping"} # ............................................................ &code ... dummy = "$id: start:" :0 *$ ^Subject:$s*ping$s*$ *$ ! ^X-Loop: $JA_PING_XLOOP *$ ! $JA_FROM_DAEMON { :0 fhw | $FORMAIL -rt -A "X-Loop: $JA_PING_XLOOP" # Remember, Don't send back anything that would be vital to attacker. # It doesn't matter if the `uptime` or other scripts fail, the reply # is sent anyway. # # Record this ping request # # 'a' Makes sure Formail succeeded and could create reply address. # HOST is your Mail delively host; the same where your programs # will run. :0 ahwc | ( $CAT -; \ uptime; \ echo "[$HOST] User count: "; who | wc -l; \ echo "Unread mail count:"; $GREP '^From ' $DEFAULT |wc -l; \ ) | $SENDMAIL MBOX = $JA_PING_MBOX INCLUDERC = $PMSRC/pm-jastore.rc } # When pinging yourself # the reply message comes back to you as "Re: ping" :0 *$ ^Subject:.*\$s*$ { MBOX = $JA_PING_MBOX INCLUDERC = $PMSRC/pm-jastore.rc } dummy = "$id: end:" # end of pm-japing.rc procmail-lib-2009.1202/lib/pm-japop3.rc000066400000000000000000000274521130547513300173210ustar00rootroot00000000000000# pm-japop3.rc -- Remotedly download messages by mail command request # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # Ahem, that `pop3' is just to draw your attention. This module has # nothing to do with pop3. The idea may resemble it though. This # module listens pop3 requests, and when it gets one, it sends # the whole mailbox content as separate forwarded messages to the # account from where you sent the request. # # This is kinda "empty my mailbox in account X and send the messages # to account Y" # # You might have permanent forwarding on in account X, but if that # is your secondary account, you can ask what messages has been arrived # there with this recipe. # # After you have configured your magic pop3 command, which is your # password, simply send a message to account X, and this module # initiates emptying the mailbox. Here is an example: # # Subject: pOp3-send [mailbox] [kill] # # o `mailbox', is optional folder name which you want to process. # it is $DEFAULT if not given in subject. Use *absolute* path if # you specify one. # o if word `kill' is found, the mailbox will be emptied after # forwarding. If the word is not found, messages are preserved. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-japop3.rc # Phew! We include ourself, we are recursive. # # Call arguments (variables to set before calling) # # o `JA_POP3_SUBJECT_CMD' is your personal access command string. # If this is the first word in the subject line, forwarding starts. # This string is case sensitive. # o `JA_POP3_TMP' is the file where mailbox is moved before starting # to forward the messages. Do not put to point to your $HOME, # becaus that may exceed the quota. # o `JA_POP3_TO_MUST_MATCH' must contain regexp that match the email # addresses where the pop3 messages are allowed to send. BE SURE # TO DEFINE this. If you have account X,Y,Z where you want to receive # pop3 messages, set this regexp to match those site's email addresses. # o `JA_POP3_LOGFILE' is the log where you can see how the forked # procmail processes send each pop3 mail. You may want to set this # to different location than your default `$LOGFILE'. # # Return value # # `STATUS' will contain mailbox name if valid pop3 request was received. # You may wish to save the pop3 requests to separate folder. See example # below. # # Example usage # # You install this same setup for each site where you have account. This # is the account X, from where you want to empty the mailboxes. # # RC_POP3 = $PMSRC/pm-japop3.rc # # .. somewhere in your .procmailrc .. # # JA_POP3_SUBJECT_CMD = myPoPcmd # INCLUDERC = $RC_POP3 # # # Save all pop3 requests to folder # # :0 : # * STATUS ?? [a-z] # mail.pop3-req.mbox # # # In account Y, from where you send the pop3 requests. Following code stores # the received messages to separate folder # # # The MATCH will contain the host name from where the messages # # were moved # # :0 : # *$ X-Loop-Fwd:.*\.rc +\/$NSPC+ # mail.fwd.$MATCH.mbox # # Change Log (none) # ............................................................ &init ... id = "pm-japop3.rc" dummy = " ======================================================================== $id: init: " dummy = "$id: FORKED PROCESS: $JA_POP3_CHILD $JA_POP3_FWD_TO DEFAULT [$DEFAULT] $NL$NL" :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # .......................................................... &public ... JA_POP3_TMP = ${JA_POP3_TMP:-"$TMPDIR/$LOGNAME.pop3"} JA_POP3_SUBJECT_CMD = ${JA_POP3_SUBJECT_CMD:-"XyZ-yourPop3-cmd"} JA_POP3_TO_MUST_MATCH = ${JA_POP3_TO_MUST_MATCH:-"Allowed-address-regexp"} JA_POP3_LOGFILE = ${JA_POP3_LOGFILE:-"$LOGFILE"} # Do not set this to "sendmail -oi -t" JA_POP3_SENDMAIL = ${JA_POP3_SENDMAIL:-"sendmail"} # /usr/lib/ # Script to call to handle each piece of forwarded mail. JA_POP3_RC = ${JA_POP3_RC:-"$PMSRC/pm-japop3.rc"} # don't touch # ......................................................... &private ... # Don't change or define these variables anywhere! These are passed # to child process from this module when forking new procmail copy. JA_POP3_CHILD = ${JA_POP3_CHILD:-"not-child"} JA_POP3_FWD_TO = ${JA_POP3_FWD_TO:-""} # ..................................................... &output-vars ... STATUS # .............................................. start-pop3-transfer ... :0 D * JA_POP3_CHILD ?? not-child *$ ^Subject: $JA_POP3_SUBJECT_CMD\/.* { subject = $MATCH # Set default values error = "" kill = "" mbox = "" mailbox = $DEFAULT keyword = "forwarded to" address = `$FORMAIL -rt -x To:` # - mark each message forwardable by adding X-Loop header. xloop = "X-Loop: $keyword $address from $HOST" # ................................................... &kill-flag ... :0 * ^Subject:.* kill\> { kill = "yes" } # ............................................... &other-mailbox ... dummy = "$id: Check /mailbox/ keyword in subject line" :0 *$ subject ?? ()\/$NSPC+ { mailbox = $MATCH } # ................................................. check-access ... :0 *$ ! address ?? $JA_POP3_TO_MUST_MATCH { error = "Invalid destination [$address]" } # ............................................... &check-mailbox ... :0 * error ?? ^^^^ * mailbox ?? [a-z] *$ ? $IS_READABLE $mailbox { mbox = $mailbox } :0 e { error = "mailbox is not readable" } # ............................................... &check-formail ... :0 fh w # Just check that formail is working ok * error ?? ^^^^ | $FORMAIL -I"X-Dummy-Test: xyz" :0 e { error = "formail [$FORMAIL] not working right" } # ................................................. &check-child ... :0 * error ?? ^^^^ *$ ! ? $IS_EXIST $JA_POP3_RC { error = "child module does not exist" } # ............................................. &prepare-mailbox ... japop3LOCKFILE = $LOCKFILE lockFile = $JA_POP3_TMP$LOCKEXT # ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~ &protect .~. # We must not allow another request to arirve during this period # for this same mailbox. Any new try must be ignored :0 *$ ! $IS_EXIST $lockFile { # Activate regional lockfile. no other file locks are needed # from now on. LOCKFILE = $lockFile :0 hwic # copy to temporary place * error ?? ^^^^ * mbox ?? [a-z] | $CP $mbox $JA_POP3_TMP :0 e { error = "cp [$CP] failure" } :0 hwic # protect mailbox * error ?? ^^^^ | $CHMOD 600 $JA_POP3_TMP :0 e { error = "chmod [$CHMOD] protection failure" } # ....................................................... &do-it ... dummy = "$id: Check if pop3 should be initiated." :0 * error ?? ^^^^ * CP ?? [a-z] * CAT ?? [a-z] *$ ! ^$xloop { STATUS = $mbox :0 *$ ? $IS_READABLE $mbox { dummy = "$id: child: $TIMEOUT $HOST $JA_POP3_RC" dummy = "$id: SH [$SHELL]" dummy = "$id: SENDMAIL [$SENDMAIL]" dummy = "$id: FORMAIL [$FORMAIL]" dummy = "$id: PROCMAIL [$PROCMAIL]" dummy = "$id: HOME [$HOME]" dummy = "$id: PATH [$PATH]" # This may take some time, give enough rope # 16 minutes maximum to process the mailbox japop3TIMEOUT = $TIMEOUT TIMEOUT = 960 # - we're calling ourself, so we must pass the envinronment # variables too so that called JA_POP3_RC script inherits # the environment. # # - DEFAULT is set to /dev/null so that any failure in # child won't put messages back to our mailbox. # # - FORMAIL options are: (-n 5), maximum 5 parallel processes # (-d), ignore Content-Length header, (-s), split # mailbox -- must be the last option. # :0 a hwic | $CAT $JA_POP3_TMP | \ $FORMAIL \ -A"$xloop" \ -n5 \ -d \ -s \ $PROCMAIL \ VERBOSE="on" \ LOGABSTRACT="all" \ LOGFILE="$JA_POP3_LOGFILE" \ DEFAULT="/dev/null" \ SHELL="$SHELL" \ HOME="$HOME" \ PATH="$PATH" \ PMSRC="$PMSRC" \ FORMAIL="$FORMAIL" \ SENDMAIL="$SENDMAIL" \ JA_POP3_CHILD="child" \ JA_POP3_FWD_TO="$address" \ JA_POP3_TO_MUST_MATCH="$JA_POP3_TO_MUST_MATCH" \ $JA_POP3_RC TIMEOUT = $japop3TIMEOUT :0 e # failed; cancel killing the mailbox { kill = "" :0 hwc | ( $FORMAIL \ -rt \ -A "X-Loop: Error" \ | echo "Sorry, $FORMAIL -s failed" \ ) | $SENDMAIL } :0 hwic: # Truncate the file * kill ?? yes | $CAT /dev/null > $mbox } :0 E # ***************** else invalid request { :0 hwc | ( $FORMAIL \ -rt \ -A "X-Loop: Error" \ | echo "[$mbox] does not exist" \ ) | $SENDMAIL } } dummy = "$id: POP3 request handled." LOCKFILE = $japop3LOCKFILE } # ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~ &protect .~. } # ........................................................ the-child ... # The individual messages are mailed back to this script, this # is the "receiver" and handles forwarding, unless message is # already forwarded. dummy = "$id: Check if we're forwarding (pop3) messages: $JA_POP3_CHILD" dummy = "$id: $JA_POP3_FWD_TO ?? $JA_POP3_TO_MUST_MATCH" :0 * JA_POP3_CHILD ?? ^^child^^ *$ JA_POP3_FWD_TO ?? $JA_POP3_TO_MUST_MATCH { :0 fhw # mark this message "forwarded" | $FORMAIL -A "X-Loop-Fwd: pm-japop3.rc $HOST" # You can also only test the recipe if you set # # SENDMAIL = "tee -a $HOME/tmp/sent.mail" :0 ! $JA_POP3_FWD_TO } dummy = "$id: end: STATUS = $STATUS" # End of pm-japop3.rc procmail-lib-2009.1202/lib/pm-jarandf.rc000066400000000000000000000077661130547513300175400ustar00rootroot00000000000000# pm-jarandf.rc -- pick (rand)om line from (f)ile # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # Return random line or a line from a file. This subroutine uses # shell command `awk' and possibly `wc' to be as small burden to the # system as possible. # # Required settings # # You must have awk that supports VAR=value assignment syntax outside # the code block: that is, in the input line. I know no awk that # would not have this feature, but at least you know now what it takes. # # % awk '{print VAR; exit;}' VAR=1 /etc/passwd # # Try using GNU awk, if your standard awk didn't print 1 in above # test. (Put this line to the top of your .procmailrc) # # AWK = "gawk" # # Call arguments (variables to set before calling) # # If intend to call this subroutine many times, then please calculate # the number of lines beforehand and pass it to this subroutine. If # the MAX is not set, then `wc' is called every time to find your the # line count. # # o FILE, from what file to select. Make sure this exists; existence # is not checked here. # o [MAX] optional, number of lines in the FILE. # # Returned value # # variable LINE # # Example usage # # # Select random line from a file # # $RC_RANDF = $PMSRC/pm-jarand.rc # $COOKIE = $HOME/txt/cookie.lst # # ...somewhere.. # MAX=20 FILE=$COOKIE INCLUDERC=$RC_RANDF # # # LINE contains randomly read line # # Change Log: (none) # ............................................................ &init ... id = "pm-jarandf.rc" dummy = " ======================================================================== $id: init: " # ........................................................... &input ... # FILE; MAX; defined by user # ..................................................... &output-vars ... # output variables LINE # ........................................................... &do-it ... # Prevent calling sh -c here. Speeds up procmail. jarandfShellmetas = $SHELLMETAS SHELLMETAS :0 * FILE ?? [a-z] { # If max is not set beforehand :0 * ! MAX ?? ^^[0-9]+^^ { # Awk can't know how many lines are in the file in advance, # we must find it out. MAX = `wc -l $FILE` } # It works like this: # - When line number(NR) is 1, calculate random line # - calculated line is same as current line number, print and exit. LINE = `$AWK \ ' \ function GetRand(i, j) \ { \ srand(); \ return (i + int ( rand()*j )); \ } \ { \ if ( NR == 1 ) { line = GetRand(1, max); } \ if ( NR == line ) { print; exit; } \ } \ ' max=$MAX $FILE ` } SHELLMETAS = $jarandfShellmetas dummy = "$id: end:" # pm-store.rc ends here procmail-lib-2009.1202/lib/pm-jasrv-check.rc000066400000000000000000000041121130547513300203110ustar00rootroot00000000000000# pm-jasrv-check.rc -- check FILE validity, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of the TPFS or MPFS file server. # Check FILE for nonvalid filenames or other access problems. # # Input # # o JA_SRV_F_FILE_CASE_SENSITIVE, flag # o FILE, filename to check. possibly converted to lowercase. # # Output # # o stat, set to "ok" if filename is acceptable. Otherwise contains # brief error reason; # # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-check.rc" dummy = " ======================================================================== $id: init: " stat = "ok" # .................................................. &conversion ... # Should we ignore spelling mistakes? File.txt --> file.txt :0 D * JA_SRV_F_FILE_CASE_SENSITIVE ?? no * FILE ?? [A-Z] { FILE = `echo "$FILE" | $TR A-Z a-z` } # ........................................................... &check ... # Do not accept wildcard names, because # # % test -r file*txt # # would succeed, but there is no no such individual file :0 * FILE ?? [][*?{}()<>&!'$;] { stat = "invalid-characters" } # Check that filename does not have "../" security risk. # Or dos styled "..\" -- perhaps for NT? :0 * FILE ?? \.\.[/\] { stat = "invalid-directory-access" } dummy = "$id: end: STAT = $stat" # Enf of pm-jasrv-check.rc procmail-lib-2009.1202/lib/pm-jasrv-daemon.rc000066400000000000000000000065271130547513300205130ustar00rootroot00000000000000# pm-jasrv-daemon.rc -- server request check, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of the MPFS file server. # Handle BOUNCES to mail server messages, eg if delivery failed # due to maximum byte limit. # # 552 ... Message is too large; 100000 bytes max # # Input # # (none) This recipe examines headers and body to see if it's daemon # bounce. # # Output # # o stat, set to "daemon" if message was handled. # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-daemon.rc" dummy = " ======================================================================== $id: init: Check if this is bounced server message. " stat = "" msg = "" subject = "" to = "" # Hm, We wouldn't even need the FROM_DAEMON test, because # X-Loop is supposed to be unique. Because we expect to see bounce # message the original message is included in the body, that's by "B ??" # search. # # Handle only some daemon messages, notify the recipient about an error. dummy = "$id: The pm-javar.rc daemon status is: $JA_FROM_DAEMON" :0 *$ $JA_FROM_DAEMON *$ B ?? ^X-Loop: $JA_SRV_XLOOP { :0 * B ?? ^Subject:\/.* { subject = $MATCH; } :0 * B ?? ^To:\/.* { to = $MATCH } :0 *$ B ?? ()\/^$d+ .*Message is too large.* { msg = $MATCH } :0 * msg ?? [a-z] { stat = "daemon"; # Add new header telling that this bouce was auto-notified back # to original reqeastor. :0 fhw | $FORMAIL -I "X-Mpfs-daemon: [notified $to] $msg" # make sure To has "@" character, otherwise picking of # "To" from the body failed. :0 wc * to ?? @ | ( $FORMAIL \ -rtk -p " >" \ -I "To: $to" \ -I "X-Loop: $JA_SRV_XLOOP " \ -I "Subject: $msg" \ ; \ echo "Your account didn't accept the requested file. " ; \ echo "Get server help file with 'send help' and see conversion types etc."; \ echo "Or notify the File Server admin"; \ ) | $SENDMAIL; \ echo " [ja-srv; daemon $to; $msg;]" >> $JA_SRV_LOG; } } dummy = "$id: end: STATUS = $stat" # End of pm-jasrv-daemon.rc procmail-lib-2009.1202/lib/pm-jasrv-err.rc000066400000000000000000000053671130547513300200410ustar00rootroot00000000000000# pm-jasrv-err.rc -- send message, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This module is part of the MPFS file server. # Ssnd error notice: file didn't exist. # # Input # # o FILE, file or command that did ot exist. # # Output # # o fld, additional field to be added to the saved mbox log message # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-err.rc" dummy = " ======================================================================== $id: init: " # File didn't exist, send notice. stat = "error-NotExist $FILE" # ....................................................... record-log ... # Theese are no-op. We just want to leave trace to the log file TO whom # the message was sent. :0 * ^To:\/.* { } :0 * ^From\/.* { } # ................................................... Subject-notify ... header :0 * JA_SRV_F_SUBJ_NOTIFY ?? yes { header = "-ISubject: Re: $JA_SRV_SUBJECT [$stat]" } # ............................................................. send ... # We use "c" to copy this request to out log mbox dummy = "$id: HEADER: $header" :0 fbw * header ?? [a-z] | $FORMAIL ${header+"$header"} :0 hwic: | ( \ $CAT - | $FORMAIL -I "From "; \ echo "[srv-err] file `$FILE' does not exist."; \ echo "The file may have been renamed or removed."; \ echo "Please use 'send help'"; \ ) | \ $SENDMAIL ; \ echo " [ja-srv; $stat; $to;]" \ >> $JA_SRV_LOG; # ....................................................... extra-info ... # We don't want user to see this because here is directory info # This information is for ourself only. fld = "-A$JA_SRV_X_HEADER: $stat; $file; $JA_SRV_FROM" dummy = "$id: end:" # Enf of pm-jasrv-err.rc procmail-lib-2009.1202/lib/pm-jasrv-from.rc000066400000000000000000000066241130547513300202110ustar00rootroot00000000000000# pm-jasrv-from.rc -- compose reply, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of the MPFS file server. # Compose headers for reply message using `formail' -rt. # # Here is dry run example to test this module # # % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all \ # FORMAIL=/opt/local/bin/formail \ # JA_SRV_FORMAIL_FROM=me@here \ # JA_SRV_CONTENT_TYPE=content-type \ # JA_SRV_XLOOP=xloop \ # $HOME/pm/pm-jasrv-from.rc \ # < $HOME/any-sample.email # # Input # # o JA_SRV_FORMAIL_FROM, JA_SRV_XLOOP # o JA_SRV_CONTENT_TYPE # # Output # # (none) # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-from.rc" dummy = " ======================================================================== $id: init: " # add initial headers. The MIME headers may # very well change later on dummy = "$id: Preparing reply." # This a bit special. When we construct reply to user with formail # -rt, the From address would include the address where your # server is. That't usually fine. # # But if you have some virtual or `contact' address that you want # poeple to use instead of the current address where are, then you # want to rewrite the `From' field. Hm. You could also add Reply-To, # but suppose you don't want to show the real address at all. # # If you set JA_SRV_FORMAIL_FROM variable, then the email address # appears in From field. If you don't define the variable, a normal # formail -rt is used. # # Adding "From:" automatically adds From_, get rid of it too # # NOTE: We must put something into `header'; because the above formail # fails if the header contains only "". In here we duplicate the # harmless call to "-aMessage-ID:" header = "-aMessage-ID:" :0 * JA_SRV_FORMAIL_FROM ?? [a-z] { header = "-AFrom: $JA_SRV_FORMAIL_FROM" } :0 fhw | $FORMAIL -rt \ -a Message-ID: \ -A "Mime-Version: 1.0" \ -A "Content-Type: $JA_SRV_CONTENT_TYPE" \ -A "Content-Transfer-Encoding: 7bit" \ -A "Precedence: bulk" \ -A "X-Loop: $JA_SRV_XLOOP" \ -I "From " \ ${header+"$header"} # test = `$CAT - >> $HOME/tmp/srv.tst` dummy = "$id: end:" # Enf of pm-jasrv-from.rc procmail-lib-2009.1202/lib/pm-jasrv-msg.rc000066400000000000000000000041101130547513300200200ustar00rootroot00000000000000# pm-jasrv-msg.rc -- send message, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of the TPFS or MPFS file server. Run $CODE # and return resutls to to user. Subroutine is meant to be used for # informational messages. # # Input # # o code, code to run in shell # o stat, status message for user # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-msg.rc" dummy = " ======================================================================== $id: init: " head = "" dummy = "$id: Check if subject notify is on " :0 * JA_SRV_F_SUBJ_NOTIFY ?? yes { header = "-ISubject: Re: $JA_SRV_SUBJECT [$stat]" } :0 fhw | $FORMAIL \ ${header+"$header"} \ -A "$JA_SRV_X_HEADER: $stat $FILE" -I "From " :0 # Just for logging purposes, record TO in MATCH * ^To:\/.* { } dummy = "$id: Running code [$code] and sending to [$MATCH]" :0 hwc: | ( $CAT -; $code ) | \ $SENDMAIL ; \ echo " [ja-srv; $stat $FILE; $JA_SRV_FROM;]" \ >> $JA_SRV_LOG; MBOX = $JA_SRV_MSG_MBOX INCLUDERC = $JA_SRV_RC_MBOX dummy = "$id: end:" # Enf of pm-jasrv-msg.rc procmail-lib-2009.1202/lib/pm-jasrv-multi.rc000066400000000000000000000071731130547513300204000ustar00rootroot00000000000000# pm-jasrv-multi.rc -- send multipart MIME message, subroutine for FileSrv # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of MPFS file server. Send out FILE as # multipart MIME message. The message will always be base64 # encoded before sending. # # Input # # o JA_SRV_MIME_MULTI_SEND, command to feed the composed and message # which will handle sending it as multipart MIME. # o JA_SRV_MULTIPART_THRESHOLD is the hunk size for slitting mail. # o FILE, only filename part. Included in MIME headers. # o file, absolute path to send # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-multi.rc" dummy = " ======================================================================== $id: init: " fld = "" ok = "no" to = `$FORMAIL -rtzxTo:` # LOGFILE: To whom we're sending message # ........................................................ read file ... # Read file and base64 encode it to BODY. Flag "yes" is everything is ok :0 fbw | $CAT $file dummy = "$NL$id: Base64 encoding... $NL" :0 fbw | $MIME_BIN_64_E :0 a { ok = "yes" } # ............................................... error while base64 ... :0 * ok ?? no { # Combine this message to previous field. See pm-tips.txt msg = "-AX-Error: $MIME_BIN_64_E failed. Notify server admin." nl nl=${fld+"$NL"} fld="$fld${nl}$msg" # We might as well kill the body, because user # doesn't want to receive binary (gzip) :0 fbw | echo :0 wc: $JA_SRV_LOG.$LOCKEXT | $FORMAIL -I From ${fld+"$fld"} | $SENDMAIL; \ echo " [ja-srv; $file; $JA_SRV_FROM;]" \ >> $JA_SRV_LOG; } # ................................. base64 succeeded, send multipart ... :0 * ! ok ?? no { dummy = "$NL$NL$id: Sending multipart message:$NL $to$NL $file$NL" type = "application/octet-stream" coding = "base64" comment = "This is MIME multipart. You must assemble every part$NL\ together in sequential order. Then decode, cat BODY| mmencode -u > $FILE$NL" :0 fhw | $FORMAIL \ -I From \ -I "Content-Type: $type" \ -I "Content-Transfer-Encoding: $coding" \ -I "Content-Disposition: attachment; filename=\"$FILE\"" \ -I "Content-Description: $comment" :0 wc | $JA_SRV_MIME_MULTI_SEND :0 a hwic: | echo " [ja-srv; $type $file; $JA_SRV_FROM;]" \ >> $JA_SRV_LOG; :0 E { dummy = "$NL$NL$id: $JA_MSG_ERROR ERROR While calling $JA_SRV_MIME_MULTI_SEND $NL" :0 hwic: | echo " [ja-srv; SENDMAIL FAIL $type $file; $JA_SRV_FROM;]" \ >> $JA_SRV_LOG; } } # kill body contents before saving to log :0 fbwi | echo dummy = "$id: end:" # Enf of pm-jasrv-multi.rc procmail-lib-2009.1202/lib/pm-jasrv-req.rc000066400000000000000000000043201130547513300200240ustar00rootroot00000000000000# pm-jasrv-req.rc -- server request check, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of the MPFS file server. # Check if file server request is on the JA_SRV_SUBJECT and # do case or incasensitive check. # # To Dry run this module use following skeleton. Substitute keywods # as needed to reflect your system setup: # # % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all \ # PMSRC=$HOME/txt JA_SRV_CMD_STRING=send \ # JA_SRV_SUBJECT="send newbie_article.rtf noconv" \ # txt/pm-jasrv-req.rc < ~/test.mail # # Input # # o JA_SRV_F_CMD_CASE_SENSITIVE; if "yes" then server request # is case sensitive. # o JA_SRV_FORMAIL_FROM. the email From field # # Output # # o stat, set to "ok" if request is accepted # # Change Log (none) # ............................................................ &init ... # - no leading periods(.) are accepted in the filename # - Invalid filename access "../" is tested later id = "pm-jasrv-req.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } regexp = "^^$s*$JA_SRV_CMD_STRING$s+$NSPC+" subj = $JA_SRV_SUBJECT stat = "" dummy = "$NL$id: do we use case sensitive request keyword?$NL" :0 * JA_SRV_F_CMD_CASE_SENSITIVE ?? yes { flags = "D" } dummy = "$NL$is: check if this is request $NL" :0 $flags *$ subj ?? $regexp { stat = "ok" } dummy = "$id: end:" # Enf of pm-jasrv-req.rc procmail-lib-2009.1202/lib/pm-jasrv-send.rc000066400000000000000000000175541130547513300202030ustar00rootroot00000000000000# pm-jasrv-send.rc -- server request check, subroutine for File Server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine is part of the MPFS file server. # Send the requested file. You can dry-run test this module with # following command: a) make sure that $HOME/test conatins any simple # email message b) define FORMAIL if it isnot found from path. # # % procmail DEFAULT=/dev/null VERBOSE=on LOGABSTRACT=all \ # PMSRC=$HOME/txt JA_SRV_LOG=/dev/null \ # FORMAIL=/opt/local/bin/formail \ # file=$HOME/test FILE=test WORD=WORD JA_SRV_FROM=foo@bar \ # SENDMAIL="tee -a $HOME/test.send" txt/pm-jasrv-send.rc < ~/test # # Note: # # The MIME headers here selected previously were: # # Content-type: application/octet-stream # Content-transfer-encoding: x-gzip64 # # But Defining own CTE such as x-gzip64 is strongly discouraged by # the MIME RFC's. Most e-mail clients would be at a loss on how to # handle these. Many would just bomb out and not even give you the # opportunity to save it to a file. A more correct MIME type is this, # which is now used: # # Content-type: application/x-gzip # Content-transfer-encoding: base64 # # Input # # o `FILE' is the filename(chdir to directory is already done) # `file' is _absolute_ filename # `WORD' is next word from subject line after FILE word. # o JA_SRV_CMD_STRING is flag # o JA_SRV_F_SUBJ_NOTIFY is flag # # Output # # o FILE_ERROR is set to "yes" if file is not found. # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv-send.rc" dummy = " ======================================================================== $id: init: " :0 * IS_READABLE ?? ^^^^ { INCLUDERC = $PMSRC/pm-javar.rc } stat = "" FILE_ERROR = "" :0 * FILE ?? [a-z0-9] * file ?? [a-z0-9] *$ ? $IS_READABLE $file { stat = "$JA_SRV_CMD_STRING" # no header notify here, because this is ok situation, # Some MUA's thread the sending according to Subject, # so keep subject clean. (it already has Re:) # # In error situations, it's desirable to Subject line # to tell the condition right away. # :0 fh # * JA_SRV_F_SUBJ_NOTIFY ?? yes # | $FORMAIL -I"Subject: Re: $JA_SRV_SUBJECT [$stat]" # ...................................................... gzip ... # How should we send the file? # - If FILE matches list of files in JA_SRV_XGZIP_REGXP # then it is send in compresses base64 gzip format, because # it's too big. # # There must be no "noconv" word request from the user # # - For other files, send it without conversions. dummy = "$NL$NL$id: Setting defaults and clearing variables $NL" comment = "regular file" type = "$JA_SRV_CONTENT_TYPE" coding = "$JA_SRV_CONTENT_ENCODING" convert = "" xgzip = "" # ........................................................ xgzip ... dummy = "$NL$NL$id: check that there is no noconv $NL" :0 * JA_SRV_XGZIP_REGEXP ?? [a-z] *$ FILE ?? $JA_SRV_XGZIP_REGEXP * ! WORD ?? noconv { xgzip = "yes" } dummy = "$NL$NL$id: Has user requested gzip: $WORD $NL" :0 * WORD ?? ^^(gz|gzip)^^ { xgzip = "yes" } dummy = "$NL$NL$id: Was xgzip YES? $NL" :0 * xgzip ?? yes { convert = "gzip-base64" comment = "To decode, cat BODY| mmencode -u| gzip -d > $FILE$NL\ If you don't have MIME capable MUA (Email agent) or if you don't have$NL\ mmencode, you can request file without conversion with subject:$NL\ 'send $FILE noconv'" type = "application/x-gzip" stat = "$stat gzip" coding = "base64" } # But, do always "gzip" for these files, even if "noconv" # was requested. dummy = "$NL$NL$id: Decide if we convert to base64 -- $FILE $NL" :0 * JA_SRV_BASE64_ALWAYS ?? [a-z] *$ FILE ?? $JA_SRV_BASE64_ALWAYS { xgzip # kill variable convert = "base64" comment = "To decode, cat BODY| mmencode -u > $FILE$NL" type = "application/octet-stream" stat = "$stat gzip" coding = "base64" } # .................................................... MIME-TYPE ... :0 * FILE ?? \.(doc|rtf)^^ { type = "application/winword" } :0 * FILE ?? \.zip^^ { type = "application/zip" } :0 * FILE ?? \.gz^^ { type = "application/gzip" } # ...................................................... headers ... # Prevent calling shell layer (because there is ; in the command) # This speeds up procmail saved = $SHELLMETAS SHELLMETAS # Complete the MIME headers: user can download the file if he # has mime aware MUA :0 fhw | $FORMAIL \ -I "Content-Type: $type" \ -I "Content-Transfer-Encoding: $coding" \ -I "Content-Disposition: attachment; filename=\"$FILE\"" \ -I "Content-Description: $comment" SHELLMETAS = $saved # ................................................. &sending ... # pick the right sending method dummy = "$NL$NL$id: Sending $file $convert $NL" # See procmail tips page. We stack all headers to variable *f* # and avoid calling multiple `formail' processes. fld # kill variable :0 * convert ?? [a-z] { ok = "yes" error = "no" :0 # insert file "as is" * ! convert ?? gzip { :0 fbw | $CAT $file :0 e { error = "yes" } } :0 * convert ?? gzip { :0 fbw # gzip while insert | $GZIP -9c $file :0 e { error = "yes" } } :0 * error ?? yes { # If previous command failed # Add error message to separate header ok = "no" fld = "-AX-Error: $GZIP failed, try with noconv." } # ............................................... base64 ... :0 fbw * convert ?? base64 * ok ?? yes | $MIME_BIN_64_E :0 E * ok ?? yes { # Combine this message to previous field. See pm-tips.txt msg = "-AX-Error: $MIME_BIN_64_E failed. Try with noconv." nl nl = ${fld+"$NL"} fld = "$fld${nl}$msg" comment = "" # We might as well kill the body, because user # doesn't want to receive binary (gzip) :0 fbw | echo } } :0 E fb wi | $CAT $file # This is no-op as far as this recipe is concerned. # If you need to examine logs, you will see the TO address # where the message was sent in MATCH. :0 * ^To:\/.* { } dummy = "$id: programs: $FORMAIL $SENDMAIL" dummy = "$NL$NL$id: Extra fields: $fld $NL" :0 fbw * fld ?? [a-z] | $FORMAIL ${fld+"$fld"} :0 wc: $JA_SRV_LOG$LOCKEXT | $FORMAIL -I "From " | $SENDMAIL; \ echo " [ja-srv; $convert $FILE; $JA_SRV_FROM;]" \ >> $JA_SRV_LOG; # kill body contents before saving to log :0 fb wi | echo # Continue to the end fld = "-A$JA_SRV_X_HEADER: $stat; $JA_SRV_FILE_DIR/$FILE" } :0 E { FILE_ERROR = "yes" } dummy = "$id: end:" # Enf of pm-jasrv-send.rc procmail-lib-2009.1202/lib/pm-jasrv.rc000066400000000000000000000577041130547513300172550ustar00rootroot00000000000000# pm-jasrv.rc -- MIME capable Procmail File server # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This is the MPFS (Mime Procmail File Server) and it can send MIME # compliant messages with command # # "send [WORD1] [WORD2]" # # Usually only the ITEM arg is used, and the rest of the words are for # special uses like password and preventing file encoding. A typical # request looks like: # # Subject: send help # ask for file named 'help' # # Overview of features # # o MIME types gzip and text/plain are supported. # o .gz .zip etc. files are sent out as base64 attachments # o .gz .tar.gz files that exceed 100K are sent out as MIME multiparts # o requires procmail 3.11+ and MATCH operator \/ # o requires `mmencode' and `gzip' executables to be present in PATH. # # Install: server file directory # # You have to create a directory for the server where the files are kept. # Usually I don't put the files there, but whenever I want to make a # file available, I draw a hard or softlink to the real file. # # % mkdir $HOME/pm-server # # # Repeat this as needed for files you want to put available # # % cd $HOME/pm-server # % ln -s $HOME/txt/interesting-file.txt interesting-file.txt # # You define the server directory by setting # # JA_SRV_FILE_DIR = $HOME/pm-server # # The short server log is written to file pointed by this variable: # # JA_SRV_LOG = $HOME/pm-server.log # # The incoming "send" requests are stored to mailbox pointed by # following variable. The default value is /dev/null, but # you may want to set it to ~/Mail/spool/log.srv.spool which can be # used read as a newsgroup by Emacs Gnus [In Gnus create newsgroup with # `G` `m' `nnml' `log.srv'] # # JA_SRV_MSG_MBOX # # Install: special files # # Tweak this variable to commands you want to allow shell to execute # in server's directory. This tells when "ls" means command # instead of file # # JA_SRV_SH_COMMAND = "^(ls|what)$" # # That means that request like this: # # Subject: send ls # run "ls" command and return results # # Be sure that the commands exist in your system. See man pages for # more if you want to know what these commands do. Commands cannot # take switches currently for security reasons. E.g. if you want to # give access to "ls -la" listing, put a file "ls-la.txt" available # in the directory, user can get it with "send ls-la.txt" # # ls -- list directory # file -- print file type information. # what -- prints all @(#) tags from files # ident -- print all $ $ tags from files # # Install: file `help' # # Users want to get a help file with message "send help" and the # `help' is just a file in your server directory. Be sure to supply it # prior to any other files. You can always draw a link to a file if you # don't want to name it that way (e.g. if you keep several server help # files in a RCS tree) # # # draw symlink to `help' # # % ln -s $HOME/txt/srv-public-hlp.txt $HOME/server/help # # Basic usage in details # # The server accepts command in format # # "send [CMD|PASSWORD]" # # Where ITEM can be any name as long as it starts with [^ .]. The # regexp says: Anything goes as long as FILE does _not_ start with # space or period. This gives you quite a much freedom to construct # filenames. if you want to hand out file: # # .procmailrc # # You can't. Instead make a link to point to plain "procmailrc" # without the leading period. There is also additional checks # against possible security threat "../" like below; user can't # request such file. # # ../../../gotcha or dir/../../gotcha # # The filename cannot contain special characters like [*?<>{}()]. # # Advanced usage # # [conversions] # # If some of your files are big, it makes sense to send them in # compressed base64 format; which in MIME world is called content-type # gzip. You can set a regexp to enforce encoding for your big # files before they are sent to user. The following setting will send # all text files in compressed format to user. # # JA_SRV_XGZIP_REGEXP = "\.txt" # # When the message is composed a header is inserted into the message # telling how the message is to be decoded, in case user doesn't have # decent MUA that can handle the MIME type: # # X-comment: To decode, cat msg| mmencode -u| gzip -d > test.txt # # [noconv and gz] # # The `WORD1' parameter after the `FILE' is optional and user can # override base64 encoding and request plain file if he uses word # "noconv". # # Subject: send [noconv|gzip] # # However, there are files where `noconv' must not be obeyed, like # the compressed packages that you have put available in .zip, .gz, # .tar.gz or .tgz (GNU tar) format. Following variable controls # when file is always sent as base64: # # JA_SRV_BASE64_ALWAYS # # If the `WORD1' is "gz" or "gzip", then the gzip is explicitly # requested, This may be desirable, because some of the text files in # the server directory may be big and some accounts don't accept big # messages. A typical bounce looks like: # # 552 ... Message is too large; 100000 bytes max # 554 Service unavailable # # These kind of file server bounce messages are handled in separate # module which notifies the user that his account didn't accept the # sent file. # # [case sensitivity] # # By default the request word ("send") and ITEM (filename) are not # case sensitive, unless you set these flags: # # JA_SRV_F_CMD_CASE_SENSITIVE = "yes" # JA_SRV_F_FILE_CASE_SENSITIVE = "yes" # # If values are "no", then these are identical commands: # # Subject: Send Help # Subject SEND HELP # # Multi part mime messages # # If you want to deliver big files, you better be sure not to send # them as a big file. That blocks the connection between every host # along the path that the big file is transferred. The # solution is to use MIME multi parts that can be assembled back in # the receiving MUA. (In case you don't have multi part assembler # receive Perl script to do it). # # MIME multiparts are sent out if # # o Filename matches JA_SRV_BASE64_ALWAYS, typically tar.gz, zip # o Filesize is bigger than JA_SRV_MULTIPART_THRESHOLD, where # default chunk size is 100K. # # When a file meets these criteria, it is read to the `BODY' of message # and base64 encoded. This all happens in memory, so watch # procmail logs to see if any problems with very big files. (>30Meg). # Next, if the base64 conversion succeeded, the composed is handed # to # # JA_SRV_MIME_MULTI_SEND # # Which does the actual delivery and splitting. The default program # used is `splitmail'. Make sure you have it or substitute the # program with some equivalent one. # # Stopping server # # Sometimes you're making rearrangements in you file directory or # doing some other maintenance and you are unable to respond to `send' # requests. You can stop the server by setting # # JA_SRV_IN_USE = "no" # # And when you want to enable the server again; just comment out the # statement or assign `yes'. [The default is `yes']. When this # variable is set to `no', the server sends a message from following # variable as a response to any "send" request. # # JA_SRV_IN_USE_NO_MSG # # Using password to validate file requests # # You should be aware that this file server's implementation is public # in nature. Anyone who asks for a file is allowed to get it. But it # would be good if you could limit the access to documents with some # simple way, like if you set up two file servers (see next chapter) # where one is public and the other is interesting only to group of # people. You can define a string that must be found in Subject field # by setting the following variable # # JA_SRV_PASSWORD = ".*" # default # # The default value will match anything in the subject, thus making the # server public. But if you set it like this # # JA_SRV_PASSWORD ".*123" # # Then string "123" must be there somewhere in the line, like here # # Subject: send 123 # # Yes, "123" is actually a CMD definition, but it doesn't matter # because there is no CMD 123. Subject now matches password and the # server can be accessed. Of course the following is valid too. # # Subject: send noconv 123 # # If the password was wrong, server won't tell it. The message just # lands to your mailbox in that case and you can investigate who # tried to access the restricted server. # # Changing server's command string (multiple servers) # # The default command string is "send", but you can change it and thus # create multiple services. Here is one example, where you have set up # two file servers where each has its own directory. # # # The public server # # JA_SRV_CMD_STRING = "send" # JA_SRV_FILE_DIR = $HOME/server/public # INCLUDERC = $HOME/procmail/pm-jasrv.rc # # # Company server, only interests fellow workers. # # Here "xyz-send" is just magic server request string. # # Notice case sensitivity settings. # # JA_SRV_F_CMD_CASE_SENSITIVE = "yes" # JA_SRV_CMD_STRING = "xyz-send" # JA_SRV_PASSWORD = ".*12qw" # JA_SRV_FILE_DIR = $HOME/server/public/xyz-dir # INCLUDERC = $HOME/procmail/pm-jasrv.rc # # Notes from the author # # [basic Mime type note] # # All basic files that you send must be US-ASCII, 7bit. At least that # is the default MIME type used. See `JA_SRV_CONTENT_TYPE'. I once # received following message back # # ----- Transcript of session follows ----- # 554 ... Cannot send 8-bit data to 7-bit destination # 501 ... Data format error # # because in the previous releases, the MIME type headers were not # in the message saying that the content really was plain 7bit ascii. # # [Sending the file as is] # # Note, that the file is included "as is" without any extra # *start-of-file* or *end-of-file* tags. This is possible, because # the file is sent in MIME format. # # [Using one line log entry] # # It may look very spartan to print a single line log entry. You see # messages like above in the file server log. Using one line entry # instead of multi line announcements makes it possible to write a small # perl tool to parse information from a single line. If you get many # file server messages per day, it quicker to look at the single line # entries too. # # [ja-srv1; sh file; Foo Bar ;] # [ja-srv1; send xxx-file.txt; Foo Bar ;] # | # Server's request keywords (you may have multiple servers) # # [wish list] # # (*) MIME multipart message's mime headers may need some adjustments. # # (*) I rely on simple regexp to send out base64 or gzip files. # The natural extension would be to use file size threshold: if file # is bigger than N bytes, send it out with gzip. And further: if # file is more than NN bytes, send it out as multi part MIME. # # (*) In fact there is a slight mime type errors: .zip files # should be send as application/zip. If you have experience with the # mime types, please contact me and help me to sort out proper # mime headers. # # Required settings # # PMSRC must point to the source directory of procmail code. This # subroutine will include many pm-jasrv-*.rc modules and other files # from there. # # Please test the File Server in your environment before you start # using it for every day. For example I had some weird local problem # where PATH had /usr/contrib/bin/ where gzip was supposed to be, but # in spite of my tries procmail didn't find it along the path. Don't # ask why. I now use absolute binary name: # # GZIP = /usr/contrib/bin/gzip # # In addition, if your messages are not sent to recipient, but you # get daemon message: # # ... Recipient names must be specified # # That's because you have setting SENDMAIL="sendmail"; which is not # enough. It must be # # SENDMAIL = "sendmail -oi -t" # # Usage example # # This is my .procmailrc installation. Notice that the file server # code is used only if you get "send" request. On the other hand, this # double wrapping is not all necessary, you could as well rely on the # File server's capability to detect SEND request. # # # PMSRC = $HOME/pm # directory where the procmail rc files are # RC_FSRV = $PMSRC/pm-jasrv.rc # # mySavedLOGFILE = $LOGFILE # record file server actions elsewhere # LOGFILE = $PMSRC/pm-jasrv.log # # # Listen "send" requests. # :0 # * ^Subject: +send\> # { # JA_SRV_FILE_DIR = $HOME/fsrv # Where to get the files # JA_SRV_LOG = $HOME/fsrv.log # Write log here # INCLUDERC = $RC_FSRV # Use file server now # } # # LOGFILE = $mySavedLOGFILE # # Change Log (none) # ............................................................ &init ... id = "pm-jasrv.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # Too many people forget that SENDMAIL definition must include flags -oi -t :0 * ! SENDMAIL ?? (-) { LOG = "(jasrv) ** ERROR: please make sure SENDMAIL contains flags -oi -t" LOG = "(jasrv) ** ERROR: please see pm-javar.rc for SENDMAIL definition" HOST # Quit immediately } # .......................................................... &public ... # Public variables. User configurable section. # # ** DO NOT MAKE MODIFICATIONS TO THIS FILE ** # Copy variables to your ~/.procmailrc and make changes there. # Recall the 'Installation example' # ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... . flags ... # Notify errors on returned Subject line? # - Always adds message to the body too. JA_SRV_F_SUBJ_NOTIFY = ${JA_SRV_F_SUBJ_NOTIFY:-"yes"} # Should Command be case sensitive? How about file names? JA_SRV_F_CMD_CASE_SENSITIVE = ${JA_SRV_F_CMD_CASE_SENSITIVE:-"no"} JA_SRV_F_FILE_CASE_SENSITIVE = ${JA_SRV_F_FILE_CASE_SENSITIVE:-"no"} # Should the initial "send" request be copied to folder "as is" JA_SRV_F_MBOX_REQUEST = ${JA_SRV_F_MBOX_REQUEST:-"yes"} # And how about our answer to the request? JA_SRV_F_MBOX_REQUEST_SENT = ${JA_SRV_F_MBOX_REQUEST_SENT:-"no"} # ... ... ... ... ... ... ... ... ... ... ... ... ... ... files-dirs ... JA_SRV_TMP_DIR = ${JA_SRV_TMP_DIR:-$TMPDIR} JA_SRV_FILE_DIR = ${JA_SRV_FILE_DIR:-"$HOME/pm-server"} JA_SRV_LOG = ${JA_SRV_LOG:-"$HOME/pm-srv.log"} JA_SRV_MSG_MBOX = ${JA_SRV_MSG_MBOX:-"/dev/null"} # ... ... ... ... ... ... ... ... ... ... ... ... ... .. basic-config ... JA_SRV_CMD_STRING = ${JA_SRV_CMD_STRING:-"send"} JA_SRV_PASSWORD = ${JA_SRV_PASSWORD:-".*"} # From: header in OUTGOING MAIL # # - This is the "From:" header that is set when you send a reply # - You may want to set this to different address than your regular # login address. JA_SRV_FORMAIL_FROM = ${JA_SRV_FORMAIL_FROM:-""} JA_SRV_XGZIP_REGEXP = ${JA_SRV_XGZIP_REGEXP:-"dummy-regexp"} JA_SRV_BASE64_ALWAYS = ${JA_SRV_BASE64_ALWAYS:-"\.(zip|tar|tgz|gz)$"} JA_SRV_X_HEADER = ${JA_SRV_X_HEADER:-"X-Mpfs-Info"} JA_SRV_SH_COMMANDS = ${JA_SRV_SH_COMMANDS:-"^(ls|what|ident|file)$"} # ... ... ... ... ... ... ... ... ... ... ... ... ... ... .. headers .. # Headers read from INCOMING MAIL # # We could do ${JA_SRV_FROM:-`$FORMAIL -xFrom:`} here, but # this way we prevent calling extra formail processes. JA_SRV_SUBJECT = ${JA_SRV_SUBJECT:-""} JA_SRV_FROM = ${JA_SRV_FROM:-""} :0 * JA_SRV_SUBJECT ?? ^^^^ * ^Subject:\/.* { JA_SRV_SUBJECT = $MATCH } :0 * JA_SRV_FROM ?? ^^^^ * ^From:\/.* { JA_SRV_FROM = $MATCH } # ... ... ... ... ... ... ... ... ... ... ... ... ... .. maintenance .. JA_SRV_IN_USE = ${JA_SRV_IN_USE:-"yes"} JA_SRV_IN_USE_NO_MSG = ${JA_SRV_IN_USE_NO_MSG:-\ "File server is not functional at the moment due to maintenance."} # Could also be application/octet-stream for plain files JA_SRV_CONTENT_TYPE = ${JA_SRV_CONTENT_TYPE:-"text/plain; charset=US-ASCII"} JA_SRV_CONTENT_ENCODING= ${JA_SRV_CONTENT_ENCODING:-"7bit"} # ................................................... multipart mime ... # If file is bigger than 100K, it is better that it is sent as mime multipart # to save network connections. # # This applies to only files that match regexp JA_SRV_BASE64_ALWAYS JA_SRV_MULTIPART_THRESHOLD = ${JA_SRV_MULTIPART_THRESHOLD:-100000} # When the message has been composed, (file is in the body), it is # handed to this program to do the actual mail split and sending. # make sure you have this in your system. JA_SRV_MIME_MULTI_SEND = ${JA_SRV_MIME_MULTI_SEND:-"\ splitmail -d -s $JA_SRV_MULTIPART_THRESHOLD"} # ..................................................... &subroutines ... # You could replace any of these modules. # if you change them and think the change would be useful for others too, # send me an update or improvement. JA_SRV_RC_REQUEST = ${JA_SRV_RC_REQUEST:-$PMSRC/pm-jasrv-req.rc} JA_SRV_RC_FROM = ${JA_SRV_RC_FROM:-$PMSRC/pm-jasrv-from.rc} JA_SRV_RC_REPLY = ${JA_SRV_RC_REPLY:-$PMSRC/pm-jasrv-msg.rc} JA_SRV_RC_CHECK = ${JA_SRV_RC_CHECK:-$PMSRC/pm-jasrv-check.rc} JA_SRV_RC_SEND = ${JA_SRV_RC_SEND:-$PMSRC/pm-jasrv-send.rc} JA_SRV_RC_SEND2 = ${JA_SRV_RC_SEND2:-$PMSRC/pm-jasrv-multi.rc} JA_SRV_RC_SEND_ERR = ${JA_SRV_RC_SEND_ERR:-$PMSRC/pm-jasrv-err.rc} JA_SRV_RC_DAEMON = ${JA_SRV_RC_DAEMON:-$PMSRC/pm-jasrv-daemon.rc} JA_SRV_RC_MBOX = ${JA_SRV_RC_MBOX:-$PMSRC/pm-jastore.rc} # Please do _not_ change this variable; it is important the revision # Number is shown there. And when you upgrade tp a new version, the # variable has again the right version number. JA_SRV_XLOOP = ${JA_SRV_XLOOP:-\ "Mime Procmail file server (MPFS $Revision: 2.9 $)\ $JA_SRV_FORMAIL_FROM"} # .......................................................... &daemon ... INCLUDERC = $JA_SRV_RC_DAEMON # Is this bounce to FileServer msg? :0 # is stat is empty, everything is ok. * stat ?? ^^^^ { INCLUDERC = $JA_SRV_RC_REQUEST # Determine if we got request. } # ......................................................... &service ... :0 * stat ?? ok *$ ^Subject:.*$JA_SRV_PASSWORD *$ ! ^X-Loop: $JA_SRV_XLOOP { # The nice thing is that the dummies show up in the VERBOSE log # so you have a better clue where program is executing. dummy = "$NL$NL$id: copying original request to $JA_SRV_MSG_MBOX $NL" :0 c # Copy the original request * JA_SRV_F_MBOX_REQUEST ?? yes { MBOX = $JA_SRV_MSG_MBOX INCLUDERC = $JA_SRV_RC_MBOX } INCLUDERC = $JA_SRV_RC_FROM # compose initial -rt reply # ......................................... &server-in-use-check ... # Is the server up or down currently: If not; send message and quit. dummy = "$NL$NL$id: Is server down currently? $NL" :0 * JA_SRV_IN_USE ?? no { stat = "NotInUse" code = "echo \"$JA_SRV_IN_USE_NO_MSG\"" INCLUDERC = $JA_SRV_RC_REPLY } # "send THISFILE noconv" # | | # WORD # dummy = "$NL$NL$id: Subject: $JA_SRV_SUBJECT [reading the file] $NL" FILE = "" WORD = "" :0 *$ JA_SRV_SUBJECT ?? $NSPC+$s+\/$NSPC+ { FILE = $MATCH } :0 *$ JA_SRV_SUBJECT ?? $NSPC+$s+$NSPC+$s+\/$NSPC+ { WORD = $MATCH } # ....................................................... &check ... INCLUDERC = $JA_SRV_RC_CHECK dummy = "$NL$NL$id: was $FILE a legal name $NL" :0 * ! stat ?? ok { code = "echo \"$FILE is not acceptable\"" INCLUDERC = $JA_SRV_RC_REPLY } # ....................................................... &shell ... dummy = "$NL$NL$id: Check if FILE [$FILE] is allowed SHELL command $NL" :0 * FILE ?? [a-z0-9] *$ FILE ?? $JA_SRV_SH_COMMANDS { dummy = "$NL$NL$id: PATH used for shell command is [$PATH] $NL" stat = "sh" code = "$FILE * " INCLUDERC = $JA_SRV_RC_REPLY } # ........................................................ &send ... dummy = "$NL$NL$id: Test if file exists in server dir $NL" MAILDIR = $JA_SRV_FILE_DIR # chdir to the fileserver directory file = $MAILDIR/$FILE # absolute filename :0 * FILE ?? [a-z0-9] *$ ? test -r $file { dummy = "$NL$NL$id: Checking mime multipart $NL" size = "" # only binary files are send out as multiparts. # We call Perl only if we need the file size information :0 * JA_SRV_BASE64_ALWAYS ?? [a-z] *$ FILE ?? $JA_SRV_BASE64_ALWAYS { size = `$PERL -e 'print "", (stat shift @ARGV)[7]; exit' $file` } # If we got the file size, (perl succeeded), and if the size is # more than the threshold, send the file as MIME multipart. # ELSE then send the file conventionally. :0 * size ?? [0-9] * JA_SRV_MULTIPART_THRESHOLD ?? [0-9] *$ $size ^0 *$ -$JA_SRV_MULTIPART_THRESHOLD ^0 { INCLUDERC = $JA_SRV_RC_SEND2 } :0 E { INCLUDERC = $JA_SRV_RC_SEND } } :0 E { INCLUDERC = $JA_SRV_RC_SEND_ERR } # ........................................................ &mbox ... # Sink the "send FILE" msg dummy = "$NL$NL$id: Sinking request to $JA_SRV_MSG_MBOX $NL" :0 * JA_SRV_F_MBOX_REQUEST_SENT ?? yes { # Do we have anything to report before sinking to folder? # Add possible new fields ($fld) in one call. dummy = "$NL$NL$id: Anything to report in headers? $NL" :0 fhw * ! fld ?? ^^^^ | $FORMAIL ${fld+"$fld"} MBOX = $JA_SRV_MSG_MBOX INCLUDERC = $JA_SRV_RC_MBOX } # IF the answer was not filed (JA_SRV_F_MBOX_REQUEST_SENT == no) # Then kill the message. :0 h /dev/null } dummy = "$id: end:" # Enf of pm-jasrv1.rc procmail-lib-2009.1202/lib/pm-jastore.rc000066400000000000000000000066701130547513300175730ustar00rootroot00000000000000# pm-jastore.rc -- Store messagee to inbox or gzip inbox # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This subroutine stores the message to file pointed by `MBOX'. This # subroutine is meant to be used with the the other general purpose # includerc files. This makes it possible to have a centralized file # storage handling for all your rc files. # # Regular user doesn't get much out of this rc unless he mixes both # .gz and regular files in his .procmailrc # # R e p e a t: This module is basis for general purpose procmail # rc plug-ins to strre message to mailbox pointed by some rc # configuration variable. Normal user can simply say in his .procmailrc: # # :0: # mail.private # # Required settings # # (none) # # Call arguments (variables to set before calling) # # `MBOX' must have been set to point to message storage. # `MBOX_SUFFIX' is extension added to MBOX. Default is none. # `MBOX_MH' if "yes" then deliver to MH mailbox with # `MBOX_MH_CMD' which is "rcvstore" by default. # # o message is delivered to MH mailbox using `MBOX_MH_CMD' # # otherwise # # o If MBOX is `some.mbox' the message is stored as is. # o If MBOX is `some.mbox.gz' the message is gzipped to folder. # o If MBOX is `some-dir/.' then deliver as individual files # # Example usage # # $RC_MBOX = $PMSRC/pm-jastore.rc # # :0 # * condition # { # MBOX = $HOME/Mail/spool/junk.mbox INCLUDERC = $RC_MBOX # } # # Change Log: (none) # ............................................................ &init ... id = "pm-jastore.rc" dummy = " ======================================================================== $id: init: " # ........................................................... &do-it ... # make sure you define MBOX before calling this module. :0 h * MBOX ?? /dev/null /dev/null :0 E * MBOX ?? [a-z] { MBOX_SUFFIX = ${MBOX_SUFFIX:-""} MBOX_MH = ${MBOX_MH:-"no"} MBOX_MH_CMD = ${MBOX_MH_CMD:-"rcvstore"} lock = "$MBOX$LOCKEXT" :0 fhw # Add possibly missing From_ line * ! ^From + | $FORMAIL dummy = "pm-jastore.rc: testing MH mbox" :0 * MBOX_MH ?? yes { # Do we need lock for MH ? :0 w: $lock | $MBOX_MH_CMD $MBOX } :0 E { dummy = "pm-jastore.rc: testing compressed mbox" :0 w: $lock * MBOX ?? \.gz | $GZIP -9fc >> $MBOX # Whether it is regular mbox or directory, this # will deliver the message to it :0 E { dummy = "pm-jastore.rc: if empty MBOX_SUFFIX (ordinary mbox)" :0 : * MBOX_SUFFIX ?? ^^^^ $MBOX :0 E: $MBOX$MBOX_SUFFIX } } :0 E { dummy = "pm-jastore.rc: ***** WARNING - MBOX variable is empty ******" } dummy = "$id: end:" # pm-store.rc ends here procmail-lib-2009.1202/lib/pm-jasubject.rc000066400000000000000000000467661130547513300201100ustar00rootroot00000000000000# pm-jasubject.rc -- Subject field cleaner and canonicalizer (Re:) # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # _NOTE:_ If you receive RFC 2047 encoded Subject headers like # "Subject: =?ISO-8859-1?Q?=C4hnlichkeiten_von_=DCbungen?=", you # must first decode it before using this subroutine. Feed the # message to `pm-jamime-decode.rc' first. # # There are many different Email programs out there that add their # own `reply' characters to the subject field. The most sad programs # come usually from PC platform. Eg. Microsoft has gained a lot of # bad reputation due to it's own standards. # # o MS Explorer can use localized reply strings, # Eg `Vs:' or `vast:' seems to be Finnish `Vastaus'. # o MS product Outlook (??) can be configured similarly. # I have received swedish `Sv:' `-Svar' for `Svaring' (eng: reply) # o MS mail uses `FW:' in forwarded mails. # o Intelligent MUAs try to keep count of replies with # `Re2:' or `Re[2]' # o Japanese MUA Denshin 8 Go V321.1b7 has sent Re^2: # o Some mua uses `Re>' # o Lotus notes (in French version) uses `Ref:' # o Some MS product sends `UQ:' # o XXX uses `-reply' # o Forwarding schemes: (fwd) [fwd] fw: [FWD: [FWD:]] # o Subject references: -subj subj- subj: # # There already is a de facto standard where message should contain # only single `Re:' if message has been replied to (no matter how # many times). This makes it possible to do efficient message # threading by only using Subject and date fields. And grepping same # subjects is lot easier than from this horrible mess. Note that # all text is on one line, the subject has been broken only # for visual reasons: # # Subject: re- Re^2: Re[32]: FW: Re: Re(15) Sv: Re[9]: -reply # (fwd) [fwd] fw: [FWD: [FWD:]] # -subj subj: subj: subj- # test # # This recipe standardizes any subject (like above) that has been # replied to, to de facto format below. That is: "Any number of 'Re:' # will be converted to *single* 'Re:' and any number of 'Fwd:' will be # converted to *single* 'Fwd:'" # # Subject: Re: test (fwd) # # About In-Reply-To header # # If there is `In-Reply-to' header in the message, but there is # not *Re:* in the subject line, one is added automatically. # Some broken Mailers forget to add the *Re:* to the Subject # line. # # Variable JA_SUBJECT_SAVE # # This is by default `yes' which causes the original subject to # be saved under header field `X-Old-Subject'. If you don't want # that extra header generated, set this variable to `no' # # Variable JA_SUBJECT_FWD_KILL # # This is by default `yes', which will kill extra forwarding # indication words like (fwd) [fwd] . If you set this # to `no', then all the forwarding words are preserved. The de # facto forward format is: # # Subject: This subject (fwd) # # Code note # # This subroutine's intention is to make Subject more expressive # by deleting redundant information. A simplistic approach has # been taken where Subject consists of list of *words* whose # each attribute can be either `ok' or `delete'. No attempt has # been made to determine the structure of the Subject. You can # see the algorithm better # from an example: # # Re: New subject (was Re: Old subject) # # That should be treated syntactically like "New subject" and # forgetting anything between parenthesis. This is however not # respected and not even tried. The rule applied here is "One # Re: is tolerated", so the subject won't change. It doesn't # matter where "Re:" is. # # But here the subject is changed. The rule applied is: Delete # all unwanted _words_ and then add one Re: to the beginning if OLD # content had any Reply indications # # Re: New subject (was Re: Old subject) # --> Re: New subject (was Old subject) # # IMPORTANT notice # # Please check that your `SHELL' variable setting in `~/procmailrc' # is `sh' derivate, /bin/sh or /bin/bash. This module won't work with # other shells. # # Awk usage note # # `awk' is a small, effective and much smaller than perl for little # tasks. See the verbose log and make sure your awk understands # VAR="value" passing syntax. Change it to `nawk' or `gawk' if they # work better than your standard awk. # # AWK = "gawk" # you may need this, try also gawk # # Customizations # # Let's say Polish M$Outlook uses `ODP:' instead of # standard `re:' and you want to handle that too: Then set: # # JA_SUBJECT_KILL = "odp:" # NOTE: all lowercase # JA_SUBJECT_SAVE = "no" # INCLUDERC = $PMSRC/pm-jasubject.rc # # You ca use `JA_SUBJECT_KILL' to delete any additional words from the # subject line. E.g. if you have good news-reader, you don't need the # mailing list prefixes that some mailing lists add to the beginning # # Subject: [LIST-xxx] the subject here # # to remove that list prefix, you simply match it # # JA_SUBJECT_KILL = "(list-xxx|list-yyy)" # # Important: The regexp must be _all_ lowercase, because when match # happens, the words have been converted to lowercase. # # Example usage # # You need nothing special, just include this recipe # before you save message to folder. # # INCLUDERC = $PMSRC/pm-jasubject.rc # # Debugging # # You can dry-run test this module with following command and watching # output. Substitute variables as they are in your system. You feed # the content of entire example mail where the Subject that needs # correction is found. # # % procmail SHELL=/bin/sh AWK=gawk VERBOSE=on LOGABSTRACT=all \ # DEFAULT=/dev/null LOGFILE=$(tty) \ # JA_SUBJECT_KILL="(ace-users)" \ # PMSRC=/path/to/install/dir \ # /path/to/pm-jasubject.rc \ # < ~/test.mail # # Thank you # # Thanks to for his creative # improvement suggestions and sending code that this # recipe didn't catch at first. # # Change Log (none) dummy = " ======================================================================== pm-jasubject.rc: init: " :0 * ! WSPC ?? ( ) { INCLUDERC = $PMSRC/pm-javar.rc } # .......................................................... &public ... # -- Put your own reply customization here: regexp is merged to # default values. # -- The regexp must be _all_ lowercase, because the matched # word in the line is converted to lowercase before # matching takes place. JA_SUBJECT_KILL = ${JA_SUBJECT_KILL:-""} # Set to "no" if you don't want to see `X-Old-Subject:' JA_SUBJECT_SAVE = ${JA_SUBJECT_SAVE:-"yes"} JA_SUBJECT_FWD_KILL = ${JA_SUBJECT_FWD_KILL:-"yes"} # ........................................................... &check ... # If the pm-javar.rc module was not loaded, then it would be # disaster to call awk block. Make sure the $a and $AWK variables # exist before doing anything. error = "no" :0 * a ?? [a-z] * AWK ?? [a-z] { } :0 E # Else { dummy = "pm-jasubject.rc: $JA_MSG_ERROR CONFIGURATION IS NOT CORRECT" error = "yes" } # .......................................................... &private ... subject = # Kill variable :0 * ^Subject: *\/.* { originalSubject = $MATCH subject = $MATCH } # These variables are not all caps, because they are not intended to be # user configurable. Please email the author if this module if they are # not enough for you. # # All characters in the regexp must be lowercase, because regexp is # used in awk. Remember: -- Always parenthesize -- # # Notes: # o Using regexp "re^[0-9]+:" to kill Re^2: doesn't work. We use # regexp "re.[0-9]+:" # o re(2) is matched by re[(][0-9]+[)]. Notice that there is not colon(:) # o [[(<]fwd?[])>] matches things like (fwd) [fwd] fwd = "" fwdKill = 0 # AWK needs numeric True/False fwdCount = "" forwarded = "no" savedLINEBUF = $LINEBUF LINEBUF = 8192 # Need bigger value than default # All letters MUST BE LOWERCASE (for awk). No spaces anywhere in regexp fwdRegexp = ${fwdRegexp:-"(fwd?):|[[(<]fw?d?[])>]"} :0 * JA_SUBJECT_FWD_KILL ?? yes { fwd = $fwdRegexp fwdKill = 1 :0 *$ $fwdRegexp { forwarded = "yes" } } # All letters MUST BE LOWERCASE (for awk). No spaces anywhere in regexp replyTypes = ${replyTypes:-"\ (re([0-9]+|.[0-9]+.|.[0-9]+):\ |re[(][0-9]+[)]\ |re-|re>|-reply|-svar\ |(vs|vl|aw|fs|vast|sv|rv|ref|uq):\ |-subj|subj-|subj:\ )"} SubjectDoIt = "no" UserRegexp = "" wordKillRegexp = "$replyTypes" dummy = "pm-jasubject.rc: Possibly adding JA_SUBJECT_KILL" # Has user given any additional keywords to kill? # The variable must contains a-z dummy = "pm-jasubject.rc: :::::::::::::::::::::::::::::: #JA_SUBJECT_KILL" :0 * ! subject ?? ^^^^ *$ JA_SUBJECT_KILL ?? $a { wordKillRegexp = "$replyTypes|$JA_SUBJECT_KILL" # Always remove words that user has defined :0 *$ subject ?? $JA_SUBJECT_KILL { SubjectDoIt = "yes" UserRegexp = "yes" } } # ....................................................... &forwarded ... dummy = "pm-jasubject.rc: :::::::::::::::::::::::::::::: #FWD" :0 *$ fwdRegexp ?? [a-z] { wordKillRegexp = "$wordKillRegexp|$fwdRegexp" :0 * SubjectDoIt ?? no *$ subject ?? ($fwdRegexp)\/.* { subject = $MATCH fwdCount = "1" SubjectDoIt = "yes" :0 *$ subject ?? ()\/($fwdRegexp).* { fwdCount = "2" } } } # must parenthise, so that ".*" can be added to it wordKillRegexp = "($wordKillRegexp)|re:" # ........................................................ &de-facto ... # We count because we want to know if we need to call awk or not. # If there is only 1, then there is no point running external shell process, # if there is at least two, then we need awk. # # In any case we need AWK if user has set mailing list kill words, like # [this-list] # *) grab first match. REPLY word count is then 1. In this case there is # nothing more to kill # *) Search second match, REPLY word count is 2 dummy = "pm-jasubject.rc: :::::::::::::::::::::::::::::: #DE-FACTO" replyCount = 0 :0 *$ subject ?? re:\/.* { subject = $MATCH replyCount = 1 :0 *$ subject ?? ()\/re:.* { replyCount = 2 SubjectDoIt = "yes" } } # .................................................... &non-standard ... # Note: The "Re[0-9]+ " is special case. We can't pass it to AWK, because # it doesn't see spaces, it couns only words, which are delimited by # ^...$ dummy = "pm-jasubject.rc: :::::::::::::::::::::::::::::: #REPLY-TYPES " :0 * SubjectDoIt ?? no * subject ?? ()\/.* *$ $SUPREME^0 subject ?? ($replyTypes)\/.* *$ $SUPREME^0 subject ?? Re[0-9]+ \/.* { subject = $MATCH replyCount = 1 SubjectDoIt = "yes" :0 *$ subject ?? ()\/($replyTypes).* { replyCount = 2 } } dummy = "pm-jasubject.rc: ::::::::::::::::::::::::::::: #DO-IT $SubjectDoIt" # Many foreign language is usually presented in encoded format # (iso-8859-1). Furthermore, if pm-jamime-decode.rc was used to # "open" the Subject line it will set a flag # `PM_JAMIME_COMPLEX_SUBJECT' for messages that should not be # touched (too complex). In those cases it the procmail's # capabilities were reaached and the Subject line should be left # as is. :0 *$ $SUPREME ?? ^Subject:.*\?iso-8859-.\? *$ $SUPREME ?? ! PM_JAMIME_COMPLEX_SUBJECT ?? ^^^^ { SubjectDoIt = "no" } :0 * SubjectDoIt ?? no { # Remove excess spaces between the "Subject" keyword and subject itself :0 fh w *$ subject ?? $s$s+\/$NSPC.* | $FORMAIL -I "Subject: $MATCH" # Some Emacs VM users reply emails without # adding "Re: " in front of the subject (as VM default setting). # Add one if needed. :0 fh w * replyCount ?? 0 * ^(In-Reply-To|References): *$ subject ?? $s+\/.* | $FORMAIL -I "Subject: Re: $MATCH" # Some users (of dtmail) forward emails without # adding "fwd " in front of the subject # Add one if needed. :0 E * ^Message-ID: \ * fwdCount ?? 0 * replyCount ?? 0 * B ?? ^ ---[\-]+ Begin Forwarded Message --- { :0 fh w *$ subject ?? $s+\/.* | $FORMAIL -I "Subject: $MATCH (fwd)" } } :0 * subject ?? ()\/.+ * error ?? no * SubjectDoIt ?? yes { subject = $MATCH # Print log entry to show what regexp we're using. # Grab the regexp from there for external testing or development. dummy = "pm-jasubject.rc: $SHELL $AWK is called with regexp: $NL\ $wordKillRegexp $NL $fwdRegexp" # ......................................................... clean ... # The awk works this way: # - split subject to individual words --> array LIST # - convert every word to lowercase(str) before doing match # because AWK is case sensitive # - Add only valid words to "s" (string) and return "clean" subject. # # There is a special check in this program. Notice the 'lastpos'. # It's purpose is to detect cases like this: # # [Fwd: Re: [jp] J-Pilot 0.99.8-pre2] Real subject here # | # lastpos # # The above subject is too complex to be treated like words, # because it contains inner bracket which ends to lastpos. All # of them must be removed. The word based match would treat it like: # # [Fwd: Re: [jp] J-Pilot 0.99.8-pre2] # 1 2 3 4 5 # # 1. Looks like forwarding word. Removed # 2. Looks like forwarding word. Removed # 3. Looks good word # 4. Looks good word; the ']' is not special # # And the result would be: # # J-Pilot 0.99.8-pre2] clean = `echo "$subject" | $AWK \ ' { \ max = split( $0, list, "[ \t]+" ); \ lastpos = 0; \ s = ""; \ for( i = 1; i <= max; i++) \ { \ word = list[i]; \ str = tolower( word ); \ if ( FWD_KILL && match(str,FWD_RE) > 0 ) \ { \ fwd = 1; \ } \ if ( match(str,RE) < 1 && match(str, "^re[0-9]+$") < 1 ) \ { \ if ( s == "" ) \ { \ s = word; \ } \ else \ { \ s = s " " word; \ } \ } \ if ( match(str,"^[^][]+[]]") > 0 ) \ { \ lastpos = i; \ } \ } \ if ( lastpos ) \ { \ s = ""; \ for( i = lastpos + 1; i <= max; i++) \ { \ s = s " " list[i]; \ } \ } \ if ( match(s, "^ *$") ) \ { \ s = "(none)"; \ } \ if ( fwd ) \ { \ printf "%s (fwd)", s; \ } \ else \ { \ print s; \ } \ } \ ' RE="$wordKillRegexp" FWD_RE="$fwdRegexp" FWD_KILL=$fwdKill ` # ................................................ update subject ... dummy = "pm-jasubject.rc: :::::::::::::::::::::::::::: #RESULT" word = "" :0 *$ replyCount ?? [1-9] { word = "Re: " } # it makes sense replacing the Subject only if the word # contains something :0 * clean ?? [a-z] { # Coording to RFs, all user defined additional fields # must start with X- :0 fh w * JA_SUBJECT_SAVE ?? yes | $FORMAIL -I "X-Old-Subject: $originalSubject" :0 fh w | $FORMAIL -I "Subject: $word$clean" } } LINEBUF = $savedLINEBUF dummy = "pm-jasubject.rc: end: $word$clean" # End of pm-jasubject.rc procmail-lib-2009.1202/lib/pm-jatime.rc000066400000000000000000000055611130547513300173730ustar00rootroot00000000000000# pm-jatime.rc -- "hh:mm:ss" time parser from variable INPUT # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This includerc parses date from variable INPUT which has string # # "hh:mm:ss" # # Example input # # "Thu, 13 Nov 1997 11:43:23 +0200" # # Returned values # # hh = 2 digits # mm = 2 digits # ss = 2 digits # # Variable ERROR is set to "yes" if it couldn't recognize the INPUT # and couldn't parse all hh, mm, ss variables. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include pm-javar.rc from there. # # Call arguments (variables to set before calling) # # INPUT = string-to-parse # # The INPUT can be anything as long as it contains NN:NN:NN # # Usage example # # Get the time of received message. The From_ header will always # have the standard time stamp. # # PMSRC = $HOME/pm # RC_DATE_TIME = $PMSRC/pm-jatime.rc # # :0 c # * ^From +\/.* # { # INPUT = $MATCH # # Turn off the logging while executing this part # # VERBOSE=off INCLUDERC = $RC_DATE_TIME VERBOSE=on # # :0 # * ERROR ?? yes # { # # Should not ever happen, you have broken From_ # } # } # # Change Log (none) # .................................................... &initializing ... id = "pm-jatime.rc" dummy = " ======================================================================== $id: init: " :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # ..................................................... &output-vars ... # output variables # hh mm ss ERROR = "yes" # set default value # ........................................................... &do-it ... # Check that input is something like: Thu, 13 Nov 1997 # dummy = "$id: Parse date like [Tue, 31 Dec 1997}" dummy = "$id: INPUT = $INPUT" :0 *$ INPUT ?? $s*\/$d$d:$d$d:$d$d { INPUT = $MATCH *$ INPUT ?? ^\/$d$d { hh = $MATCH } :0 *$ INPUT ?? ^$d$d:\/$d$d { mm = $MATCH } :0 *$ INPUT ?? ^$d$d:$d$d:\/$d$d { ss = $MATCH ERROR = "no" } } dummy = "$id: end:" # end of file pm-jadate.rc procmail-lib-2009.1202/lib/pm-jaube-keywords.rc000066400000000000000000000423221130547513300210510ustar00rootroot00000000000000# pm-jaube-keywords.rc -- Bare bones word list based UBE filter # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your UBE (aka spam) filters towards the _end_ of your # ~/.procmailrc. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked. # # Now, if 50-70 % hit rate is good enough for your starting point, # go ahead and read more. This file is supposed to be the last resort, # if you really do not have any better tool to analyze messages. # # Overview of features # # o Word and phrase based matching # o 50-70 % success rate. 90 % never achieved. That's a guarantee. # o Extremely fast and a dream to CPU resources. Implemented in pure # procmail and you can almost hear the humming sound of its # regular expression engine shredding UBE messages to pieces. # # Description # # Are you sure you want use this word list based checking? # # Think twice before you use this subroutine. It knows nothing about # the content your mail. "It's all UBE unless proven otherwise" is the # motto. The brutal search tracks words and phrases to find an indication # of mass posting and traces of Unsolicited Bulk Email (UBE aka spam). # _Repeat:_ Read the first paragraph again before you consider putting # this file into action. This filter WILL PASS through unwanted mail # and it WILL catch good mail. This is rule based matching, so I suppose # you know where you're putting your head with this. Ahem. Alerted? Good. # # The Story # # There was a man and mail account. The account had limited space, # couldn't install any other programs because disk quota would have # exceeded. System administrators weren't' interested in installing # anything. The Mail server ran behind firewall and had OS that was # never heard of - it couldn't run other programs. Or if it could, # the Bad system administrator was too scared to install extra # programs to the host MTA ran. No joy -- no means to stop incoming # UBE -- Right? # # Wrong. There was procmail. The Bad system adminitrator didn't mention # that `~/.procmailrc' was honored - just the the external programs # we a no-no-no (Technical: the MDA host mounted user disks; the # server ran on separate host and couldn't use any of the user # compiled programs. Statically linked ones filled up the man's disk # space). # # First line of defense, any defense would do. So, this rule based # file was born. Nothing else was installed in that account and the # happy word list based matching routine kept chewing mail, mail, # mail. And the system administrator was happy - he nurtured the MTA # host's CPU resources and noticed nothing alarming. All ticked like # clockwork. # # Life began again. After 1000 mail bombards a day, the account was # usable again. # # Motivation # # If you can, use the Bayesian filters and forget all rule based # ones, word and phrase matching based ones; all static filters. On # the other hand, if you want quick solution, even imperfect, until # you have time to learn and setup other tools, this subroutine may # be of interest. # # The best part. You can carry this single file anywhere where procmail # lives. No other files are needed. Setup couldn't be simpler. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address is usually forged. Do not # increase the network traffic. Instead save the messages to folders # and periodically check their contents. It's not nice to be forced to # apologize about bounces to a wrong destination. # # Code Note # # Procmail is picky about the whitespace in continuing lines, make sure # there is _not_ a single spaces left after the continuation backslash. # Use good editors or external programs to get rid of the white spaces. In # Emacs you would add this line to your `~/.emacs' startup file: # "(add-hook 'write-file-hooks 'delete-trailing-whitespace)" # # :0 # * ^Subject:.*(regexp\ # |and-more\ # |and-more\ # ) # { # # Process it # } # # Why are the regexps put into this file and not to a separate regexp # file? Good question. It is possible to check message's content with # external process, like `grep', to see if any matches are found. # This kind of methodology is covered in Procmail Tips section # "Using grep with file lists to mach messages" at # . The reason why all the regexp are maintained # inside this file is: # # o Simplicity. One file - no extra configuration files or regexp # databases. # o Self standing. Does not call external processes, so it's a little # faster than possible `grep' and `fgrep' solution. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o JA_UBE_KEYWORD_HEADER, if set, then the results are put to # messages headers. By default this variable is not defined # to save from external `formail' process call. # Suggestion: "X-Spam-JaubeKwd"; without trailing colon. # # Return values # # o `ERROR_STATUS' is set to word "Bad" otherwise empty. # o `ERROR' is set to short descriptive word that indicate which # rule was matched. Values: *Header-FromKeywords*, # *Header-SubjectKeywords* and *Body-Keywords* # o `ERROR_MATCH' is set to some words that happened to trigger # UBE catch rule. # # Usage example # # PMSRC = "/path/to/procmail/lib" # # Exclude these addresses from tests # VALID_FROM = "(my@address.example.com|word@here.example.com)" # # :0 # *$ ! ^From:.*$VALID_FROM # * ! FROM_DAEMON # { # INCLUDERC = $PMSRC/pm-jaube-keywords.rc # # # Variable "ERROR" is set if message was UBE # # :0 : # * ! ERROR ?? ^^^^ # junk.ube.spool # } # # File layout # # The layout of this file is managed by Emacs packages tinyprocmal.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None. dummy = " ======================================================================== pm-jaube-keywords.rc: init:" ####################################################################### # # User configurable variables. Set these, before calling this # module/subroutine. # ####################################################################### # Set to a empty to suppress external shell call to `formail'. JA_UBE_KEYWORD_HEADER = ${JA_UBE_KEYWORD_HEADER:-"X-Spam-JaubeKwd"} ####################################################################### # # Private variables. Do not touch # ####################################################################### # Kill variables or set default values ERROR ERROR_MATCH ERROR_STATUS NL = " " LF = $NL # synonym, linefeed CR = " " # Carriage return TAB = " " # \t character, you won't see it. WSPC = " $TAB" # whitespace in procmail: space + tab # These are the variables that you're likely to use in # condition lines. Notice that there is Perl styles `s' variable # for shorter name for most used SPC. SPC = "[$WSPC]" # Regexp space/tab NSPC = "[^$WSPC]" # Negation, non-whitespace CHAR = "[^ $TAB$NL$CR]" # A character # Whitespace with linefeed # Note that in regexps, the character class is faster that OR. # Refer to O'Reilly book "Mastering Regular Expressions" # # space + tab + dollar # # ( | |$) is slower than ([ ]|$) SPCL = "($SPC|$|$CR)" # space or tab; linefeed; Carriage return jaubeKwdLinebufOld = $LINEBUF LINEBUF = 65535 # Increase jaubeKwdVerboseOld = $VERBOSE # don't write log for these variables VERBOSE = off # German, Spanish and other languages jaubeLanguage="(\ [a-z] (con|m[ae]s|para) [a-z]\ |\\ |\\ |\. # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ mkdir $HOME/.annoyance # $ DB=$HOME/.annoyance/dict.bin; DB2=$HOME/.annoyance/fdict.bin # $ annoyance-filter --mail single.msg --prune --write $DB # $ annoyance-filter --phrasemax 2 \ # --read $DB \ --mail dir/to/good/messages \ # --junk dir/to/bad/messages \ # --prune --write $DB # $ annoyance-filter -v --read $DB --prune --fwrite $DB2 # # To check message: # # $ annoyance-filter --read $DB --test mail.msg # $ annoyance-filter --fread $DB2 -v --class mail.msg # # Overview of features # # o Implements interface to # http://sourceforge.net/projects/annoyancefilter/ project. # See article "Training Annoyance Filter to combat spam" by # Corrado Cau at # http://www.newsforge.com/software/03/10/24/2046238.shtml?tid=74 # o variable `ERROR' is set if the message was UBE. # o Results are available by default in header # `X-Spam-Annoyance-Status'. # # Description # # There are several Bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # This procmail subroutine implements call interface to program # `annoyance-filter', which must already have been installed. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `annoyance-filter' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_ANNOYANCE_PRG = /usr/bin/spamprobe # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o `JA_UBE_ANNOYANCE_PRG', path to the program [required]. # o `JA_UBE_ANNOYANCE_SPAM_DB', path to the dictionary database # [required]. E.g. `$HOME/.annoyance/dict.db'. # o `JA_UBE_ANNOYANCE_SPAM_DB_OPT', type of dictionary to read. # Default is "--read", but this could be fast dictionary option # "--fread". # o `JA_UBE_ANNOYANCE_HEADER', the header name where the results # are put. If not defined, no header is added. # Defaults to *X-Spam-Annoyance-Status* # o `JA_UBE_ANNOYANCE_FORCE', if set to _yes_ then call program no matter # what. Normally if there already is *X-Spam-Annoyance-Status* header, # it is assumed that the message has already been checked # and no new checking is needed. # # Return values # # o ERROR, is set to the return value of the program. # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_ANNOYANCE_PRG = "/usr/bin/nice -n 5 /usr/bin/annoyance-filter" # JA_UBE_ANNOYANCE_SPAM_DB = $HOME/.annoyance/dict.db # INCLUDERC = $PMSRC/pm-jaube-prg-spamprobe.rc # # # The ERROR will contains word "yes" if message was spam # # :0 : # * ERROR ?? yes # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-annoyance-filter.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_ANNOYANCE_PRG = ${JA_UBE_ANNOYANCE_PRG:-""} # There is no default location for the dictionaly file, so these # variables *must* be set in order to activate this module. JA_UBE_ANNOYANCE_SPAM_DB_OPT = ${JA_UBE_ANNOYANCE_SPAM_DB_OPT:-"--read"} JA_UBE_ANNOYANCE_SPAM_DB = ${JA_UBE_ANNOYANCE_SPAM_DB:-""} # The header name with no colon at the end. If this variable # is empty, then external formail call is saved - results can still # be checked from variable ERROR. There is no trailing colon in this # variable. JA_UBE_ANNOYANCE_HEADER = ${JA_UBE_ANNOYANCE_HEADER:-"\ X-Spam-Annoyance-"} # Should we check even if there already was header # JA_UBE_ANNOYANCE_HEADER JA_UBE_ANNOYANCE_FORCE = ${JA_UBE_ANNOYANCE_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variable :0 * JA_UBE_ANNOYANCE_PRG ?? [a-z] * JA_UBE_ANNOYANCE_SPAM_DB ?? [a-z] *$ ! 9876543210^0 ^$JA_UBE_ANNOYANCE_HEADER * 9876543210^0 JA_UBE_ANNOYANCE_FORCE ?? yes { # Will return headers like: # # X-Annoyance-Filter-Junk-Probability: 0 # X-Annoyance-Filter-Classification: Mail :0 w : spamannoyance$LOCKEXT jaubeAnnoyanceData=|$JA_UBE_ANNOYANCE_PRG \ $JA_UBE_ANNOYANCE_SPAM_DB_OPT \ $JA_UBE_ANNOYANCE_SPAM_DB \ --transcript - --test - :0 * jaubeAnnoyanceData ?? ^X-Annoyance-Filter-Junk-Probability: \/.+ { jaubeAnnoyanceScore = $MATCH :0 * jaubeAnnoyanceData ?? ^X-Annoyance-Filter-Classification: \/.+ { jaubeAnnoyanceType = $MATCH :0 * jaubeAnnoyanceType ?? Junk { ERROR = "yes" } } :0 fw * ! JA_UBE_ANNOYANCE_HEADER ?? ^^^^ | ${FORMAIL:-formail} \ -I "${JA_UBE_ANNOYANCE_HEADER}Status: ${ERROR:-no}" \ -I "${JA_UBE_ANNOYANCE_HEADER}Classification: $jaubeAnnoyanceType" \ -I "${JA_UBE_ANNOYANCE_HEADER}Probability: $jaubeAnnoyanceScore" } } dummy = "pm-jaube-prg-annoyance-filter.rc: end: $ERROR" # End of file procmail-lib-2009.1202/lib/pm-jaube-prg-bmf.rc000066400000000000000000000241411130547513300205330ustar00rootroot00000000000000# pm-jaube-prg-bmf.rc -- Interface to Bayesian Mail Filter program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages # are filed first (mailing lists, your work and private mail, # bounces) and only the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ ls spam/*.mail | xargs -n 1 bmf -s # feed individual messages # $ ls good/*.mail | xargs -n 1 bmf -n # feed individual messages # # To test # # $ bmf -p < test.mail | less # # Overview of features # # o Implements interface to http://www.sf.net/projects/bmf # "Bayesian Mail Filter" project. The called binary is "bmf" # hence the name of this subroutine. Bmf program uses well # know statistical analysis which is much more reliable than # any hand made procmail scripts could ever achieve. # o Variable `ERROR' is set if the message was UBE. # o Results are available in headers `X-Spam-bmf-Status' and # `X-Spam-bmf-Flag' for further analysis. # # Description # # There are several bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the # UBE detection. # # For serious discussion of strenghts of the different programs, # refer to a very good article "Spam Filters" by Sam Holden at # 2004-08-16 . The # article evaluated throughly following programs: # # o Bayesian Mail Filter (bayesian) # o Bogofilter (bayesian) # o dbacl (bayesian; multiple wordlists) # o Quick Spam Filter (bayesian) # o SpamAssassin (perl matching + bayesian) # o SpamProbe (bayesian) # o SPASTIC (procmail recipes) # # This subroutine implements call interface to `bmf' program. Why # whould you need it? Because unfortunately `bmf' by default # use exactly the same headers as spamasassin and the two cannot # co-operate together: bmf would overwrite existing # spamassasin headers. This subroutine takes care of saving # previous headers and move `bmf' results to their own # `X-Spam-bmf-*' headers. # # About bouncing message back # # The general consensus is, that you should not send bounces. # The UBE sender is not there, because the address forged. Do # not increase the network traffic; you will not do any good to # anybody by bouncing messgas -- you just increase mail traffic # even more. Instead save the messages to folders and # periodically periodically check their contents. # # Required settings # # If `bmf' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_BMF_PRG = "/usr/bin/bmf" # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o JA_UBE_BMF_PRG, path to program # o JA_UBE_BMF_HEADER_PREFIX, the header name where the results # are put. If not defined, no headers are added. Default # value is `X-Spam-bmf'. # o JA_UBE_BMF_FORCE, if set to _yes_ then call program no matter # what. Normally if there already are `X-Spam-bmf-*' headers, # it is assumed that the message has already been checked # and no new checking is needed. # # Return values # # o ERROR, is set to short ube trigger recipe reason. Contains # content of `X-Spam-bmf-Status' header which you can check # for values # o ERROR_MATCH contains detailed content of # `X-Spam-bmf-Status' header. # # If headers were enabled, they will contain: # # X-Spam-bmf-Status: Yes, hits=1.000000 required=0.900000, tests=bmf # X-Spam-bmf-Flag: YES # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_BMF_PRG = "/usr/bin/nice -n 5 /usr/bin/bmf" # INCLUDERC = $PMSRC/pm-jaube-prg-bmf.rc # # # The ERROR will contains word "yes" if it program classified # # the message into "bad" category. # # :0 : # * ERROR ?? yes # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-bmf.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_BMF_PRG = ${JA_UBE_BMF_PRG:-""} JA_UBE_BMF_PRG_OPT = ${JA_UBE_BMF_PRG_OPT:-"-p"} # The header name prefix with no colon at the end. If this variable # is empty, then `formail' is not called and no headers are added to # the message. This saves a shell call and will make this repice a # bit faster. The return status can still be checked from variable # ERROR JA_UBE_BMF_HEADER_PREFIX = ${JA_UBE_BMF_HEADER_PREFIX:-"X-Spam-Bmf-"} # Should we run the check even if there aready were header # JA_UBE_BMF_HEADER_PREFIX? Setting to 'yes' might mean: # # o We suspect that someone else had added the header, so don't # trust it but generate our own # o We don't trust the local MDA's result (if it had invoked # bmf for us), because we want' to run the message # through our own trained database # o Or, we're simply testing and have several INCLUDERC=$RC_UBE_BMF # calls in our ~/.procmailrc to find out what location would be the # best (beginning, middle, last) by examining the procmail LOGFILE. JA_UBE_BMF_FORCE = ${JA_UBE_BMF_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variable # The condition below reads: # - Require that variable is defined (contains path to 'bmf' program) # - Run immediately: if there is no X-spambmf header # - OR Run immediately: (even if there were headers) forced evaluation :0 * JA_UBE_BMF_PRG ?? [a-z] *$ 9876543210^0 ! ^$JA_UBE_BMF_HEADER_PREFIX * 9876543210^0 ! JA_UBE_BMF_FORCE ?? yes { # Unfortunately bmf inserts same headers as Spamassassin (SA), so # we must first save previous SA values. Kill variables first # # Note: the initial value is set here to header name, so that if # there is no previous SA headers, they will be left empty. This # works fine, because e.g. "formail -I X-Name:" does nothing when # message does not include "X-Name:" header. dummy = "pm-jaube-prg-bmf.rc: saving previous X-Spam-* headers" jaubeBmfSaStatus = "X-Spam-Status:" jaubeBmfSaFlag = "X-Spam-Flag:" :0 * ^\/X-Spam-Status:.* * ! ^\/X-Spam-Status:.*tests=bmf { jaubeBmfSaStatus = $MATCH :0 * ^\/X-Spam-Flag:.* { jaubeBmfSaFlag = $MATCH } } # Now run the filter with -p "pass through". jaubeBmfStatus jaubeBmfFlag :0 fw : bmf$LOCKEXT | $JA_UBE_BMF_PRG ${JA_UBE_BMF_PRG_OPT} # After previous call, there should be these headers. It is unfortunate, # that "tests=bmf" is not included with "No" case # # X-Spam-Status: No, hits=0.000000 required=0.900000 # X-Spam-Status: Yes, hits=1.000000 required=0.900000, tests=bmf # X-Spam-Flag: YES :0 a * ^X-Spam-Status: \/.+ { :0 * ^X-Spam-Status: \/.+tests=bmf { ERROR = $MATCH } jaubeBmfStatus = "${JA_UBE_BMF_HEADER_PREFIX}Status: $MATCH" jaubeBmfFlag = "${JA_UBE_BMF_HEADER_PREFIX}Flag:" # Initial value :0 * ^X-Spam-Flag: \/.* { jaubeBmfFlag = "$jaubeBmfFlag $MATCH" } dummy = "pm-jaube-prg-bmf.rc: restore X-Spam-* / add X-Spam-Bmf headers" # Rearrange headers nicely and put back all Spamassassin values :0 fhw * ! jaubeBmfSaStatus ?? ^^^^ * ! jaubeBmfSaFlag ?? ^^^^ * ! jaubeBmfStatus ?? ^^^^ * ! jaubeBmfFlag ?? ^^^^ | ${FORMAIL:-formail} \ -I "$jaubeBmfSaStatus" \ -I "$jaubeBmfSaFlag" \ -I "$jaubeBmfStatus" \ -I "$jaubeBmfFlag" } } dummy = "pm-jaube-prg-bmf.rc: end: $ERROR" # pm-jaube-prg-bmf.rc ends here procmail-lib-2009.1202/lib/pm-jaube-prg-bogofilter.rc000066400000000000000000000167211130547513300221300ustar00rootroot00000000000000# pm-jaube-prg-bogofilter -- Interface to bogofilter program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ rm -f ~/.bogofilter/*.db # delete database # $ bogofilter -B -n good.msg ... # $ bogofilter -B -s spam.msg ... # # Overview of features # # o Implements interface to http://www.sf.net/projects/bogofilter # project. # o variable `ERROR' is set if message was likely spam. # o Results are available by default in header # `X-Spam-Bogofilter-Status'. # # Description # # There are several Bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # This procmail subroutine implements call interface to program # `bogofilter', which must already have been installed. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `bogofilter' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_BOGOFILTER_PRG = /usr/bin/bogofilter # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o JA_UBE_BOGOFILTER_PRG, path to the program # o JA_UBE_BOGOFILTER_HEADER_NEW, the header name where the results # are put. If not defined, no header is added. # Defaults to `X-Spam-Bogofilter-Status' # o JA_UBE_BOGOFILTER_FORCE, if set to _yes_ then call program no matter # what. Normally if there already is `X-Spam-*' header, # it is assumed that the message has already been checked # and no new checking is needed. # # Return values # # o ERROR, is set to the return value of program if message was spam. # o ERROR_INFO, is set if case is "unsure". # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_BOGOFILTER_PRG = "/usr/bin/nice -n 5 /usr/bin/bogogilter" # INCLUDERC = $PMSRC/pm-jaube-prg-bogofilter.rc # # # The ERROR will contains reason if program classified # # the message into "bad" category. # # :0 : # * ! ERROR ?? ^^^^ # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-bogofilter.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_BOGOFILTER_PRG = ${JA_UBE_BOGOFILTER_PRG:-""} JA_UBE_BOGOFILTER_OPT = ${$JA_UBE_BOGOFILTER_OPT:-""} # No user options cannot be passed, because the output would # change. This variable is not used. # JA_UBE_BOGOFILTER_PRG_OPT = ${JA_UBE_BOGOFILTER_PRG_OPT:-""} # The original header name. JA_UBE_BOGOFILTER_HEADER_ORIGINAL = ${JA_UBE_BOGOFILTER_HEADER_ORIGINAL:-"\ X-Bogosity"} # The header name with no colon at the end. If this variable # is empty, then external formail call is saved - results can still # be checked from variable ERROR. JA_UBE_BOGOFILTER_HEADER_NEW = ${JA_UBE_BOGOFILTER_HEADER:-\ "X-Spam-bogofilter-Status"} # Should we check even if there already was already header # 'JA_UBE_BOGOFILTER_HEADER' ? JA_UBE_BOGOFILTER_FORCE = ${JA_UBE_BOGOFILTER_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variables ERROR_INFO :0 * JA_UBE_BOGOFILTER_PRG ?? [a-z] *$ ! 9876543210^0 ^$JA_UBE_BOGOFILTER_HEADER_NEW * 9876543210^0 JA_UBE_BOGOFILTER_FORCE ?? yes { # This call will add header. Notice that newer version output # "Ham" instead of "No" # # X-Bogosity: No, tests=bogofilter, spamicity=0.000111, version=0.92.5 # X-Bogosity: Ham, tests=bogofilter, spamicity=0.004063, version=0.93.2 # X-Bogosity: Unsure, tests=bogofilter, spamicity=0.499327, version=0.92.5 # X-Bogosity: Yes, tests=bogofilter, spamicity=1.000000, version=0.92.5 jaubeBogoHdr # Kill variable :0 * ! JA_UBE_BOGOFILTER_HEADER_NEW ?? ^^^^ { jaubeBogoHdr = $JA_UBE_BOGOFILTER_HEADER_NEW # -e = Exit with code 0 if message is ham/unsure. # -p = Pass through :0 fhbw # : bogofilter$LOCKEXT | $JA_UBE_BOGOFILTER_PRG \ -e \ -p \ --spam-header-name="$JA_UBE_BOGOFILTER_HEADER_NEW" \ $JA_UBE_BOGOFILTER_OPT } :0 E { jaubeBogoHdr = $JA_UBE_BOGOFILTER_HEADER_ORIGINAL :0 fhbw : bogofilter$LOCKEXT | $JA_UBE_BOGOFILTER_PRG -e -p $JA_UBE_BOGOFILTER_OPT } # Bogofilter returns three status messages: Yes, Unsure, No|Ham # Save the value for user to check :0 *$ ^$jaubeBogoHdr: \/yes.* { ERROR = "bogofilter; $MATCH" } :0 E *$ ^$jaubeBogoHdr: \/unsure.* { ERROR_INFO = "bogofilter; $MATCH" } :0 E *$ ^$jaubeBogoHdr: \/.+ { # Do nothing. Just record bogofilter response to log file } } dummy = "pm-jaube-prg-bogofilter.rc: end: $ERROR" # End of file procmail-lib-2009.1202/lib/pm-jaube-prg-bsfilter.rc000066400000000000000000000157711130547513300216120ustar00rootroot00000000000000# pm-jaube-prg-bsfilter.rc -- Interface to Bsfilter program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ bsfilter --add-clean good.msg ... # $ bsfilter --add-spam spam.msg ... # # Overview of features # # o Implements interface to project # http://packages.debian.org/testing/mail/bsfilter # o variable `ERROR' is set if the message was UBE. # o Results are available by default in header # `X-Spam-Bsfilter-Status'. # # Description # # There are several Bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # This procmail subroutine implements call interface to program # `bsfilter', which must already have been installed. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `bsfilter' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_BSFILTER_PRG = /usr/bin/bsfilter # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o `JA_UBE_BSFILTER_PRG', path to the program. # o `JA_UBE_BSFILTER_HEADER', the header prefix name where the results # are put. If not defined, no header is added. # Defaults to *X-Spam-Bsfilter-* # o `JA_UBE_BSFILTER_FORCE', if set to _yes_ then call program no matter # what. Normally if there already is *X-Spam-Bsfilter-* header, # it is assumed that the message has already been checked # and no new checking is needed. # # Return values # # o `ERROR', is set to the return value of `bsfilter' program. # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_BSFILTER_PRG = "/usr/bin/nice -n 5 /usr/bin/bsfilter" # INCLUDERC = $PMSRC/pm-jaube-prg-bsfilter.rc # # # The ERROR will contains word "yes" if message was spam # # :0 : # * ERROR ?? yes # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-bsfilter.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_BSFILTER_PRG = ${JA_UBE_BSFILTER_PRG:-""} # You could use "--update" if database is well trained. JA_UBE_BSFILTER_PRG_OPT = ${JA_UBE_BSFILTER_PRG_OPT:-""} # The header prefix name. If this variable is empty, then external # formail call is saved - results can still be checked from variable # ERROR. JA_UBE_BSFILTER_HEADER = ${JA_UBE_BSFILTER_HEADER:-"\ X-Spam-Bsfilter-"} # Should we check even if there already was header # JA_UBE_BSFILTER_HEADER JA_UBE_BSFILTER_FORCE = ${JA_UBE_BSFILTER_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variable :0 * JA_UBE_BSFILTER_PRG ?? [a-z] *$ ! 9876543210^0 ^$JA_UBE_BSFILTER_HEADER * 9876543210^0 JA_UBE_BSFILTER_FORCE ?? yes { # bsfilter uses same headers as spamassassin, so we must # read the results separately. :0 w : bsfilter$LOCKEXT jaubeBsfilterData=|$JA_UBE_BSFILTER_PRG \ --pipe \ --insert-revision \ --insert-flag \ --insert-probability \ $BSFILTER_OPT # X-Spam-Revision: bsfilter release 1.0.4 revision 1.63 # X-Spam-Flag: No # X-Spam-Probability: 0.906504 jaubeBsfilterVer # Kill variables jaubeBsfilterFlag jaubeBsfilterStatus :0 * jaubeBsfilterData ?? X-Spam-Revision: \/.*bsfilter { jaubeBsfilterVer = $MATCH :0 * jaubeBsfilterData ?? X-Spam-Flag: \/.+ { jaubeBsfilterFlag = $MATCH } :0 * jaubeBsfilterData ?? X-Spam-Probability: \/.+ { jaubeBsfilterStatus = $MATCH } :0 * jaubeBsfilterFlag ?? yes { ERROR = "yes" :0 * ! jaubeBsfilterStatus ?? ^^^^ { ERROR = "$ERROR $jaubeBsfilterStatus" } } } :0 fw * ! JA_UBE_BSFILTER_HEADER ?? ^^^^ * ! jaubeBsfilterFlag ?? ^^^^ | ${FORMAIL:-formail} \ -I "${JA_UBE_BSFILTER_HEADER}Flag: $jaubeBsfilterFlag" \ -I "${JA_UBE_BSFILTER_HEADER}Status: $jaubeBsfilterStatus" \ -I "${JA_UBE_BSFILTER_HEADER}Version: $jaubeBsfilterVer" } dummy = "pm-jaube-prg-bsfilter.rc: end: $ERROR" # End of file procmail-lib-2009.1202/lib/pm-jaube-prg-ifile.rc000066400000000000000000000150021130547513300210530ustar00rootroot00000000000000# pm-jaube-prg-ifile -- Interface to ifile program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ rm ~/.idata # delete database # $ echo herbalife | ifile -i spam # initialize database # $ ifile -h -i good good.msg ... # $ ifile -h -i spam spam.msg ... # # Overview of features # # o Implements interface to http://freshmeat.net/projects/ifile # project. # o variable `ERROR' is set to the result of ifile check. This # usually holds the "folder" name the ifile was trained at the # time. E.g. if the folder used for training Unsolicited Bulk # Email was "ifile -i spam", then the return value is "spam". # o Results are available by default in header `X-Spamifile'. # # Description # # There are several Bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # This procmail subroutine implements call interface to program # `ifile', which must already have been installed. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `ifile' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_IFILE_PRG = /usr/bin/ifile # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o JA_UBE_IFILE_PRG, path to the program # o JA_UBE_IFILE_HEADER, the header name where the results # are put. If not defined, no header is added. # Defaults to `X-Spam-Ifile-Status' # o JA_UBE_IFILE_FORCE, if set to _yes_ then call program no matter # what. Normally if there already is header, # it is assumed that the message has already been checked # and no new checking is needed. # # Return values # # o ERROR, is set to the return value of `ifile' program. # # If header output is enabled, it will contain the folder name # `ifile' thinks the message belongs to. Assuming that trained # folders used for messages were *spam* and *good*, then the headers # read: # # X-Spam-Ifile-Status: spam # X-Spam-Ifile-Status: good # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_IFILE_PRG = "/usr/bin/nice -n 5 /usr/bin/ifile" # INCLUDERC = $PMSRC/pm-jaube-prg-ifile.rc # # # The ERROR will contains reason if program classified # # the message into "bad" category. # # :0 : # * ! ERROR ?? ^^^^ # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-ifile.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_IFILE_PRG = ${JA_UBE_IFILE_PRG:-""} # No user options cannot be passed to ifile, because the output would # change. This variable is not used. # JA_UBE_IFILE_PRG_OPT = ${JA_UBE_IFILE_PRG_OPT:-""} # The header name with no colon at the end. If this variable # is empty, then external formail call is saved - results can still # be checked from variable ERROR. JA_UBE_IFILE_HEADER = ${JA_UBE_IFILE_HEADER:-\ "X-Spam-Ifile-Status"} # Should we check even if there already was header # JA_UBE_IFILE_HEADER ? JA_UBE_IFILE_FORCE = ${JA_UBE_IFILE_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variable :0 * JA_UBE_IFILE_PRG ?? [a-z] *$ ! 9876543210^0 ^$JA_UBE_IFILE_HEADER * 9876543210^0 JA_UBE_IFILE_FORCE ?? yes { :0 w : ifile$LOCKEXT jaubeIfileFolder=|$JA_UBE_IFILE_PRG --strip-header --query --concise :0 * ! jaubeIfileFolder ?? ^^^^ { ERROR = $jaubeIfileFolder :0 fhw * ! JA_UBE_IFILE_HEADER ?? ^^^^ | ${FORMAIL:-formail} -I "$JA_UBE_IFILE_HEADER: $jaubeIfileFolder" } } dummy = "pm-jaube-prg-ifile.rc: end: $ERROR" # End of file procmail-lib-2009.1202/lib/pm-jaube-prg-runall.rc000066400000000000000000000164021130547513300212650ustar00rootroot00000000000000# pm-jaube-prg-runall.rc -- Interface to all Bayesian filter programs # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Overview of features # # o To detect spam reliably, run all Bayesian programs one by one # to see if any of them classifies the message as spam. # o Programs supported: bogofilter, spamprobe, Bayesian Mail # Filter, Annoyance Filter, Bsfilter, Spamoracle and Spamassassin. # # Description # # There are several bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. This module is a # _meta_ _package_ which will call all other individual modules # that interface to these Bayesian programs. The use is simple: define # programs that are available in your system and which you have # trained (Bayesian programs need to be trained before use), and this # this module will query how those programs would classify the message. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # o pm-jaube-prg-spamprobe.rc # o pm-jaube-prg-spamoracle.rc # o pm-jaube-prg-annoyance-filter.rc # o pm-jaube-prg-bsfilter.rc # o pm-jaube-prg-bmf.rc # # Call arguments (variables to set before calling) # # To activate Bayesian program(s), define path to them. Default # value for all these variables is "" i.e. is is supposed that # no programs have been installed or trained. # # o `JA_UBE_BOGOFILTER_PRG', path to *bogofilter* program. # o `JA_UBE_SPAMPROBE_PRG', Path to *spamprobe* program # o `JA_UBE_BMF_PRG', Path to Bayesian Mail Filter *bmf* program. # o `JA_UBE_SPAMASSASSIN_PRG', path to *spamassassin* program. # If daemon version is available, set this to *spamc* program. # o `JA_UBE_SPAMORACLE_PRG', path to *spamoracle* program. # o `JA_UBE_ANNOYANCE_PRG', path to *annoyance-filter* program. # You must also set `JA_UBE_ANNOYANCE_SPAM_DB' to fast # dictionary database location. # o `JA_UBE_BSFILTER_PRG', path to *bsfilter* program. # # Optional variables to set: # # o `JA_UBE_BOGOFILTER_OPT'. Default is "-p" passthrough. # Option "-e" will report exit code to procmail. # o `JA_UBE_SPAMASSASSIN_OPT'. Default is "". # o `JA_UBE_SPAMASSASSIN_MAX_SIZE'. Default is 256000 (256k). # Spamassassin is a Perl program, which is slow at startup, # so checking e.g. long attachements consumes lot of resources. # Keep this value relatively small. # # Important notes # # All headers are canonicalized to *X-Spam--* so e.g. # in bogofilter's case, the default *X-Bogocity* header is # changed to value *X-Spam-Bogofilter-Status* and so on. # Summaries like below can then be generated: # # $ egrep -i '(Subject|From|^X-Spam.*Status)' *.mbox # # Return values # # o `ERROR' variable's first word is set to program that classified # the spam: *bogofilter*, *bmf* (Bayesian Mail Filter), # *spamassassin* etc. It is followed by semicolon ";" and # detailed return status from the program. # o `ERROR_INFO' is set only in bogofilter's case if it thinks # the message is neither spam nor ham ("Unsure"). # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # ... other checks, mailing lists, work mail etc. # # # bogofilter and Bayesian Mail Filter available and trained. Use them. # # JA_UBE_BOGOFILTER_PRG = "/bin/nice -n 5 /bin/bogofilter" # JA_UBE_BMF_PRG = "/bin/nice -n 5 /bin/bmf" # # # Call the "umbrella" module, which will take care of # # all the details. # # INCLUDERC = $PMSRC/pm-jaube-prg-runall.rc # # # ERROR is set if message was spam. The "()\/" logs reason. # # :0 : # * ERROR ?? ^()\/.+ # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-runall.rc: init:" # Kill variables ERROR ERROR_INFO dummy = "pm-jaube-prg-runall: Run Bogofilter" :0 * ERROR ?? ^^^^ * JA_UBE_BOGOFILTER_PRG ?? [a-z] { INCLUDERC = $RC_UBE_BOGOFILTER :0 * ERROR ?? ^()\/spam.* { ERROR = "bogofilter; $MATCH" } :0 E { ERROR # Kill variable } } dummy = "pm-jaube-prg-runall: Run Spamprobe" :0 * ERROR ?? ^^^^ * JA_UBE_SPAMPROBE_PRG ?? [a-z] { INCLUDERC = $RC_UBE_SPAMPROBE :0 * ERROR ?? ^()\/spam.* { ERROR = "spamprobe; $MATCH" } :0 E { ERROR } } dummy = "pm-jaube-prg-runall: Run Annoyance filter" :0 * ERROR ?? ^^^^ * JA_UBE_ANNOYANCE_PRG ?? [a-z] { INCLUDERC = $RC_UBE_ANNOYANCE :0 * ERROR ?? yes { ERROR = "annoyance-filter; $MATCH" } :0 E { ERROR } } dummy = "pm-jaube-prg-runall: Run Bayesian Mail Filter" :0 * ERROR ?? ^^^^ * JA_UBE_BMF_PRG ?? [a-z] { INCLUDERC = $RC_UBE_BMF :0 * ERROR ?? ^()\/yes.* { ERROR = "bmf; $MATCH" } :0 E { ERROR } } dummy = "pm-jaube-prg-runall: Run Spamassassin" :0 * ERROR ?? ^^^^ * JA_UBE_SPAMASSASSIN_PRG ?? [a-z] { INCLUDERC = $RC_UBE_SPAMASSASSIN :0 * ERROR ?? yes { ERROR = "spamassassin; $MATCH" } :0 E { ERROR } } dummy = "pm-jaube-prg-runall: Run Bsfilter" :0 * ERROR ?? ^^^^ * JA_UBE_BSFILTER_PRG ?? [a-z] { INCLUDERC = $RC_UBE_BSFILTER :0 * ERROR ?? yes { ERROR = "bsfilter; $MATCH" } :0 E { ERROR } } dummy = "pm-jaube-prg-runall: Run Spamoracle" :0 * ERROR ?? ^^^^ * JA_UBE_SPAMORACLE_PRG ?? [a-z] { # We must run spamoracle last, because it lacks the ability # to read message from stdin. Due to this many shell calls # are needed. See the RC file for more information. INCLUDERC = $RC_UBE_SPAMORACLE :0 * ERROR ?? yes { ERROR = "spamoracle; $MATCH" } :0 E { ERROR } } dummy = "pm-jaube-prg-runall.rc: end: $ERROR" # pm-jaube-prg-bmf.rc ends here procmail-lib-2009.1202/lib/pm-jaube-prg-spamassassin.rc000066400000000000000000000203261130547513300224750ustar00rootroot00000000000000# pm-jaube-prg-spamassassin -- Interface to spamassassin program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ rm -f ~/.spamassassin/bayes* # $ sa-learn $opt --local --no-rebuild --ham good.msg ... # $ sa-learn $opt --local --no-rebuild --spam spam.msg ... # $ sa-learn --rebuild # # Overview of features # # o Implements interface to http://www.spamassassin.org/ # project. # o variable `ERROR' is set if message was spam. # o Results are available in default headers (X-Spam-*) # # Description # # There are several Bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # This procmail subroutine implements call interface to program # `spamassassin', which must already have been installed. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `spamassassin' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_SPAMASSASSIN_PRG = /usr/bin/spamassassin # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o JA_UBE_SPAMASSASSIN_PRG, path to the program # o JA_UBE_SPAMASSASSIN_MIN_SIZE, minumum message size. Default is # 100 bytes. # o JA_UBE_SPAMASSASSIN_MAX_SIZE, maximum message size. Default is # 256 000 bytes (about 256k). # o JA_UBE_SPAMASSASSIN_FORCE, if set to _yes_ then call program no # matter what. Normally if there already is `X-Spam-*' header, # it is assumed that the message has already been checked # and no new checking is needed. # # Return values # # o ERROR, is set to the return value of program if message was spam. # o ERROR_INFO, is set if case is "unsure". # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/nice -n 5 /usr/bin/bogofilter" # INCLUDERC = $PMSRC/pm-jaube-prg-spamassassin.rc # # # The ERROR will contains reason if program classified # # the message into "bad" category. # # :0 : # * ! ERROR ?? ^^^^ # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-spamassassin.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_SPAMASSASSIN_PRG = ${JA_UBE_SPAMASSASSIN_PRG:-""} # No user options cannot be passed, because the output would # change. This variable is not used. # JA_UBE_SPAMASSASSIN_PRG_OPT = ${JA_UBE_SPAMASSASSIN_PRG_OPT:-""} # Theshold values when to run spamassassin for a message. JA_UBE_SPAMASSASSIN_MIN_SIZE = ${JA_UBE_SPAMASSASSIN_MIN_SIZE:-100} JA_UBE_SPAMASSASSIN_MAX_SIZE = ${JA_UBE_SPAMASSASSIN_MAX_SIZE:-256000} # Headers of earlier run of the program. No trailing colon. JA_UBE_SPAMASSASSIN_HEADER_FLAG = ${JA_UBE_SPAMASSASSIN_HEADER_FLAG:-\ "X-Spam-Flag"} JA_UBE_SPAMASSASSIN_HEADER_STATUS = ${JA_UBE_SPAMASSASSIN_HEADER_STATUS:-\ "X-Spam-Status"} # Should we check even if there already was header # JA_UBE_SPAMASSASSIN_HEADER ? JA_UBE_SPAMASSASSIN_FORCE = ${JA_UBE_SPAMASSASSIN_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variables ERROR_INFO :0 * JA_UBE_SPAMASSASSIN_PRG ?? [a-z] *$ ! 9876543210^0 ^$JA_UBE_SPAMASSASSIN_HEADER_FLAG * 9876543210^0 JA_UBE_SPAMASSASSIN_FORCE ?? yes { # Last, run spamassassin if it has not already been run # system wide at MTA level. NOTE: run spamassassin # absolutely _last_ and only _if_ message was still not # detected as Unsolicited Bulk Email by previous recipes. # # A lock is used so that only one program is run at a time. # X-Spam-Flag just tests if systemwide SA has already # been run => Headers are there already and we should save CPU # and not call SA again. Skip too long messages (256K) :0 *$ > $JA_UBE_SPAMASSASSIN_MIN_SIZE *$ < $JA_UBE_SPAMASSASSIN_MAX_SIZE { jaubeSaved = $LINEBUF LINEBUF = $JA_UBE_SPAMASSASSIN_MAX_SIZE # This is Procmail's global variable. Kill it for now. PROCMAIL_OVERFLOW # The message must be saved, because if there is # a problem with SA call, it will trash the whole message. :0 * HB ?? ^^\/(.*$)+$ { jaubeSavedMsg = $MATCH } # Procmail will set PROCMAIL_OVERFLOW if 'jaubeSavedMsg' # cannot hold the content # # procmail: Exceeded LINEBUF # procmail: Assigning "PROCMAIL_OVERFLOW=yes" :0 fhbw : spamassassin$LOCKEXT * PROCMAIL_OVERFLOW ?? ^^^^ | ${JA_UBE_SPAMASSASSIN_PRG} ${JA_UBE_SPAMASSASSIN_OPT:-""} # Check if SA trashed the message. This is usually due # to errors in environment. # # procmail: Executing "/usr/bin/spamassassin," # Use of uninitialized value in pattern match (m//) at /usr/share/perl5/Mail/SpamAssassin/ArchiveIterator.pm line 571. # ... # Unable to open : No such file or directory :0 * HB ?? 1^1 ^.+ { } # If no lines were found, then message was trashed. Restore :0 E fhbw * jaubeSavedMsg ?? [a-z] | echo -e "$jaubeSavedMsg" LINEBUF = $jaubeSaved } :0 *$ ^$JA_UBE_SPAMASSASSIN_HEADER_FLAG: yes *$ ^$JA_UBE_SPAMASSASSIN_HEADER_STATUS: \/.* { ERROR = "spamassassin; $MATCH" } } dummy = "pm-jaube-prg-spamassassin.rc: end: $ERROR" # End of file procmail-lib-2009.1202/lib/pm-jaube-prg-spamoracle.rc000066400000000000000000000242271130547513300221220ustar00rootroot00000000000000# pm-jaube-prg-spamoracle.rc -- Interface to Spamoracle program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ spamoracle add -v -spam good.msg ... # feed individual messages # $ spamoracle add -v -good good.msg ... # feed individual messages # # To test # # $ spamoracle test mail.msg | less # # Overview of features # # o Implements interface to http://freshmeat.net/projects/spamoracle # OCaml language based Bayesian Mail program. # o Variable `ERROR' is set to "yes" if the message was UBE. # o Results are available in headers `X-Spam-Spamoracle-Status', # `X-Spam-Spamoracle-Score', `X-Spam-Spamoracle-Details' and # `X-Spam-Spamoracle-Attachment' for further analysis. # # Description # # There are several bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # # Using Spamoracle as sole spam protection is inefficient, because # version version 1.4 (2004-09-29) does not accept messages from # stdin. Becaus of this message has to be written to a temporary file # before calling Spamoracle. Later the temporary file must be removed # with `rm'. All these three shell calls are needed for each message. # If you have other detection programs, call them first to identify # unsolicited Bulk Email. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `spamoracle' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_SPAMORACLE_PRG = /usr/bin/spamoracle # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o `JA_UBE_SPAMORACLE_PRG', path to program # o `JA_UBE_SPAMORACLE_HEADER_PREFIX', the header name where the results # are put. If not defined, no headers are added. Default # value is *X-Spam-Spamoracle'*. # o `JA_UBE_SPAMORACLE_FORCE', if set to _yes_ then call program no matter # what. Normally if there already are *X-Spam-Spamoracle-* headers, # it is assumed that the message has already been checked # and no new checking is needed. # o `JA_UBE_SPAMORACLE_REGEXP', regexp to match for spam probability. # Defaul value will match probabbility of 0.8 with 5 interesting words. # The match is tried agains *X-Spam-Spamoracle-Score* header. # # Return values # # o `ERROR', value "yes" if `JA_UBE_SPAMORACLE_REGEXP' matched. # o `ERROR_MATCH' contains detailed content of # `X-Spam-Spamoracle-Score' header. # # If headers were enabled, they will contain these values. The # score's values are spam probability 0.0 - 1.0 and the degree of # similarity 0-15 of the message with the spam messages in the # corpus. # # X-Spam-Spamoracle-Status: yes # X-Spam-Spamoracle-Score: 1.00 -- 15 # X-Spam-Spamoracle-Details: refid:98 $$$$:98 surfing:98 asp:95 click:93 # cable:92 instantly:90 https:88 internet:87 www:86 U4:85 isn't:14 month:81 # com:75 surf:75 # X-Spam-Spamoracle-Attachments: cset="GB2312" type="application/octet-stream" # name="Guangwen4.zip" # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_SPAMORACLE_PRG = "/usr/bin/nice -n 5 /usr/bin/bmf" # INCLUDERC = $PMSRC/pm-jaube-prg-spamoracle.rc # # # The ERROR will contains word "yes" if it program classified # # the message into "bad" category. # # :0 : # * ERROR ?? yes # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-spamoracle.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_SPAMORACLE_PRG = ${JA_UBE_SPAMORACLE_PRG:-""} # The header name prefix with no colon at the end. If this variable # is empty, then `formail' is not called and no headers are added to # the message. This saves a shell call and will make this repice a # bit faster. The return status can still be checked from variable # ERROR JA_UBE_SPAMORACLE_HEADER_PREFIX = ${JA_UBE_SPAMORACLE_HEADER_PREFIX:-"\ X-Spam-Spamoracle-"} # Should we run the check even if there aready were header # JA_UBE_SPAMORACLE_HEADER_PREFIX? Setting to 'yes' might mean: # # o We suspect that someone else had added the header, so don't # trust it but generate our own # o We don't trust the local MDA's result (if it had invoked # bmf for us), because we want' to run the message # through our own trained database # o Or, we're simply testing and have several INCLUDERC=$RC_UBE_SPAMORACLE calls # in our ~/.procmailrc to find out what location would be the # best (beginning, middle, last) by examining the procmail LOGFILE. JA_UBE_SPAMORACLE_FORCE = ${JA_UBE_SPAMORACLE_FORCE:-"no"} # This regexp is matched against header like below. If found, the ERROR # is set to "yes" to flag the spam. Range 0.8 - 1.00 and at least 5 # or more interesting words. # # X-Spam--Spamoracle-Score: 0.81 -- 5 JA_UBE_SPAMORACLE_REGEXP = "\ (\.[8-9]|1\.).* *-- *([5-9]|[0-9][0-9])" # Program cannot read message from STDIN, so we must write it to a file JA_UBE_SPAMORACLE_TMP_FILE = ${JA_UBE_SPAMORACLE_TMP_FILE:-\ $HOME/spamoracle-${USER:-${LOGNAME:-foo}}.tmp} # ............................................................ do it ... # Kill variables ERROR ERROR_MATCH :0 * JA_UBE_SPAMORACLE_PRG ?? [a-z] *$ 9876543210^0 ! ^$JA_UBE_SPAMORACLE_HEADER_PREFIX * 9876543210^0 ! JA_UBE_SPAMORACLE_FORCE ?? yes { jaubeSpamoracleData = "" jaubeSpamoracleDetails = "" jaubeSpamoracleAttach = "" # This area must be locked, so that no other process # is writing at the same time. LOCKFILE = spamoracle$LOCKEXT savedMetas = $SHELLMETAS savedShell = $SHELL SHELLMETAS = ">" SHELL = /bin/sh :0 wc | ${CAT:-/bin/cat} > $JA_UBE_SPAMORACLE_TMP_FILE :0 w jaubeSpamoracleData=| $JA_UBE_SPAMORACLE_PRG \ test \ $JA_UBE_SPAMORACLE_TMP_FILE dummy = `${RM:-/bin/rm} -f $JA_UBE_SPAMORACLE_TMP_FILE` SHELLMETAS = $savedMetas SHELL = $savedShell LOCKFILE # An empty message looks like this # # From: # Subject: # Score: 0.50 -- 0 # Details: :0 * jaubeSpamoracleData ?? ^From: .+ * jaubeSpamoracleData ?? ^(X-)?(Spam-)?Score: \/.+ { dummy = $jaubeSpamoracleData ERROR_MATCH = $MATCH :0 * jaubeSpamoracleData ?? ^(X-)?(Spam-)?Details:\/.+ { jaubeSpamoracleDetails = $MATCH } :0 * jaubeSpamoracleData ?? ^(X-)?(Spam-)?Attachments:\/.+ { jaubeSpamoracleAttach = $MATCH } dummy = "pm-jaube-prg-spamoracle.rc: Does score match?" :0 *$ ERROR_MATCH ?? $JA_UBE_SPAMORACLE_REGEXP { ERROR = "yes" } :0 fhw | ${FORMAIL:-formail} \ -I "${JA_UBE_SPAMORACLE_HEADER_PREFIX}Status: ${ERROR:-no}" \ -I "${JA_UBE_SPAMORACLE_HEADER_PREFIX}Score: $ERROR_MATCH" \ -I "${JA_UBE_SPAMORACLE_HEADER_PREFIX}Details:$jaubeSpamoracleDetails" \ -I "${JA_UBE_SPAMORACLE_HEADER_PREFIX}Attachments:$jaubeSpamoracleAttach" } } dummy = "pm-jaube-prg-spamoracle.rc: end: $ERROR" # pm-jaube-prg-spamoracle.rc ends here procmail-lib-2009.1202/lib/pm-jaube-prg-spamprobe.rc000066400000000000000000000154421130547513300217630ustar00rootroot00000000000000# pm-jaube-prg-spamprobe.rc -- Interface to Spamprobe program # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your Unsolicited Bulk Emacil (aka spam) filters towards the # end of your `~/.procmailrc'. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked last. # # YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE # BAYESIAN PROGRAM FIRST! # # To train: # # $ spamprobe -8 good good.msg ... # $ spamprobe -8 spam spam.msg ... # # Make sure there are no stale lock files, or the spamprobe and this # subroutine will hang infinitely: # # $ rm -f ~/.spamprobe/lock # # Overview of features # # o Implements interface to http://freshmeat.net/projects/spamprobe/ # project. # o variable `ERROR' is set if the message was UBE. # o Results are available by default in header # `X-Spam-Spamprobe-Status'. # # Description # # There are several Bayesian based statistical analysis programs that # study the message's tokens and then classify it into two categories: # good or bad, or if you like, ham and spam. All the Bayesian programs # are not the same, so if you want to achive magic 99.99% probability # the only methodology to do that is to chain several programs in # serially. There is no single program that can solve the UBE detection. # This procmail subroutine implements call interface to program # `spamprobe', which must already have been installed. # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address forged. Do not increase # the network traffic; you will not do any good to anybody by # bouncing messgas -- you just increase mail traffic even more. # Instead save the messages to folders and periodically periodically # check their contents. # # Required settings # # If `spamprobe' program is available, define this variable in your # `~/.procmailrc'. Use absolute path to make the external shell # quick; it'll save server load considerably. # # JA_UBE_SPAMPROBE_PRG = /usr/bin/spamprobe # # If you _do_ _not_ have program installed, do not leave the # variable lying aroung, because it will keep this subroutine active. # Calling a non existing program is not a good idea, so it better to # empty the variable if the program is not available. # # Required settings # # None. No dependencies to other procmail modules. # # Call arguments (variables to set before calling) # # o `JA_UBE_SPAMPROBE_PRG', path to the program. # o `JA_UBE_SPAMPROBE_HEADER', the header name where the results # are put. If not defined, no header is added. # Defaults to *X-Spam-Spamprobe-Status* # o `JA_UBE_SPAMPROBE_FORCE', if set to _yes_ then call program # no matter what. Normally if there already is # *X-Spam-Spamprobe-Status* header, it is assumed that the # message has already been checked and no new checking is # needed. # # Return values # # o `ERROR', is set to the return value of `spamprobe' program. # # Usage example # # PMSRC = $HOME/procmail # procmail recipe dir # # # # JA_UBE_SPAMPROBE_PRG = "/usr/bin/nice -n 5 /usr/bin/spamprobe" # INCLUDERC = $PMSRC/pm-jaube-prg-spamprobe.rc # # # The ERROR will contains word "yes" if message was spam # # :0 : # * ERROR ?? yes # junk.mbox # # File layout # # The layout of this file is managed by Emacs packages tinyprocmail.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # None dummy = " ======================================================================== pm-jaube-prg-spamprobe.rc: init:" # ................................................... User variables ... # You must define program path, because we don't know # if it has been installed in this system or not JA_UBE_SPAMPROBE_PRG = ${JA_UBE_SPAMPROBE_PRG:-""} # Command "score" examines the message # You could use command "train" is you have good database. JA_UBE_SPAMPROBE_PRG_OPT = ${JA_UBE_SPAMPROBE_PRG_OPT:-"score"} # The header name with no colon at the end. If this variable # is empty, then external formail call is saved - results can still # be checked from variable ERROR. There is no trailing colon in this # variable. JA_UBE_SPAMPROBE_HEADER = ${JA_UBE_SPAMPROBE_HEADER:-"\ X-Spam-Spamprobe-Status"} # Should we check even if there already was header # JA_UBE_SPAMPROBE_HEADER JA_UBE_SPAMPROBE_FORCE = ${JA_UBE_SPAMPROBE_FORCE:-"no"} # ............................................................ do it ... ERROR # Kill variable :0 * JA_UBE_SPAMPROBE_PRG ?? [a-z] *$ ! 9876543210^0 ^$JA_UBE_SPAMPROBE_HEADER * 9876543210^0 JA_UBE_SPAMPROBE_FORCE ?? yes { jaubeSpamprobeScore # Kill variable :0 w # : spamprobe$LOCKEXT jaubeSpamprobeScore=|$JA_UBE_SPAMPROBE_PRG ${SPAMPROBE_OPT:-"score"} # Check for failures; require (A)and condition # # procmail: Executing "/usr/bin/spamprobe,score" # error: unable to open database ....spamprobe/sp_words: # Cannot allocate memory # warning: berkeley db reported error: env close: Invalid argument (22) # caught runtime exception: unable to open words database # caught signal 11: cleaning up :0 A * jaubeSpamprobeScore ?? [a-z] { ERROR = $jaubeSpamprobeScore # X-Spam-Spamprobe-Status: GOOD 0.0000273 e5af974acad8028bea8a10f1f08b966e # X-Spam-Spamprobe-Status: SPAM 0.9742932 07a3b71c9c96968641bbfa497a458d8e :0 fw * ! JA_UBE_SPAMPROBE_HEADER ?? ^^^^ | ${FORMAIL:-formail} \ -I "$JA_UBE_SPAMPROBE_HEADER: $jaubeSpamprobeScore" } } dummy = "pm-jaube-prg-spamprobe.rc: end: $ERROR" # End of file procmail-lib-2009.1202/lib/pm-jaube.rc000066400000000000000000001253251130547513300172110ustar00rootroot00000000000000# pm-jaube.rc -- Unsolicited Bulk Email (UBE) filter. # # {{{ Documentation # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Warning # # Put all your UBE (aka spam) filters towards the _end_ of your # ~/.procmailrc. The idea is that valid messages are filed # first (mailing lists, your work and private mail, bounces) and only # the uncategorized messages are checked. # # Are you sure you want to use procmail for UBE? # # If you think you can put this recipe as a first line of defence to # your mail, you will disappoint. Checking UBE with procmail's # rule based means does not work that way. The good messages # must be sorted first (like your mailing lists and your # important work or friend message) and only then what's left to # process can be scanned by static rule based tools, like this # procmail module. There are much more better tools that are # based on statistical analysis of messages. You really should # consider using one or combination of Bayesian tools: # *Spamassassin*, *bogofilter*, *spamprobe*, *Bayesian* *Mail* # *Filter*, *ifile* etc. # # _Repeat:_ procmail rules are not the tool to UBE control. The # pattern matching rules can never keep up with the spammers. That # said, if you: # # o Can bare a 70-80 % UBE detection rate. # o Can bare 10 % false hits; you need to check you UBE folder # regularly for messaged that did not belong there. # o Have an account that does not get large number of UBE messages. # o Or if procmail is all you have in the system. # # only then consider this module or any other procmail based # spam filters in that respect. So, please don't set your # expectations high. Spend good time with the configuration # variables and check there returned result in variable `ERROR' # carefully. Good luck. # # Overview of features # # o Requires procmail 3.11pre7+ # o You don't need external files: site block lists, the # heuristics nail most of the UBE messages. Just plug in this # module and you have UBE shield active. # o Header based filtering: Minimum headers, Pegasus bulk mail, # X-uidl validity check, bogus From-To combination, # o Address based filtering: Numeric address, Invalid address (eg. # me@myMarketing.global), UBE-like(friend,remove request.) # o Text filtering: no html accepted, common advertising slogans, # unnecessary many capitalized words, HTML message body detection, # o And many more check that just not were listed here. # # Remember: this is not 100% and there will always be some mishits, so # don't just junk messages to `/dev/null'. # # Description # # Originally Daniel Smith posted his spam.rc, where he had gathered # many tips and heuristics to filter UBE email. This filter here # expresses work of many procmail users. Original filters were # modified, some rules were left out that catched false email # messages and made the package look a bit more general so that it # could be included via `INCLUDERC' in the standard way. # # Thanks to Daniel and others, the UBE bomb days can be reduced, # when this filter is active. Some UBE messages may still lurk # into the mailbox, but that's the problem with all static rule # based tools. # # Logging the events # # A good strategy to follow incoming mail is to log the vital parts # like Date, From, Subect to some log file and then a reason what # happened to a message. The `~/Mail/mail.log' might look like: # # 1997-12-08 work@example.com Extra Holiday $$$$$ # [jaube; Marketing-Big-ExitCode; LEGAL, MONEY-MAKING PHENOMENON] # 1997-12-09 Denizen [RePol] hiding # 1997-12-09 david X Re: Send list to incoming folder # 1997-12-09 david X Re: Send list to incoming folder # 1997-12-09 OMC manager "Environments updated" # [my; work-localenv] # 1997-12-09 doodle@example.org Re: Gnus (Emacs Newsreader) FAQ # [my; emacs; Re: Gnus (Emacs Newsreader) FAQ ] # # First a UBE message that was identified and saved # to folder. Next 3 messages were filed to mailing-list folders and # there was no [] action displayed for them (left out due to high # volume of these messages). Second Last was internal work # message. Lastly someone asked somthign about Emacs. # # The basic incoming message log recipe could be like this. # Variable `TODAY' is `$YYYY-$MM-$DD' whose values are set after # calling `pm-jadate.rc'. The `LISTS' is user set variable to exclude # mailing lists whose activity is not important. Variables `FROM' and # `SUBJECT' are fields read the message's headers. # # BIFF = $HOME/Mail/mail.log # INCLUDERC = $PMSRC/pm-jadate.rc # ... # # :0 hwic: # *$ ! $LISTS # |echo "$TODAY $FROM $FSUBJECT" >> $BIFF # # Here is small perl script to print summary of trapped UBE # messages from a log like above. It gives nice overview which recipes # catch most of the UBE messages. # # perl -ne '/jaube; (\S+)/; $s{$1}++; \ # END { $s = (map{$x += $_; $_= $x} values %s)[-1]; \ # $i = int $s{$_}/$s *100; \ # for (keys %s) { printf "$s{$_} $i $_\n" } \ # }' \ # mail.log | \ # sort -nr # # Here is sample results during two month period There are total of # 3248 UBE messages catched. # # count % type # ------------------------------------------ # 554 17 Marketing-CountBigLetterWords # 457 14 Marketing # 422 12 Marketing-SelectedBigLetterWords # 349 10 AddrBogus-ToFrom # 263 8 FromReceived-Mismatch # 223 6 NoDirectAddress-ToCc # 216 6 HdrForgedPegasus # 164 5 AddrBogus-To # 151 4 MessageId # 102 3 BodyHtml # 73 2 Received-IPError # 63 1 Identical-FromTo # 53 1 AddrInvalid # 15 0 From-nslookup # 9 0 HdrReceivedTime # 7 0 HdrX-UIDL # 4 0 Marketing-headers # # About bouncing message back # # The general consensus is, that you should not send bounces. The UBE # sender is not there, because the address is usually forged. Do not # increase the network traffic. Instead save the messages to folders # and periodically check their contents. It's not nice to be forced to # apologize if you bounced message to a wrong destination. DON'T # BOUNCE. Forget all recipe examples that use HOST and EXITCODE and # be a good Net citizen. # # Required settings # # PMSRC must point to source directory of procmail code. This # recipe file will include # # o pm-javar.rc # o pm-janslookup.rc # o pm-jaaddr.rc # # Call arguments (variables to set before calling) # # Only handful of the most important variables are described here. # You really should read all the comments placed in the "user configured # section" in this procmail module's code. Most of the defaults # should work out of the box. # # o `JA_UBE_VALID_ADDR', your email addresses or other # valid from addresses that will say "this is mail addressed # directly to you". # o `JA_UBE_HDR', If non-empty, a new header is added which tells which # recipe was triggered. The header is not added to message, if # there is nothing to report; i.e. message passed all tests. # o Various flags: Some of the ube detecting recipes give more # false hits than nail real ube. Experiment with yourself and turn # on or off the recipes that work for the kind of ube messages # you receive. # o `JA_UBE_MAX_BIG_WORDS', the maximum count of big letter words in the # message that is tolerated. The current count 5 is rather # conservative and it is suggested you to increase it to prevent # trapping too many false hits. Alternatively update JA_UBE_CAPS_OK # to include accepted words. # o `JA_UBE_APPARENTLY_TO_MAX', how many Apparently-To headers are # tolerated. Default is 3. # o `JA_UBE_MAX_HTML_TAGS', maximum count of html tags allowed in the # body. # o `JA_UBE_ATTACHMENT_ILLEGAL_KILL', if set to "yes" (default), then # illegal attachment from body is ripped off. This is brute way # to truncate the message abruptly to save mailbox space. You still # see the headers for tracking, but the body is gone. The regexp # to test is set in `JA_UBE_ATTACHMENT_ILLEGAL_REGEXP'. # o `JA_UBE_ATTACHMENT_SUSPECT_KILL', if set to "yes" (default "no"), # kill suspectible characters in attachement filename. The regexp # to test is set in `JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP'. # o JA_UBE_CHARSET_LEGAL, if set, accept only these character. The # default value detect messages with 7bit only (english speaking. # For foreign language you may want to set this something like # `$CHAR_7BIT_SET$CHAR_LIST_FINLAD' # for Finnish. See `pm-javar.rc' for available character sets. # # Return values # # o `ERROR_STATUS', status word of checks. Value "Good" or "Bad" # o `ERROR,' is set to short ube trigger recipe reason # o `ERROR_MATCH', is set to some MATCH that happened while triggering # UBE message. # # Alternatively you check content of header `JA_UBE_HDR' which contains # results of the above variables. Possible values for `ERROR' are: # # AddrAOLinvalid # AddrBogus-From # AddrInvalid-From # AddrInvalid-To # AddrNumeric # AddrNumericDomain # AddrUbeLike # BodyAttachment-FileIllegalAdditional # BodyAttachment-FileIllegalMatch # BodyAttachment-FileIllegalOther # BodyAttachment-FileSuspect # BodyCharacters-Illegal # BodyHtml-NonMime # BodyHtml-script # BodyHtmlBase64 # BodyHtmlImage # BodyHtmlTags # BodyMimeCharset-Illegal # EnvelopeFrom-Invalid # From-nslookup # FromReceived-Mismatch # HdrForgedPegasus # HdrReceived # HdrReceivedTime # HdrX-Distribution # HdrX-UIDL # Header-ApparentlyTo # HeaderCharacters-Illegal # HeaderMimeCharset-Illegal # Html-base64 # Identical-FromTo # Marketing-Body # Marketing-CountBigLetterWords # Marketing-SelectedBigLetterWords # Marketing-Subject # Marketing-SubjectGreeting # MegaSpammer # MessageId-Invalid # MessageId-Empty # NoDirectAddress-ToCc # NotEnoughHeaders # Received-IPError # VirusBody # VirusHeader # # Usage example # # # - All legimate messages should already been handled and # saved before this recipe. # # - Activate the filter only for messages that are not from # # daemon and not from valid senders: like from "my" domain # # and mailing lists and from somewhere else. # # VALID_FROM = "(my@address.example.com|word@here.example.com)" # # :0 # *$ ! ^From:.*$VALID_FROM # *$ ! FROM_DAEMON # { # # # Do not add extra headers. This saves external shell call # # (formail). Also do not try to kill the message content, # # again saving one external call (awk). With these, the # # recipe is faster and more CPU friendly. # # PM_JA_UBE_HDR = "" # JA_UBE_ATTACHMENT_ILLEGAL_KILL = "no" # # INCLUDERC = $PMSRC/pm-jaube.rc # # # Variable "ERROR" is set if message was UBE, record error # # to log file with "()\/" # # :0 : # * ERROR ?? ()\/[a-z].* # { # # Don't save those *.exe, *.zip UBE attachements # :0 # * ERROR ?? attacment.*file # /dev/null # # :0 : # spam.mbox # } # } # # There may be UBE messages that fool `FROM_DAEMON' test, so # you could also use something more finer check. The standard daemon # error message almost always has sentence "Transcript of session # follows" in the body. This recipe says: "Unless proven otherwise, # I don't believe this is daemon message even if it looked like that". # Add More "2^1" checks to raise score for other valid daemon cases. # # * -1^0 ^FROM_DAEMON # * ! 2^1 B ?? Transcript of session follows # { # # ... Now call UBE checker # } # # File layout # # The layout of this file is managed by Emacs packages tinyprocmal.el # and tinytab.el for the 4 tab text placement. # See project http://freshmeat.net/projects/emacs-tiny-tools/ # # Change Log # # 2004-09-10 Restructural changes and many improvements with added # checks. This module no longer saves messages - it only checks if # message is UBE or not. # # 1998-08-24 Gregory Sutter sent update to his recipe. # # 1998-02-27 (Henryk Bochmann) # reported that the ReceivedFrom test triggered all htmail messages. # Now Fixed. # # }}} # {{{ Variables # ............................................................ &init ... dummy = " ======================================================================== pm-jaube.rc: init:" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc :0 # This is extremely critical, so flag error * ! WSPC ?? [ ] { LOG = "(pm-jaube.rc) *** FATAL ERROR: couldn't include pm-javar.rc" } } ####################################################################### # # User configurable variables. Set these, before calling this # module/subroutine. # ####################################################################### # ............................................... &enabling-features ... # Recipe enable flags. Turn off if you think they # give too many false hits. Set to 'yes' or 'no' JA_UBE_FLAG_IP = ${JA_UBE_FLAG_IP:-"yes"} JA_UBE_FLAG_MID = ${JA_UBE_FLAG_MID:-"yes"} JA_UBE_FLAG_NUM_ADDR = ${JA_UBE_FLAG_NUM_ADDR:-"yes"} JA_UBE_FLAG_TEXT_MARKET = ${JA_UBE_FLAG_TEXT_MARKET:-"yes"} JA_UBE_FLAG_TEXT_VIRUS = ${JA_UBE_FLAG_TEXT_VIRUS:-"yes"} JA_UBE_FLAG_IDENTICAL_FROM_TO = ${JA_UBE_FLAG_IDENTICAL_FROM_TO:-"yes"} JA_UBE_FLAG_TO_CC = ${JA_UBE_FLAG_TO_CC:-"yes"} JA_UBE_FLAG_BIG_LETTER_WORDS = ${JA_UBE_FLAG_BIG_LETTER_WORDS:-"yes"} # Is there is an attachment (*.exe ...), setting this option to 'yes' # will brutally remove file attached in base64 data thus reducing the # size of the saved message considerably. Warning: the MIME headers # WILL BE INVALID after this brutal operation, so some Mail User # Agents (MUAs) may not be able to read the message properly. # # If you have plenty of disk space OR if you plan to send the # message to /dev/null after checking the ERROR variables for # indication of "attachment.*file", please turn this option "off". # Then no external awk process is called and your procmal # process is faster. JA_UBE_ATTACHMENT_ILLEGAL_KILL = $JA_UBE_ATTACHMENT_ILLEGAL_KILL:-"yes"} JA_UBE_ATTACHMENT_SUSPECT_KILL = $JA_UBE_ATTACHMENT_SUSPECT_KILL:-"no"} # Should the From: addresses domain be validated with nslookup? # Turning this option on may slow down UBE filter for first 200 # mails. After that the nslookup cache starts playing well. JA_UBE_FLAG_FROM_NSLOOKUP = ${JA_UBE_FLAG_FROM_NSLOOKUP:-"yes"} # ....................................................... &variables ... JA_UBE_HDR = ${JA_UBE_HDR:-"X-Spam-Jaube"} # No trailing colon! # Define this variable to match _all_ valid From and To addresses that # are yours. Put your regexp inside prenthesis. # # This defualts to "(logname|email@foo.com)" or "(logname|xyzabc)" # if EMAIL is not defined. JA_UBE_VALID_ADDR = ${JA_UBE_VALID_ADDR:-\ (${LOGNAME:-$USERNAME}|${EMAIL:-xyzabc})} # A Macro JA_UBE_FROM = ${JA_UBE_FROM:-\ "(^(Apparently-|Resent-)*(From|Reply-To|Sender):|^From$NSPC+)"} # If message comes from these address, check that From addresses domain # is found from Received header. If not, then it's forged. # # This regexps must not include @ character because the matched string # is used later "as is" and included @ will confuse the algorithm. # # 1998-10-05 Jacques Gauthier informed that # rocketmail was merged with lycosmail, but that rocketmail still exists. JA_UBE_FROM_QUESTIONABLE = ${JA_UBE_FROM_QUESTIONABLE:-"\ @.*(compuserve\ |aol\.\ |microsoft\ |yahoo |juno\.\ |netcom\ |earthlink\ |prodigy\ |freeyellow\ |hotmail\ |rocketmail\ |lycosmail\ |wowmail\ )"} # This list is _not_ meant to be comprehensive. Just some words that are # likely to be used in Computer related communication. # # ootb = out of the box oob = out of box # fyi = for your information # fwiw = # itp = intent to package # eof = end of file # esmtp = If message headers have been attached thre will be ESMTP Mail server # Received: lines # dst,cest = timezone values JA_UBE_CAPS_OK_DEFAULT = ${JA_UBE_CAPS_OK:-\ "\<(\ \\ |ASAP\ |API\ |BEGIN\ |BLOCK\ |\\ |CVS\ |CYGWIN\ |DHCP\ |\\ |\\ |\\ |\\ |EMACS\ |ENCRYPTED\ |\\ |E?SMTP\ |EXIT\ |\\ |FAQ\ |\\ |FWIW\ |GNOME\ |\\ |GPG\ |GPL\ |\\ |GIF\ |GSM\ |HOME\ |HP-?UX\ |HTTP\ |\\ |JPG\ |\\ |KDE\ |\\ |PATH\ |\\ |PCX\ |PGP\ |<\ORACLE\>\ |POSIX\ |PUBLIC\ |PXE\ |README\ |RSA\ |\\ |SSH\ |TEXT/PLAIN\ |\\ |\\ |US-ASCII\ |\\ |WWW\ |XEMACS\ )\>"} # Allowed words that are all caps. # If message contains too many capitalized words, it's certainly UBE. # # If you want caps checking, set # # JA_UBE_CAPS_OK = $JA_UBE_CAPS_OK_DEFAULT JA_UBE_CAPS_OK = "" # Disabled by default # If you'tr english speankin and to not want any messages that # contains exotic character, this default is fine. If you speak # some other language, you should define this variable to list # of characters allowed. It will be later converted into [ ... ] # class regexp. JA_UBE_CHARSET_LEGAL = ${JA_UBE_CHARSET_LEGAL:-\ "$CHAR_7BIT_SET$CHAR_7BIT_CONTROL"} # Check for header of body for these MIME content types JA_UBE_MIME_CHARSET_ILLEGAL = ${JA_UBE_MIME_CHARSET_ILLEGAL:-\ "\<(ks_\ |euc-kr\ |ISO-.*2022\ |big-?5\ |gb[0-9]\ |koi[0-9]\ |kr\>\ |cs\>\ |jis\>\ |jp\>\ |Windows-1251\ )"} # Any regexp than can match the full attachment file name. # *.scr is audio/x-wav JA_UBE_ATTACHMENT_ILLEGAL_REGEXP = ${JA_UBE_ATTACHMENT_ILLEGAL_REGEXP:-\ "\.(\ ba[st]\ |bin\ |chm\ |cmd\ |com\ |cpl\ |dll\ |exe\ |hta\ |inf\ |jar\ |ms[cit]\ |mp3\ |pcd\ |pif\ |ram\ |reg\ |sc[rt]\ |swf\ |vb[es]?\ |wav\ |ws[cfh]\ )"} # In addition to JA_UBE_ATTACHMENT_ILLEGAL_REGEXP, this regexp is tried. # So, if you want to retain the default (*.exe) checks, do not touch # JA_UBE_ATTACHMENT_ILLEGAL_REGEXP, but set # JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL # # You could include \.(bmp|jpe?g|gif|png) JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL = \ ${JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL:-""} # If this regexp matches the attachement filename, then it is # suspect. Some spammers send files named after the email address, # so this regexp catches those. An example: # # name="j.doe@example.net" # # Set this variable to an empty string "" to disable checking. JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP = \ ${JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP:-\ "[@&%!?#|;:<>{}\[\]\'$]"} # Subject field words to classify as "Greeting" JA_UBE_SUBJECT_GREETING = ${JA_UBE_SUBJECT_GREETING:-\ "\<(hi|hey|greeting|hello|help)\>"} # ...................................................... &thresholds ... JA_UBE_MAX_APPRENTLY_TO = ${JA_UBE_MAX_APPRENTLY_TO:-3} JA_UBE_MAX_BIG_WORDS = ${JA_UBE_MAX_BIG_WORDS:-5} JA_UBE_MAX_HTML_TAGS = ${JA_UBE_MAX_HTML_TAGS:-4} # ........................................................... &other ... # Define DEGUG = "yes" to get the headers into the LOGFILE :0 * DEBUG ?? on { LOG = "$NL$NL ######## head-begin $NL" HEADER = `sed /^$/q` LOG = "$NL ######## head-end $NL" } ####################################################################### # # Private variables. Do not touch # ####################################################################### jaubePGPmessage = "no" # set initial value for flag :0 * B ?? BEGIN PGP (SIGNED )?MESSAGE { jaubePGPmessage = "yes" } jaubeHTML = "no" # set initial value for flag :0 *$ HB ?? ^Content-Type:.*html { jaubeHTML = "yes" } # .......................................................... &output ... # The status of this message. Changed to "Bad" if ERROR is set here. ERROR_STATUS = "Good" # - Kill these variables. # - The UBE catch reason is stored into ERROR. # - If something was matched while detecting UBE, te second # will hold the match. ERROR ERROR_MATCH # }}} # ............................................................ &misc ... money1="[0-9]+([,.][0-9]+)*$WSPC+(dollars?|euros?)" money = "(\ \$[0-9]\ |[0-9]$WSPC*%\ |$money1 )" # {{{ Body: Attachments # ............................................................ &text ... dummy="pm-jaube.rc: Check attachements" # These are some clever attachement names like: # name="this.doc .pif" # name="this.doc # .pif" :0 * ERROR ?? ^^^^ * HB ?? Content-Type:.*(application|octet-stream|multipart|alternative) *$ B ?? name=\/.+$SPCL+[^\"']+ { jaubeFile = $MATCH # Remove leading quote mark :0 *$ jaubeFile ?? ^^[\"']+\/.+$SPCL+[^\"']+ { jaubeFile = $MATCH } :0 * ! JA_UBE_ATTACHMENT_ILLEGAL_REGEXP ?? ^^^^ *$ $SUPREME^0 jaubeFile ?? ()\/$JA_UBE_ATTACHMENT_ILLEGAL_REGEXP { ERROR = "BodyAttachment-FileIllegalMatch" ERROR_MATCH = "$jaubeFile ($MATCH)" } :0 * ! JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL ?? ^^^^ *$ $SUPREME^0 jaubeFile ?? ()\/$JA_UBE_ATTACHMENT_ILLEGAL_REGEXP_ADDITIONAL { ERROR = "BodyAttachment-FileIllegalAdditional" ERROR_MATCH = "$jaubeFile ($MATCH)" } } :0 * ERROR ?? ^^^^ * HB ?? Content-Type:\/.*(audio|video) { ERROR = "BodyAttachment-FileIllegalOther" ERROR_MATCH = "$MATCH" } :0 * ERROR ?? ^^^^ * ! JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP ?? ^^^^ * B ?? base64 * B ?? name=\/.* * MATCH ?? ()\/[^\"\' ]+ { jaubeFile = $MATCH :0 *$ jaubeFile ?? $JA_UBE_ATTACHMENT_SUSPECT_NAME_REGEXP { ERROR = "BodyAttachment-FileSuspect" ERROR_MATCH = "$jaubeFile" } } # }}} # {{{ Invalid IP and domains, or From_ :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_IP ?? yes *$ ^Received.*()\/\[[0-9\.]*([03-9]$d$d|2[6-9]$d|25[6-9]) { ERROR = "Received-IPError" ERROR_MATCH = $MATCH } # 1998-05-26 By (David W. Tamkin) in # procmail mailing list. Message-ID: # # Valid envelope From_ address looks like and anything different from # that is probably spam. # # From foo@bar.com Tue May 26 02:46:33 1998 :0 * ERROR ?? ^^^^ *$ ! ^From$WSPC+$NSPC+$WSCPC+.*$weekdays *$ From+s+\/.* { ERROR = "EnvelopeFrom-Invalid" ERROR_MATCH = $MATCH } # }}} # {{{ Invalid message id # By era eriksson # # Invalid Message-Id:s are likely UBE # Careful, this seems to give false hits sometimes(and one is enough!) # You may want to disable this permanently. # # There is software out there that breaks # RFC822 in that they don't include an "@" in the Message-Id. I don't # care too much since I see them in my spam tank but if you send stuff # to /dev/null, you'll probably want to take out the @ part. # # RFC822 says (4.1): # # msg-id = "<" addr-spec ">" # addr-spec = local-part "@" domain ; global address # local-part = word *("." word) # domain = sub-domain *("." sub-domain) # => # Message-Id: word *("." word) "@" sub-domain *("." sub-domain), # # where (3.3): # # word = atom / quoted-string # atom = 1*; efectively ascii 33-127. # # Example invalid: # Example valid : # # Below, it is required that domain is like "this.com", and not just "localhost". :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_MID ?? yes * ^Message-Id:\/.* *$ ! ^Message-Id:[$WSPC]+<[^$WSPC<>@]+@([a-zA-Z0-9-]+\.)+[a-zA-Z]+> { ERROR = "MessageId-Invalid" ERROR_MATCH = $MATCH } # Empty Message-ID should never be generated by a real mail program :0 * ERROR ?? ^^^^ *$ ^Message-Id:.*<$WSPC*> { ERROR = "MessageId-Empty" # ERROR_MATCH = $MATCH } # }}} # .......................................................... &header ... # {{{ Header: Required minimum :0 * ^From: * ^(Apparently-|Delivered-|Envelope-)?To: * ^Date: { } :0 E * ERROR ?? ^^^^ { ERROR = "NotEnoughHeaders" # ERROR_MATCH = $MATCH } # }}} # {{{ Header: X-distribution # Pegasus mail uses this :0 * ERROR ?? ^^^^ *$ ^X-Distribution:$WSPC*\/(moderate|bulk|mass) { ERROR = "HdrX-Distribution" ERROR_MATCH = $MATCH } # }}} # {{{ Header: Illegal character sets # This section is special. We always run the character test set, # No matter if the previous check would have found another # error (and ERROR is set) dummy = "pm-jaube.rc: Check illegal character sets" charset = $JA_UBE_MIME_CHARSET_ILLEGAL :0 * ! JA_UBE_CHARSET_LEGAL ?? ^^^^ { dummy = "Charset test: $JA_UBE_CHARSET_LEGAL" :0 *$ ^(Subject|From|To):.*()\/[^$JA_UBE_CHARSET_LEGAL] { ERROR = "${ERROR}${ERROR+:}HeaderCharacters-Illegal" ERROR_MATCH = $MATCH } :0 E *$ B ?? ()\/[^$JA_UBE_CHARSET_LEGAL] { ERROR = "${ERROR}${ERROR+:}BodyCharacters-Illegal" ERROR_MATCH = $MATCH } } :0 *$ $SUPREME^0 ^Content-Type:.*\/$charset[^ \"'<>]* *$ $SUPREME^0 ^Subject:.*=[?]\/$charset[^ '\"<>]* { ERROR = "${ERROR}${ERROR+:}HeaderMimeCharset-Illegal" ERROR_MATCH = "$MATCH" } :0 *$ B ?? charset=.*\/$charset[^ '\"<>]* { ERROR = "${ERROR}${ERROR+:}BodyMimeCharset-Illegal" ERROR_MATCH = "$MATCH" } # }}} # {{{ Header: Apparently-To # One typical UBE is where there is multiple apparently-to headers # # Apparently-To: # Apparently-To: # Apparently-To: # Apparently-To: # Apparently-To: :0 * ERROR ?? ^^^^ *$ -$JA_UBE_MAX_APPRENTLY_TO^0 * 1^1 ^Apparently-To: { ERROR = "Header-ApparentlyTo" ERROR_MATCH = "$= too many" } # }}} # {{{ Header: X-uidl # Headers that shouldn't exist in "real" mail # # Might need to be a little more particular here; # Philip Guenther : If a message comes into your # mailbox that has the X-UIDL: header, and doesn't have your address in # the header, then I would have strong doubts about it's legitimacy. # # Edward J. Sabol : E-mails with # X-UIDL: headers are almost definitely spam unless they've been # Resent-To: me by someone. Also, valid X-UIDL: headers have 32 hexadecimal # digits exactly. hex8 = "$h$h$h$h$h$h$h$h" :0 * ERROR ?? ^^^^ * ^X-UIDL: *$ ! ^X-UIDL:$WSPC*\/$hex8$hex8$hex8$hex8$WSPC*$ * ! ^Resent-To: { ERROR = "HdrX-UIDL" ERROR_MATCH = $MATCH } # }}} # {{{ Header: bogus Pegasus # 1998-08-24 Gregory kindly sent update to this filter. Thank you. # # Pegasus mailer is the only mailer which legitimately generates # "Comments: Authenticated sender is ..." so kill anything else. # --Gregory S. Sutter # # Pegasus mailer is the only mailer which legitimately generates # "Comments: Authenticated sender is ..." so kill anything else. # This works for Pegasus versions 2.54 and below only, 2.55 and # above don't generate the Authenticated Sender header. :0 * ERROR ?? ^^^^ * ^Comments:.*Authenticated sender * ! ^X-Mailer:.*Pegasus Mail * ! ^Resent-To: * ! ^Return-Path:.*owner- { ERROR = "HdrForgedPegasus" # ERROR_MATCH = $MATCH # what should be saved here? } # }}} # {{{ Header: Received # ........................................................ &received ... # Spamford's "Cyber-Bomber" generates "CLOAKED!" headers. # The following also catches bogus IP addresses :0 * ERROR ?? ^^^^ * ^Received: \/.*(CLOAKED|\[(0)+\.(0)+\.(0)+\.(0)+\]).* { ERROR = "HdrReceived $MATCH" ERROR_MATCH = $MATCH } # Stealth Mailer bogus timestamp :0 * ERROR ?? ^^^^ * ^Received: \/.*-0[67]00 \(E[SD]T\) { ERROR = "HdrReceivedTime" ERROR_MATCH = $MATCH } # by wwgrol@sparc01.fw.hac.com (W. Wesley Groleau x4923) # Check that suspicious From site is mentioned in the Received headers :0 * ERROR ?? ^^^^ *$ ! ^(From|To|Cc):.*$JA_UBE_VALID_ADDR * ^Received: *$ ^From:.*\/$JA_UBE_FROM_QUESTIONABLE *$ ! ^Received:.*\/$MATCH { ERROR = "FromReceived-Mismatch" ERROR_MATCH = $MATCH } # }}} # ......................................................... &Address ... # {{{ Address: Numeric :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_NUM_ADDR ?? yes *$ ^From:\/$WSPC*$d+@.* { ERROR = "AddrNumeric" ERROR_MATCH = $MATCH } # Bogus, all-numeric domain names: :0 * ERROR ?? ^^^^ * ^(From|To|Reply-To): \/.*@[0-9]+\..* { ERROR = "AddrNumericDomain" ERROR_MATCH = $MATCH } # }}} # {{{ Address: Invalid AOL # By John Gianni # # From Postmaster@aol.com: Valid AOL address can not: # # - be shorter than 3 or longer than 10 characters # - begin with numerals # - contain periods, underscores, dashes or other punctuation # # Valid AOL mail will have a short, verifiable Received path directly # from a resolvable host within AOL.COM to your mail host. Valid AOL # address are 10 characters or less and also has to begin with a # letter and not a number also. # # If AOL address starts with anything else but A-Z; then it must be bogus. :0 * ERROR ?? ^^^^ * ^From: \/.*@aol\.com * ! ^From: *([^a-z]|.+[^0-9a-z]|............).*@ { ERROR = "AddrAOLinvalid" ERROR_MATCH = $MATCH } # }}} # {{{ Address: Bogus :0 * ERROR ?? ^^^^ { # Originally by Daniel Smith word = "[a-z0-9][-a-z0-9_.+]*" word2 = "[-a-z0-9]" # See "Top Level Domains (gTLDs)" http://www.icann.org/tlds/ tld = "(\ aero\ |arpa\ |biz\ |com\ |coop\ |edu\ |gov\ |info\ |int\ |mil\ |museum\ |name\ |net\ |org\ |pro\ |[a-z][a-z]\ )" } :0 * ERROR ?? ^^^^ *$ ! ^From:\/.*$word@($word2+\.)+$tld { ERROR = "AddrBogus-From" ERROR_MATCH = $MATCH } :0 * ERROR ?? ^^^^ *$ ! $SUPREME^0 (To|Cc):.*$JA_UBE_VALID_ADDR *$ ! $SUPREME^0 (To|Cc):.*$word@($word2+\.)+$tld { :0 * (To|Cc):\/.* *$ MATCH ?? $NSPC.+$NSPC { } ERROR = "AddrInvalid-To" ERROR_MATCH = $MATCH } # If the From: line contains a @ but no . after it, it's suspect # By Era eriksson :0 * ERROR ?? ^^^^ * ^From:\/.*@[^ >]+>? *$ ! ^From:.*@[^.]+\. { ERROR = "AddrInvalid-From" ERROR_MATCH = $MATCH } # }}} # {{{ Address: UBE-like :0 * ERROR ?? ^^^^ *$ ()\/(${JA_UBE_FROM}|^TO)(remove|delete|\|friend@) { ERROR = "AddrUbeLike" ERROR_MATCH = $MATCH } # }}} # {{{ Header: From-To, To-Cc # By Era Eriksson, Sun, 08 Feb 1998 in procmail mailing list # The lone "To" is purely for logging purposes to record MATCH :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_IDENTICAL_FROM_TO ?? yes *$ ! ^(From|To|Cc):.*$JA_UBE_VALID_ADDR * ^To: \/.* * $ ^\/(From|Reply-To): $\MATCH { ERROR = "Identical-FromTo" ERROR_MATCH = $MATCH } # If the message is not directly addressed to ME, then It's suspect. # Be sure to handle mailing lists before you call this file !! :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_TO_CC ?? yes * ! FROM_DAEMON * ^(To|Cc):\/.* *$ ! ^(To|Cc):.*$JA_UBE_VALID_ADDR { ERROR = "NoDirectAddress-ToCc" ERROR_MATCH = $MATCH } # }}} # {{{ Text: Marketing slogans # ....................................................... &marketing ... # Notice that the MATCH is set to text line that triggered the UBE dummy = "pm-jaube.rc: Marketing-CaseSensitive" # Case sensitive tests :0 D * ERROR ?? ^^^^ * JA_UBE_FLAG_TEXT_MARKET ?? yes * HB ?? ()\/\<(\ GUARANTEED|OFFER|BONUS|CREDIT\ |LEGAL(LY)?|SECRET|\\ |NO RISK|MAKE.*MONEY\ |MILLION|THOUSEND\ ).* { ERROR = "Marketing-SelectedBigLetterWords" ERROR_MATCH = $MATCH } dummy = "pm-jaube.rc: Marketing-Headers" # If there is a dollar in header(subject), this is ube. :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_TEXT_MARKET ?? yes *$ ^Subject:.*()\/(\$[0-9]|[0-9]$WSPC*%|\|!!+) * ! SUBJECT ?? Returned mail { ERROR = "Marketing-Subject" ERROR_MATCH = $MATCH } dummy = "pm-jaube.rc: Simple headers, dollar body" :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_TEXT_MARKET ?? yes *$ ^Subject:$WSPC*((fwd|re):)*$WSPC*$JA_UBE_SUBJECT_GREETING *$ ^Subject:()\/.* *$ B ?? $money { ERROR = "Marketing-SubjectGreeting" ERROR_MATCH = $MATCH } dummy = "pm-jaube.rc: Marketing body" # "Earn" must not match "learn" # Some marketing people try to be clever, they send # # for just $19.95, for incredible $19.95, for the sum 19.195 # for 19.95 # # So we match anything that has "for" and NN+.N+. There must not be # dollar in from, because the marketing could also use English pounds # or some other currency. # # \.*\<[0-9][0-9.]*\> :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_TEXT_MARKET ?? yes *$ B ?? ()\/\ \<(naked|women|girls|nude)\>\ |\<(babe|chick|blonde|brunette|cash|sex|hardcore|viagra)\>\ |\<(promote|earn|porn|drug\ |make.*money\ |Money making\ |Make \$[0-9]\ |(Low|fair|these) +price\ |price.*\.*$[0-9][0-9.]\ |This offer\ |FREE.*(offer|bonus|sample)\ |as low as.*$[0-9]\ |$money1\ |send \$.* to\ |save up.*to.*%\ |save as much as.*[$%]\ |sav(e|ing).*money\ |Delete if not interested\ |wish to be (excluded|removed)\ |to our remove list\ |Remov(al|e) instruction\ |to be removed from.*list\ |to reply to remov\ |you were.*selected\ |life style\ |phone card\ |long distance\ |Life Insurance\ |forgive the intrusion\ |Your.*(bonus|marker)\ |(visit|Welcome).*our.*Web ?site\ |(CALL|visit).*\<(us|today)\>\ |webcam\ |Response +needed\ )$S*$WSPC*$S* *$ MATCH ?? $NSPC { ERROR = "Marketing-Body" ERROR_MATCH = $MATCH } dummy = "pm-jaube.rc: Virus message" :0 * ERROR ?? ^^^^ { regexpBody = "\ Attenzione Virus\ |Returned due to virus\ |[]{<(]virus[]})>]\ |InterScan NT Alert\ |Message quarantined\ |Filter incident\ |Symantec AVF detected\ |banned filename .*in mail from you\ |File blocked - ScanMail for Lotus\ |MDaemon Notification -- Attachment Removed\ |SAV detected a violation in a document\ |MailMarshal has detected a suspect attachment\ |Security Alert - ScanMail for Lotus Notes\ |Skynet Mail Protection scan results\ |Vexira ALERT\ |You sent potentially unsafe content\ " # These are too general to appear in Body. regexpHeader = "\ virus(es|ii)?.*\<(alert|warn|detect|remov|found|infect|notif|scan|mail)\ |\<(alert|warn|detect|remov|found|infect|notif|scan|mail|sen[dt]).*virus\ |\<(contained).*virus\ |\\ |virus.*(gefunden|encontrado|enviado|correo)\ |$regexpBody\ " } :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_TEXT_VIRUS ?? yes *$ ()\/($regexpHeader)$S*$WSPC*$S* { ERROR = "VirusHeader" ERROR_MATCH = $MATCH } :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_TEXT_VIRUS ?? yes *$ B ?? ()\/($regexpBody)$S*$WSPC*$S* { ERROR = "VirusBody" ERROR_MATCH = $MATCH } # }}} # {{{ score: big letters # Count full words whose all letters have been capitalized # - If must not be uuencoded message, # - Ignore some commond words like: IP AM SMTP # - Word must have at least 3 big letters dummy = "pm-jaube.rc: CHECK BigLetterWords" :0 D * ERROR ?? ^^^^ * jaubeHTML ?? no * jaubePGPmessage ?? no *$ ! JA_UBE_CAPS_OK ?? ^^^^ *$ -$JA_UBE_MAX_BIG_WORDS^0 *$ B ?? -1^1 ()$JA_UBE_CAPS_OK * B ?? 1^1 ()\/\<[A-Z][A-Z][A-Z]+\> { ERROR = "Marketing-CountBigLetterWords" ERROR_MATCH = "$= too many" } # }}} # {{{ text: html # Raw HTML, but missing MIME definition headers. # Or you could match B ?? ()<(body[^<>]*|html)> :0 * ERROR ?? ^^^^ *$ B ?? ^^$SPCL* * ! H ?? ^(Mime-Version\\|Content-Type): { ERROR = "BodyHtml-NonMime" ERROR_MATCH = $MATCH } :0 * ERROR ?? ^^^^ * HB ?? ^Content-Type:.*/html * HB ?? ^Content-Transfer-Encoding:.*base64 * HB ?? ^\/Subject:.* { ERROR = "Html-base64" } # The Javascript, VBscript :0 * ERROR ?? ^^^^ * B ?? () * B ?? ()\/<$SPC*script$SPC*(lang.+)?> * B ?? { ERROR = "BodyHtml-script" ERROR_MATCH = $MATCH } :0 * ERROR ?? ^^^^ *$ -$JA_UBE_MAX_HTML_TAGS^0 * B ?? 1^1 ()\/ { ERROR = "BodyHtmlTags" ERROR_MATCH = "$= too many" } :0 * ERROR ?? ^^^^ * B ?? ^Content-Type:.*text/html * B ?? ^Content-Transfer-Encoding:.*base64 { ERROR = "BodyHtmlBase64" # ERROR_MATCH = $MATCH } :0 * ERROR ?? ^^^^ *$ B ?? () # * -1^1 ^Subject:(.*\<)?cyberpromo.com\> # # While less "perfect", I can never remember the scoring rules, and I'd # likely use something like the following; plus, it's probably faster: # This catches "cyberpromo.com" in any header not starting with "S", and # it happens that none of the ones we need to catch it in start with "S", # so it probably works the same on "real-life" mail headers. The # condition can be modified to check for headers not starting with "Su" # by changing it to: # # * ^([^S]|S[^u]).*\ # # if needed; further extensions should be obvious.) :0 * ERROR ?? ^^^^ * ^[^S].*\/\ { ERROR = "MegaSpammer" ERROR_MATCH = $MATCH } # }}} # {{{ nslookup dummy = "pm-jaube.rc: Check nslooup" # Check if From address has valid domain. We can't check address, but this # is closest we get. This check must be at the end so that faster "text" # test are applied first. :0 * ERROR ?? ^^^^ * JA_UBE_FLAG_FROM_NSLOOKUP ?? yes * ^From:\/.* { INPUT = $MATCH INCLUDERC = $PMSRC/pm-jaaddr.rc # explode address string ERROR :0 *$ SITE ?? $a { INPUT = $SITE INCLUDERC = $PMSRC/pm-janslookup.rc :0 * ERROR ?? yes { ERROR_MATCH = "From $SITE nslookup fail/$ERROR_MATCH" ERROR = "From-nslookup" } :0 E { ERROR # Clear variable } } } # }}} # ..................................................... &final-check ... :0 * ! ERROR ?? ^^^^ { ERROR_STATUS = "Bad" :0 * ! JA_UBE_HDR ?? ^^^^ { jaubeHeader = "$JA_UBE_HDR: $ERROR_STATUS $ERROR $ERROR_MATCH" # Check if ERROR_MATCH is not set (empty) :0 * ERROR_MATCH ?? ^^^^ { jaubeHeader = "$JA_UBE_HDR: $ERROR_STATUS $ERROR" } :0 fhw | ${FORMAIL:-"formail"} -I "$jaubeHeader" } # If AWK fails, then we see "Rescue of unfiltered data succeeded" # This might be due to message being too big :0 fbiw * ERROR ?? Attachment.*FileSuspect * JA_UBE_ATTACHMENT_SUSPECT_KILL ?? yes * B ?? base64 | $AWK '/[bB]ase64|BASE64/ { exit } { print }' :0 E fbiw * ERROR ?? Attachment.*FileIllegal * JA_UBE_ATTACHMENT_ILLEGAL_KILL ?? yes * B ?? base64 | $AWK '/[bB]ase64|BASE64/ { exit } { print }' } dummy = "pm-jaube.rc: end: $ERROR" # pm-jaube.rc ends here procmail-lib-2009.1202/lib/pm-jaube1.rc000066400000000000000000000032071130547513300172640ustar00rootroot00000000000000# pm-jaube1.rc -- Jari's UBE filter. Subroutine 1 # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Documentation # # This file is part of the "pm-jaube.rc". This subroutine is called # when likely UBE message has been triggered. # # Required settings # # PMSRC must point to source directory of procmail code. This recipe file # will include # # o pm-jastore.rc # # Change Log (none) # ............................................................ &code ... # id = "pm-jaube1.rc" dummy = " ======================================================================== $id: init: " # Should we write log message to file which identifies this UBE :0 hic: $JA_UBE_LOG$LOCKEXT * JA_UBE_LOG ?? [a-z] |echo " [jaube; $ERROR; $ERROR_MATCH]" >> $JA_UBE_LOG # Add new header to the message :0 fhw * JA_UBE_HDR ?? [a-z] | $FORMAIL -A "$JA_UBE_HDR: $ERROR, $ERROR_MATCH" # Should it be stored directly? :0 * JA_UBE_MBOX ?? [a-z] { MBOX = $JA_UBE_MBOX INCLUDERC = $RC_STORE } dummy = "$id: end:" # pm-jaube1.rc ends here procmail-lib-2009.1202/lib/pm-javac.rc000066400000000000000000000107121130547513300172000ustar00rootroot00000000000000# pm-javac.rc -- Procmail: Vacation framework recipe (id-cache) # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # Framework for all programs that need to reply to messages only once. # Usually known as "vacation" feature. If you cahnge th cache file, # you can attach this recipe to any messages that you want to deal with # only once. # # Required settings # # PMSRC must point to source directory of procmail code. This subroutine # will include # # o pm-javar.rc # # Call arguments (variables to set before calling) # # o JA_VAC, To activate vacation, set value to "yes" # o JA_VAC_RC, When new message-id is found, run this includerc # o JA_VAC_ID_CACHE, Remember to clear this file when you start # the vacation. # # Usage example # # To turn on the vacation feature, create ~/.vac file and recipe below # activates vacation. If the vacation is not active, then cache file # is removed. (automatic cleanup). The VERBOSE is also turned off # when you're on vacation; so that your procmail log will not get # filled. # # So when you go to vacation, you 'touch ~/.vac' and update # ~/vacation.msg. When you come back, you 'rm ~/.vac'. That's it. # # IMPORTANT: If you are subscribed to mailing lists, be sure to file # messages from those services first and put the vacation recipe # only after the list or bot messages. Also add sufficent "!" conditions # in order not to reply to other "bot" service messages. # # JA_VAC_ID_CACHE = $HOME/.pm-vac.cache # # :0 # *$ ? $IS_EXIST $HOME/.vac # { # VERBOSE = off # JA_VAC = "yes" # JA_VAC_RC = $PMSRC/pm-myvac.rc # my vacation recipe # INCLUDERC = $PMSRC/pm-javac.rc # framework # } # :0 E # else # * ? $IS_EXIST $JA_VAC_ID_CACHE # { # dummy = `$RM -f $JA_VAC_ID_CACHE` # } # # Here is example of pm-myvac.rc recipe # # # Change subject # # :0 fhw # * ^Subject: *\/[^ ].* # | $FORMAIL -I "Subject: vacation (was: $MATCH)" # # :0 fb # put message to body # | $CAT $HOME/.vacation.msg # # :0 # Send it # | $SENDMAIL # # Change Log (none) dummy = " ======================================================================== pm-javac.rc: init:" :0 * ! WSPC ?? [ ] { INCLUDERC = $PMSRC/pm-javar.rc } # .......................................................... &public ... JA_VAC = ${JA_VAC:-"no"} JA_VAC_RC = ${JA_VAC_RC:-""} JA_VAC_XLOOP = ${JA_VAC_XLOOP:-"$LOGNAME@$HOST X-loop"} JA_VAC_ID_CACHE = ${JA_VAC_ID_CACHE:-"$HOME/pm-vac.cache"} JA_VAC_ID_CACHE_SIZE = ${JA_VAC_ID_CACHE_SIZE:-8192} # ........................................................... &do-it ... # - The `! precedence' match should prevent from replying to "bot" # messages # - Mailing lists should use type "list" :0 * JA_VAC ?? yes *$ ! $JA:FROM_DAEMON *$ ! ^X-Loop: $JA_VAC_XLOOP * ! ^Precedence:.*(bulk|list|junk) * JA_VAC_RC ?? [a-z] { dummy = "pm-javac.rc: checking." oldLock = $LOCKFILE LOCKFILE = ${JA_VAC_ID_CACHE}${LOCKEXT} :0 c * ! ? $FORMAIL -rD $JA_VAC_ID_CACHE_SIZE $JA_VAC_ID_CACHE { # Compose reply and add some basic headers :0 fhw | $FORMAIL -rt \ -A "Precedence: junk" \ -A "X-Loop: $JA_VAC_XLOOP" :0 a # Formail succeeded { # New user, call this rc to send a reply INCLUDERC = $JA_VAC_RC } } LOCKFILE = $oldLock } dummy = "pm-javac.rc: end:" # End of file procmail-lib-2009.1202/lib/pm-javar.rc000066400000000000000000000451331130547513300172240ustar00rootroot00000000000000# pm-javar.rc -- Global variable definitions # # File id # # Copyright (C) 1997-2010 Jari Aalto # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # . # # Description # # This file defines common variables that you can use in the recipe's # condition line. Procmail does not know about escape sequences # like `\t' or `\n' and it is therefore much more readable to use # variables as substitute for common regular expression # atoms. Pay attention that the line starts with "*$ ", where # "$" expands the variables: In this file, the variable names # represent the well known Perl regular expression names, so # that $s is alost like Perl expression \s (whitespace) and $S # is almost equivalent to `\S' (non-whitespace). Similarly, $d is # `\d' (digit) and $D resembled `\D' (non-digit). # # :0 # *$ $s+something+$s+$d+$a+ # # The equivalent without variables (you don't see the tabs and # spaces here): # # :0 # # Space + tab # * [ ]something[ ][0-9]+[a-z]+ # # # In addition all system dependent variables are defined in this module. # For example if you have Gnu awk, it is strongly suggest that you set: # # AWK = "/path/to/gawk" # in Linux, this would be /usr/bin/awk # # You can define these variables before or after the module, just make # sure the binaries reflect your operating system's paths. In general, # if you "port" your setup to several system, dont' include absolute # paths. In the other hand, if your setup is in the same place using # absolute paths will speed up executions by a factor of 3 or more. # (depending on how long your PATH is) # # Standard variables defined # # See pm-tips.txt file for full explanation or look at the source code. # # SPC WSPC NSPC SPCL # Whitespace, Non Whitespace, W+linefeed # \s \d \D \w \W and \a \A # perl equivalents # # Special variable JA_FROM_DAEMON # # In order to boost procmail and to save extra CPU cycles, this module # defines variable `JA_FROM_DAEMON' that caches the information of # ^FROM_DAEMON. You can refer to `JA_FROM_DAEMON' as you would to # big brother FROM_DAEMON. This has the advantage that procmail # has already computed the result and the variable `JA_FROM_DAEMON' # is used as a cache, thus avoiding repeated FROM_DAEMON regexp # tests, which are expensive. Variable `JA_FROM_DAEMON_match' # contains "" or the result of matched daemon text. # # *$ $JA_FROM_DAEMON # # or the familiar # # *$ ! $JA_FROM_DAEMON # # Instead of using the regexp parsing with # # * ^FROM_DAEMON # # and # # * ! ^FROM_DAEMON # # Special variable JA_FROM_MAILER # # Works like `JA_FROM_DAEMON' variable but in respect to FROM_MAILER. # The matches text is in `JA_FROM_MAILER_MATCH' # # Usage example # # For your .procmailrc, you can simply put this, because you # want to load the variables at startup # # PMSRC = "/path/to/install/location/of/this/library" # INCLUDERC = $PMSRC/pm-javar.rc # # If you're developing your own modules that use these variables # put these lines at the beginning. `~/.procmailrc'. It checks # if WSPC variable does not include a space --> load the # variable definitions. If the variable is already defined, the # file is not loaded. The test line is something alike #ifdef -- # #endif in C/C++ language or a conditional "import" command in # other languages. # # :0 # * ! WSPC ?? [ ] # { # INCLUDERC = $PMSRC/pm-javar.rc # } # # Defined modules # # After this file loads, you can refer to any module with $RC_JA_MODULE. # E.g. to call email spit module in your code you would use following. # See at the end of this file for all defined module names. # # INCLUDERC = $RC_JA_UBE # # Change Log (none) dummy = " ======================================================================== pm-javar.rc: init:" # pure newline, you could use is like: # LOG = "message $NL" NL = " " LF = $NL # synonym, linefeed CR = " " # Carriage return TAB = " " # \t character, you won't see it. WSPC = " $TAB" # whitespace in procmail: space + tab # These are the variables that you're likely to use in # condition lines. Notice that there is Perl styles `s' variable # for shorter name for most used SPC. SPC = "[$WSPC]" # Regexp space/tab NSPC = "[^$WSPC]" # Negation, non-whitespace # Whitespace with linefeed # Note that in regexps, the character class is faster that OR. # Refer to O'Reilly book "Mastering Regular Expressions" # # space + tab + dollar # # ( | |$) is slower than ([ ]|$) SPCL = "($SPC|$|$CR)" # space or tab; linefeed; Carriage return # ..................................................... &perl-styled ... # http://www.perl.com/ # Shorter variable names, mimic perl token names. n = "$NL" # Newline -- Perl \n t = "$TAB" # Tab -- Perl \t s = "$SPC" # whitespcae -- Almost like perl \s S = "$NSPC" # Non-Whitespace -- Almost like Perl \S d = "[0-9]" # digit -- Perl \d D = "[^0-9]" # Non-digit -- Perl \D w = "[0-9a-z_A-Z]" # word -- Perl \w W = "[^0-9a-z_A-Z]" # Non-word -- Perl \W # No perl equivalents for these, but handy anyway. a = "[a-zA-Z]" # alphabetic (7 bit) A = "[^a-zA-Z]" # Non-alphabetic h = "[0-9a-fA-F]" # Hex value H = "[^0-9a-fA-F]" # Non-Hex value # ............................................................ &misc ... SUPREME = "9876543210" # The highest score value. See pm-tips.txt OR = "$SUPREME" # Multiline OR-ing in score recipes NOR = "-$SUPREME" # For IP addresses OCTET = "([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" DOTQUAD = "$OCTET[.]$OCTET[.]$OCTET[.]$OCTET" # Getting month or month-number matches. See pm-jadate*rc modules # for examples. mm2nbr = "Jan01Feb02Mar03Apr04May05Jun06Jul07Aug08Sep09Oct10Nov11Dec12" nbr2mm = "01Jan02Feb03Mar04Apr05May06Jun07Jul08Aug09Sep10Oct11Nov12Dec" weekdays = "(Sun|Mon|Tue|Wed|Thu|Fri|Sat)" TMPDIR = ${TMPDIR:-"/tmp"} # ........................................................ &programs ... # Substitute these with absolute path names and binaries will run faster FORMAIL = ${FORMAIL:-"formail"} PROCMAIL = ${PROCMAIL:-"procmail"} # Don't ever leave out flags -oi and -t SENDMAIL_FLAGS = "-oi -t" SENDMAIL = ${SENDMAIL:-"sendmail $SENDMAIL_FLAGS"} # This _must_ be Perl 5.x version. Old version 4.0 is way too old # and obsolete for statements like BEGIN{} PERL = ${PERL:-"perl"} LS = ${LS:-"/bin/ls"} LS_BY_DATE = ${LS:-"/bin/ls -t"} TR = ${TR:-"/bin/tr"} RM = ${RM:-"/bin/rm"} MV = ${MV:-"/bin/mv"} CP = ${CP:-"/bin/cp"} CAT = ${CAT:-"/bin/cat"} SED = ${SED:-"/bin/sed"} AWK = ${AWK:-"awk"} RMDIR = ${RMDIR-"/bin/rmdir"} MKDIR = ${MKDIR-"/bin/mkdir"} TOUCH = ${TOUCH:-"touch"} CHMOD = ${CHMOD:-"chmod"} DATE = ${DATE:- "date"} # must accept POSIX % escapes as date(1) EGREP = ${EGREP:-"egrep"} FGREP = ${EGREP:-"fgrep"} GREP = ${EGREP:-"egrep"} # use "grep -E" if you have GNU version NSLOOKUP = ${NSLOOKUP:-"nslookup"} GZIP = ${GZIP:-"gzip"} BZIP = ${BZIP:-"bzip2"} # Name BZIP is shorter than pedantic BZIP2 # ............................................................ &test ... # The `test' command is not identical on every operating system, so they # must be put behind variables. E.g. On Irix the -e # option is not recognized so IS_EXIST must be changed to -r there. IS_READABLE = ${IS_READABLE:-"test -r"} IS_EXIST = ${IS_READABLE:-"test -e"} IS_EXECTABLEU = ${IS_READABLE:-"test -x"} IS_FILE = ${IS_READABLE:-"test -f"} IS_DIR = ${IS_READABLE:-"test -d"} IS_NOT_EMPTY = ${IS_READABLE:-"test -s"} # exist and not empty # ............................................................ &mime ... # Mime decode commands: Install package 'metamail' if the system # does not have program `mimencode'. # See and "mm2.7*" # Metamail's description: # # Collection of MIME handling utilities Metamail is an implementation of # MIME, the Multipurpose Internet Mail Extensions, a proposed standard # for multimedia mail on the Internet. Metamail implements MIME, and also # implements extensibility and configuration via the "mailcap" mechanism # described in an informational RFC that is a companion to the MIME # document. MIME_BIN = ${MIME_BIN:-"mimencode"} MIME_BIN_QP = ${MIME_BIN_QP:-"$MIME_BIN -u -q"} # decode Quoted printable MIME_BIN_64 = ${MIME_BIN_64:-"$MIME_BIN -u -b"} # decode base64 # encode commands with "E" at the end MIME_BIN_QP_E = ${MIME_BIN_QPE:-"$MIME_BIN -q"} MIME_BIN_64_E = ${MIME_BIN_64E:-"$MIME_BIN -b"} # ...................................................... &exit-codes ... # These should be pretty standard. See /usr/include/sysexits.h EX_OK = 0 # successful termination EX__BASE = 64 # base value for error messages EX_USAGE = 64 # command line usage error EX_DATAERR = 65 # data format error EX_NOINPUT = 66 # cannot open input EX_NOUSER = 67 # addressee unknown EX_NOHOST = 68 # host name unknown EX_UNAVAILABLE = 69 # service unavailable EX_SOFTWARE = 70 # internal software error EX_OSERR = 71 # system error (e.g., can't fork) EX_OSFILE = 72 # critical OS file missing EX_CANTCREAT = 73 # can't create (user) output file EX_IOERR = 74 # input/output error EX_TEMPFAIL = 75 # temp failure; user is invited to retry EX_PROTOCOL = 76 # remote error in protocol EX_NOPERM = 77 # permission denied # ........................................................ &messages ... # Reserve string variables JA_MSG_ERROR = "ERROR: *** " # Message follows after this JA_MSG_ERROR_FATAL = "ERROR: FATAL: *** " # Message follows after this # ................................................... character sets ... # Define character sets grouped by language. # Contact: # 2004-04-16 included from http://www.professional.org/procmail/furrin.rc # See thread "furrin character sets" 2203-02-22 at # http://info.ccone.at/INFO/Mail-Archives/procmail/Feb-2003/threads.html#00521 # In emacs, you can generate any character: See key C-x 8 C-h # # There are entities: u umlaut (small/big), SZ ligature CHAR_LIST_GERMAN = "üÜß" # These are entities: a A ring, a A umlaut, o O umlaut CHAR_LIST_FINLAND = "åÅäÄöÖé" CHAR_LIST_SWEDEN = $CHAR_LIST_FINLAND # included entity: o slash CHAR_LIST_NORWAY = "$CHAR_LIST_FINNISHøØ" # included entity: ae AE ligature CHAR_LIST_DENMARK = "æÆ" CHAR_LIST_SCANDINAVIAN = "\ $CHAR_LIST_FINLAND\ $CHAR_LIST_NORWAY\ $CHAR_LIST_DENMARK\ " # You can make regular expressions like: # # unclean7bit = "[^$CHAR_7BIT_SET]" # # :0 : # * HB ?? unclean7bit # spam # Newline CHAR_7BIT_CONTROL = " " CHAR_7BIT_PUNCTUATION = "-+^~\"\'\`&/\\|*@%!?,.:;\(\){}<>\[\]\$#" CHAR_7BIT_SET = "$TAB !-~" # This is range: from SPC to TILDE. CHAR_7BIT_SCANDINAVIAN_SET = "$CHAR_7BIT_SET$CHAR_LIST_SCANDINAVIAN" CHARSET_JP = "WINDOWS-932|EUC-JP|(cs-?)?ISO-?2022-?JP(-[12])?|ISO-2022-D\ |SHIFT[-_]JIS|JIS[-_]?X[-_]?02(08|01|12|13)|sjis|jis7|ms-kanji\ |(x-)?mac(-)?japanese|x-EBCDIC-Japanese(Katakana|AndUSCanada\ |AndJapaneseLatin|AndKana)" CHARSET_CN = "WINDOWS-(936|950)|EUC-CN|(hz-|x-euc-tw)?GB[-_]?2312\ |(cn-)?(BIG5|gb)|ISO-2022-([EGHIJKLM]|cn|cn-ext)|ISO-IR-165\ |GB8565\.2(-1988)?|x-euc-tw|hz|iso-ir-58|gbk|big5-hkscs|gb18030\ |(x-)?mac(-)?chinese(trad|imp)|iso-ir-58\ |x-EBCDIC-(Traditional|Simplified)Chinese|x-Chinese-(CNS|eten)" # non-standards compliant variations of chinese CHARSET_CN_BOGUS = "CHINESEBIG5|BIG-5" CHARSET_KR = "WINDOWS-949|EUC-KR|KS[-_ ]?C[-_ ]?5601([-_ ]?1987)?\ |ISO-2022-(C|kr)|KS[-_]?X[-_]?1001|ksc5636|iso-646-kr|uhc\ |johab|(x-)?mac(-)?korean|iso-ir-149|x-EBCDIC-(KoreanAnd)?KoreanExtended" # some mailer actually sets this CHARSET_BOGUS = "X-UNKNOWN|USER-DEFINED" # Not recommended to block these - they're all rather encompassing CHARSET_UNICODE = "UTF(-)?(7|8|16)]|UCS(-)?(2|4)\ |UNICODE-1-1-UTF-7|ISO-10646-UCS-2|UNICODE-(16|32)(LITTLE|BIG)-ENDIAN)?\ |unicodeFFFE|JAVA|x-EBCDIC-International(-euro)?" # If you're english, you probably don't want to block this one either. CHARSET_ENG = "US-ASCII|ASCII|iso-ir-6|iso646-us|x-EBCDIC-(cp-us|UK)(-euro)?" # Western European (English, but also French and many others. Standard) CHARSET_WESTEURO = "WINDOWS-1252|ISO-?8859-(1|15)|iso-ir-100\ |(x-)?mac(-)?roman|latin-?(1|9)|macintosh|x-IA5(-German)?\ |x-ebcdic-(spain|italy|germany|france)(-euro)?|x-europa" # Central/Eastern European (non-english) CHARSET_SLAVIC = "WINDOWS-1250|ISO-?8859-(2|16)\ |iso-ir-(87|102)|(x-)?mac(-)?(central-europe|ce|croatian)\ |latin-?2|CP870" # uncommon stuff and/or generally obsoleted. Includes maltese (eh, sorry if # that's you) CHARSET_FUNKYLATIN = "ISO-?8859-[34]|iso-ir-109|latin-?3" # Russian, et-al. # KOI8-T is Tajiki (Tajikistan) # armscii-8 is Armenian CHARSET_CYRILLIC = "WINDOWS-1251|ISO-?8859-5|KOI8(-(RU|[RTU]))?\ |ISO-IR-(101|111|144|147)|IBM866\ |(x-)?mac(-)?(romanian?|cyrillic|ukran(e|ian))\ |nunacom-8|armscii-8|x-EBCDIC-Cyrillic(SerbianBulgarian|Russian)" # Arabic CHARSET_ARABIC = "WINDOWS-1256|ISO-?8859-6|iso-ir-127\ |(x-)?mac(-)?arabic|asmo-708|x-EBCDIC-Arabic" # Greek CHARSET_GREEK = "WINDOWS-1253|ISO-?8859-7|(x-)?mac(-)?greek\ |iso-ir-(126|150)|x-EBCDIC-Greek(Modern)?" # Hebrew CHARSET_HEBREW = "WINDOWS-1255|ISO-?8859-8(-i)?|(x-)?mac(-)?hebrew\ |iso-ir-138|x-EBCDIC-Hebrew" # Turkish CHARSET_TURKISH = "WINDOWS-1254|ISO-?8859-9|(x-)?mac(-)?turkish\ |iso-ir-(109|148)|latin-?5|x-EBCDIC-Turkish|CP1026" # Icelandic/Nordic (i.e. Iceland, Greenland, Norway, Sweden...) CHARSET_NORDIC = "ISO-?8859-10|(x-)?mac(-)?iceland(ic)?|iso-ir-60\ |x-IA5-(Norwegian|Swedish)\ |x-EBCDIC-(FinlandSweden|DenmarkNorway|Icelandic)(-euro)?" # Thai (ISO not _actually_ used, but draft standard is same) CHARSET_THAI = "WINDOWS-874|TIS[-_]?620|ISO-?8859-11\ |mulelao-1|ibm-cp1133|(x-)?mac(-)?thai|x-EBCDIC-Thai" # ISO-8859-12 is bogus (was suggested to be vietnamese, but can't fit). # However, I've seen this encoding specified in spam though, and lacking an # official designation, I'm hocking it here. CHARSET_VIETNAM = "WINDOWS-1258|ISO-?8859-12|viscii|tcvn5712|vps" # Baltic Rim CHARSET_BALTIC = "WINDOWS-1257|ISO-?8859-13|iso-ir-110" # Celtic (Irish and Welsh) CHARSET_CELTIC = "ISO-?8859-14" # Other stuff which escapes categorization at this time CHARSET_MISC = "isiri-3342|x-iscii-(as|be|de|gu|ka|ma|or|pa|ta|te)" # ..................................................... &from-daemon ... JA_FROM_DAEMON = "!" :0 * ^FROM_DAEMON { JA_FROM_DAEMON_MATCH = $MATCH JA_FROM_DAEMON = "!!" # double !! means "OK" # 2000-01-08 This has been copied from procmail log file # because we can't get the match otherwise. # Procmail version: v3.11pre4 1995/10/29 # # The following recipe is dummy: It solely sets MATCH to show # what procmail thinks triggered FROM_DAEMON # :0 # * ()\/^(Precedence:.*(junk|bulk|list)|To: Multiple recipients of |(((Resent-)?(From|Sender)|X-Envelope-From):|>?From )([^>]*[^(.%@a-z0-9])?(Post(ma?(st(e?r)?|n)|office)|(send)?Mail(er)?|daemon|mmdf|n?uucp|LIST(SERV|proc)|NETSERV|owner|r(e(quest|sponse)|oot)|b(ounce|bs\.smtp)|echo|mirror|s(erv(ices?|er)|mtp)|A(dmin(istrator)?|MMGR|utoanswer))(([^).!:a-z0-9][-_a-z0-9]*)?[%@> ][^<)]*(\(.*\).*)?)?$([^>]|$))) # { } } # ..................................................... &from_mailer ... JA_FROM_MAILER = "!" :0 * ^FROM_MAILER { JA_FROM_MAILER_MATCH = $MATCH JA_FROM_MAILER = "!!" # double !! means "OK" } # .................................................. &define-modules ... :0 * PMSRC ?? [a-z] { RC_ADDR = $PMSRC/pm-jaaddr.rc RC_BUP = $PMSRC/pm-jabup.rc RC_COOKIE = $PMSRC/pm-jacookie.rc RC_COOKIE1 = $PMSRC/pm-jacookie1.rc RC_CRON = $PMSRC/pm-jacron.rc RC_DAEMON = $PMSRC/pm-jadaemon.rc RC_DATE = $PMSRC/pm-jadate.rc RC_DATE1 = $PMSRC/pm-jadate1.rc RC_DATE2 = $PMSRC/pm-jadate2.rc RC_DATE3 = $PMSRC/pm-jadate3.rc RC_DATE4 = $PMSRC/pm-jadate4.rc RC_DATE5 = $PMSRC/pm-jadate5.rc RC_DUP = $PMSRC/pm-jadup.rc RC_EMPTY = $PMSRC/pm-jaempty.rc RC_FROM = $PMSRC/pm-jafrom.rc RC_FWD = $PMSRC/pm-jafwd.rc RC_LIST = $PMSRC/pm-jalist.rc RC_MIME_DECODE = $PMSRC/pm-jamime-decode.rc RC_MIME_KILL = $PMSRC/pm-jamime-kill.rc RC_MIME_SAVE = $PMSRC/pm-jamime-save.rc RC_MIME = $PMSRC/pm-jamime.rc RC_NETMIND = $PMSRC/pm-janetmind.rc RC_NSLOOKUP = $PMSRC/pm-janslookup.rc RC_ORIG = $PMSRC/pm-jaorig.rc RC_PING = $PMSRC/pm-japing.rc RC_POP3 = $PMSRC/pm-japop3.rc RC_RANDF = $PMSRC/pm-jarandf.rc RC_SRV_CHECK = $PMSRC/pm-jasrv-check.rc RC_SRV_DAEMON = $PMSRC/pm-jasrv-daemon.rc RC_SRV_ERR = $PMSRC/pm-jasrv-err.rc RC_SRV_FROM = $PMSRC/pm-jasrv-from.rc RC_SRV_MSG = $PMSRC/pm-jasrv-msg.rc RC_SRV_MULTI = $PMSRC/pm-jasrv-multi.rc RC_SRV_REQ = $PMSRC/pm-jasrv-req.rc RC_SRV_SEND = $PMSRC/pm-jasrv-send.rc RC_SRV = $PMSRC/pm-jasrv.rc RC_STORE = $PMSRC/pm-jastore.rc RC_SUBJECT = $PMSRC/pm-jasubject.rc RC_TIME = $PMSRC/pm-jatime.rc RC_UBE = $PMSRC/pm-jaube.rc RC_UBE1 = $PMSRC/pm-jaube1.rc RC_UBE_BMF = $PMSRC/pm-jaube-prg-bmf.rc RC_UBE_BOGOFILTER = $PMSRC/pm-jaube-prg-bogofilter.rc RC_UBE_IFILE = $PMSRC/pm-jaube-prg-ifile.rc RC_UBE_SPAMASSASSIN = $PMSRC/pm-jaube-prg-spamassassin.rc RC_UBE_SPAMPROBE = $PMSRC/pm-jaube-prg-spamprobe.rc RC_UBE_SPAMORACLE = $PMSRC/pm-jaube-prg-spamoracle.rc RC_UBE_ANNOYANCE = $PMSRC/pm-jaube-prg-annoyance-filter.rc RC_UBE_BSFILTER = $PMSRC/pm-jaube-prg-bsfilter.rc RC_UBE_RUNALL = $PMSRC/pm-jaube-prg-runall.rc RC_UBE_KEYWORDS = $PMSRC/pm-jaube-keywords.rc RC_VAC = $PMSRC/pm-javac.rc RC_VAR = $PMSRC/pm-javar.rc } :0 E { # Set LINEBUF so that next message line is not truncated. LINEBUF = 1024 dummy = " ----------------------------------------------------------------------- pm-javar.rc: PANIC: Variable PMSRC does not point to procmail recipe code directory. Add something like this to ~/.procmailrc (using correct install location): PMSRC = $HOME/procmail/procmail-lib/lib ----------------------------------------------------------------------- " } dummy = "pm-javar.rc: end: variables defined." # End of file pm-javar.rc