Subversion Repositories sa-exim

Compare Revisions

Ignore whitespace Rev 22 → Rev 23

/tags/4.2.1-7/debian/control
0,0 → 1,27
Source: sa-exim
Section: mail
Priority: optional
Maintainer: Magnus Holmgren <magnus@kibibyte.se>
Build-Depends: debhelper (>= 4.1.16), links, exim4-dev
Standards-Version: 3.7.2
 
Package: sa-exim
Architecture: any
Depends: exim4-daemon-light (>>4.30-1) | exim4-daemon-heavy (>>4.30-1) | exim4-daemon-custom (>>4.30-1), spamc, ${shlibs:Depends}, debconf (>= 1.2.0) | debconf-2.0
Recommends: ${perl:Depends}
Suggests: spamassassin
Description: Use spamAssassin at SMTP time with the Exim v4 MTA
SA-Exim lets you use spamAssassin at SMTP time with the Exim
v4 MTA, which enables you to do many things with incoming Emails,
including refusing them before they come in, or even teergrubing the
sender (i.e. slowing him down, by tying his resources)
.
Homepage: http://marc.merlins.org/linux/exim/sa.html
.
Note: Most of the functionality of this package can also be achieved
using the exiscan ACL conditions built into the "heavy" Exim daemon,
exim-daemon-heavy. You should use this package if:
.
* you want to use SpamAssassin's report_safe feature, or
* you want easier control over the header fields added, without using
the report template to add multiple fields.
/tags/4.2.1-7/debian/compat
0,0 → 1,0
4
/tags/4.2.1-7/debian/changelog
0,0 → 1,222
sa-exim (4.2.1-7) unstable; urgency=low
 
* Don't depend on debconf in postrm; if we can't prompt the user,
leave the spool directory alone (Closes: #417027).
* Do not pass a '-u' parameter to spamc if SAspamcUser expands to the
empty string.
 
-- Magnus Holmgren <magnus@kibibyte.se> Tue, 3 Apr 2007 13:02:48 +0200
 
sa-exim (4.2.1-6) unstable; urgency=low
 
* Added Portuguese Debconf template translation (Closes: #415537).
Thanks to Pedro Ribeiro.
* It is now possible to pass a username to spamc. See the SAspamcUser
option in sa-exim.conf.
* Build-depend on exim4-dev.
 
-- Magnus Holmgren <magnus@kibibyte.se> Tue, 20 Mar 2007 14:25:31 +0100
 
sa-exim (4.2.1-5) unstable; urgency=low
 
* Added Italian debconf template translation (Closes: #411396). Thanks
to Luca Monducci.
* Added Galician Debconf template translation (Closes: #412804).
Thanks to Jacobo Tarrio.
* Added Dutch debconf template translation (Closes: #413702). Thanks
to Bart Cornelis.
* Added debian/watch.
 
-- Magnus Holmgren <magnus@kibibyte.se> Wed, 7 Mar 2007 15:46:16 +0100
 
sa-exim (4.2.1-4) unstable; urgency=low
 
* Added Spanish debconf template translation (Closes: #404490).
Thanks to Rudy Godoy.
 
-- Magnus Holmgren <magnus@kibibyte.se> Tue, 9 Jan 2007 16:39:43 +0100
 
sa-exim (4.2.1-3) unstable; urgency=low
 
* New maintainer (Closes: #352533).
* Updated package description to explain what SA-Exim can do that
exim-daemon-heavy can't, and vice versa (Closes: #378732).
* Added German debconf template translation (Closes: #399963).
Thanks to Matthias Julius.
* Updated Swedish debconf templates.
* Encourage use of ACL variables in sa-exim.conf. Also exclude ::1
from SA scanning.
* Removed unnecessary question in long description of debconf
template.
* Upgraded to Standards-Version 3.7.2. No changes needed.
* Moved greylistclean to /usr/share/sa-exim. If you have modified
the crontab file, you have to update it manually.
* Added Recommends: perl (needed by greylistclean, but greylistclean
isn't completely necessary.
 
-- Magnus Holmgren <magnus@kibibyte.se> Sun, 3 Dec 2006 00:41:01 +0100
 
sa-exim (4.2.1-2) unstable; urgency=medium
 
* Fixed rights on /var/spool/sa-exim. Closes: #297623
+ Content-type bug closed by 4.2.1-1: Closes: #286069
* Fixed README.greylisting Closes: #325335
+ Added cs, sv, vi translations Closes: #315995, #332363, #317869
+ Added note about unsupported linecontinuation to README
sa-exim.conf already has note Closes: #276080
+ Removed SAtempreject from default sa-exim.conf Closes: #281567
-- Sander Smeenk <ssmeenk@debian.org> Mon, 27 Mar 2006 13:42:06 +0200
sa-exim (4.2.1-1) unstable; urgency=high
 
* SECURITY: new upstream does a better job at being safe when deleting
greylisting tuplets Closes: #345071
* Fixed sa-exim.conf typo Closes: #305890
* Disable former insecure /etc/cron.daily/greylistclean
 
-- Sander Smeenk <ssmeenk@debian.org> Mon, 09 Jan 2006 09:01:25 -0800
 
sa-exim (4.2-1) unstable; urgency=high
 
* New upstream version
* Ship new SA-Exim Greylisting plugin for SA 3.0 or better
* Ship new /etc/cron.daily/greylistclean
* Updated README.Debian
 
-- Marc MERLIN <marc_soft@merlins.org> Mon, 17 Dec 2005 00:14:03 -0800
 
sa-exim (4.1-1) unstable; urgency=high
 
* New upstream version
* SECURITY: new upstream provides SA greylisting patch with shell safe
filenames and directories (only affected users who use the SA greylisting
patch _and_ an unsafe shell cron job to delete old files and directories)
* Updated README.debian to warn that the SA 2.4 greylisting patch is out
of date and unmaintained.
 
-- Marc MERLIN <marc_soft@merlins.org> Mon, 16 Aug 2004 08:32:36 -0700
 
sa-exim (4.0-3) unstable; urgency=low
 
+ Changed hard depend on spamc, since that's all sa-exim needs.
You have to choose to install spamassassin, or run spamc to
another host. This entry closes: #253393
+ Documentation was assed to explain about sa-exim defaulting
to exim4 configured to use exim4/use_split_config. Devine
intervention is needed when using monolithic configs. One day
sa-exim might detect this and act on it?
This entry closes: #251755, #265820
+ Incorrect scoring of messages due to incorrect last-Received:
header is now fixed by newer versions of the exim4 package.
Dependencies have been changed. This entry closes: #250726, #246715
+ Updated Japanese translations of debconf templates. A typo in the
english templates has been fixed too. This entry closes: #252341
 
-- Sander Smeenk <ssmeenk@debian.org> Wed, 15 Aug 2004 19:40:05 +0200
sa-exim (4.0-2) unstable; urgency=low
 
* Clarified SA-greylisting patches in README.Debian
Closes: #245573
+ Added Danish translations
+ Added French translations
Closes: #238537, #239258
 
-- Sander Smeenk <ssmeenk@debian.org> Sat, 24 Apr 2004 11:34:35 +0200
 
sa-exim (4.0-1) unstable; urgency=low
 
* New upstream version
* Added new docs (README.greylisting / SA patches)
* Create /var/spool/sa-exim/tuplets for the new greylisting support
 
-- Marc MERLIN <marc_soft@merlins.org> Tue, 03 Mar 2004 08:52:49 -0800
 
sa-exim (3.1-4) unstable; urgency=low
 
* Fixed minor packaging bugs.
* Debconf gettextized for translators (Closes: #237105)
 
-- Sander Smeenk <ssmeenk@debian.org> Sun, 07 Mar 2004 15:38:47 +0100
 
sa-exim (3.1-3) unstable; urgency=low
 
* Clean up properly on purge, asking per debconf about removing saved mails
in spool-directory if necessary.
* Update to work with exim4 running as Debian-exim (don't include
/var/spool/sa-exim in deb, generate it in postinst; stricter
dependencies).
* sa-exim uses spamc - Correct depends accordingly.
 
-- Sander Smeenk <ssmeenk@debian.org> Sun, 22 Feb 2004 10:32:03 +0100
 
sa-exim (3.1-2) unstable; urgency=low
 
* Minor updates to control suggested by Andreas Metzler
* Minor updates on upstream source (INSTALL / sa-exim.conf)
* Uploaded to Debian (Closes: #196100)
 
-- Marc MERLIN <marc_soft@merlins.org> Wed, 20 Aug 2003 09:18:42 -0700
 
sa-exim (3.1-1) unstable; urgency=low
 
* Upstream update
 
-- Marc MERLIN <marc_soft@merlins.org> Tue, 19 Aug 2003 09:48:13 -0700
 
sa-exim (3.0+cvs-20030802) unstable; urgency=low
 
* Updated sa-exim to cvs version
* Restored plugin location to /usr/lib/exim4/local_scan/
* Added contrib contents to docs
 
-- Marc MERLIN <marc_soft@merlins.org> Sat, 02 Aug 2003 20:57:50 -0700
 
sa-exim (3.0+cvs-20030728) unstable; urgency=low
 
* Updated sa-exim to cvs version
 
-- Marc MERLIN <marc_soft@merlins.org> Mon, 28 Jul 2003 21:08:24 -0500
 
sa-exim (3.0+cvs-1) unstable; urgency=low
 
* Updated sa-exim to cvs version (and new sa-exim.conf config file)
 
-- Marc MERLIN <marc_soft@merlins.org> Mon, 08 Jun 2003 23:19:11 -0700
 
sa-exim (3.0-3) unstable; urgency=low
 
* Taken over from Andreas, thanks for the template
* Rewrote description in control
* Updated docs to contain all the documentation files
* /var/spool/sa-exim will contain the saved mails and is 770/mail.mail
* Do not patch sample sa-exim.conf, run sed during the install
* Removed ${misc:Depends} from control, my dpkg-gencontrol says it's unknown
* Fixes to debian/control, debian/rules and debian/copyright for policy
compliance and to make lintian more happy. Increased Standards-Version to
3.5.10. (Andreas Metzler)
* Add some magic to maintainerscripts, disabling the sa-exim part of exim's
main configuration file when sa-exim is uninstalled. (Andreas Metzler)
 
-- Marc MERLIN <marc_soft@merlins.org> Mon, 26 May 2003 23:22:56 -0700
 
sa-exim (3.0-2) unstable; urgency=low
 
* Small fixes
 
-- Andreas Metzler <ametzler@debian.org> Fri, 2 May 2003 20:20:11 +0200
 
sa-exim (3.0-1) unstable; urgency=low
 
* renamed package to sa-exim
* upgrade to 3.0
 
-- Andreas Metzler <ametzler@debian.org> Fri, 2 May 2003 17:36:28 +0200
 
exim4-sa-plugin (2.2-1) unstable; urgency=low
 
* Initial Release.
 
-- Andreas Metzler <ametzler@debian.org> Thu, 13 Mar 2003 17:16:46 +0100
 
/tags/4.2.1-7/debian/rules
0,0 → 1,87
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
 
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
 
CFLAGS = -Wall -g
 
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
 
configure: configure-stamp
configure-stamp:
dh_testdir
touch configure-stamp
 
build: build-stamp
build-stamp: configure-stamp
dh_testdir
$(MAKE) BUILDCFLAGS='-I/usr/include/exim4 -fPIC $$(CFLAGS)'
touch build-stamp
 
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
-$(MAKE) clean
dh_clean
 
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
install -m755 sa-exim-*so \
$(CURDIR)/debian/sa-exim/usr/lib/exim4/local_scan/sa-exim.so
install -m755 accept*so \
$(CURDIR)/debian/sa-exim/usr/lib/exim4/local_scan/accept.so
sed "s/\/var\/spool\/exim/\/var\/spool\/sa-exim/" < sa-exim.conf > \
$(CURDIR)/debian/sa-exim/etc/exim4/sa-exim.conf
chmod 644 $(CURDIR)/debian/sa-exim/etc/exim4/sa-exim.conf
install -m644 debian/15_sa-exim_plugin_path \
$(CURDIR)/debian/sa-exim/etc/exim4/conf.d/main
install -m644 SA-greylisting-2.4x.diff \
$(CURDIR)/debian/sa-exim/usr/share/doc/sa-exim/sa2.xpatches
install -m644 SA-greylisting-2.6.diff \
$(CURDIR)/debian/sa-exim/usr/share/doc/sa-exim/sa2.xpatches
install -m644 Greylisting.pm \
$(CURDIR)/debian/sa-exim/usr/share/perl5/Mail/SpamAssassin/Plugin/Greylisting.pm
install -m644 greylistclean.cron \
$(CURDIR)/debian/sa-exim/etc/cron.d/greylistclean
install -m755 greylistclean \
$(CURDIR)/debian/sa-exim/usr/share/sa-exim/greylistclean
 
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
 
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs Changelog.html
dh_installdocs
dh_installexamples
dh_installdebconf
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms -Xvar/spool/sa-exim
dh_perl
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
 
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure
Property changes:
Added: svn:executable
Index: 4.2.1-7/debian/postrm
===================================================================
--- 4.2.1-7/debian/postrm (nonexistent)
+++ 4.2.1-7/debian/postrm (revision 23)
@@ -0,0 +1,57 @@
+#!/bin/sh
+set -e
+
+if [ -f /usr/share/debconf/confmodule ]; then
+ . /usr/share/debconf/confmodule
+fi
+
+LOCALSCANCONF=/etc/exim4/conf.d/main/15_sa-exim_plugin_path
+DISABLELOCALSCANTEXT='# sa-exim plugin is disabled, because it was uninstalled'
+DISABLELOCALSCANMD5=`echo "${DISABLELOCALSCANTEXT}" | md5sum | cut -d\ -f1`
+
+case "$1" in
+ remove)
+ # disable local_scan_path directive to exim working
+ if [ -e "$LOCALSCANCONF" ] && [ ! -e "${LOCALSCANCONF}.rul" ]; then
+ echo "${DISABLELOCALSCANTEXT}" > ${LOCALSCANCONF}.rul
+ fi
+ if [ -x /etc/init.d/exim4 ]; then
+ if [ -x /usr/sbin/invoke-rc.d ]; then
+ invoke-rc.d exim4 reload || true
+ else
+ /etc/init.d/exim4 reload || true
+ fi
+ fi
+ ;;
+
+ purge)
+ # clean up temporary file generated by postrm uninstall
+ if [ -e "${LOCALSCANCONF}.rul" ] && \
+ [ "`md5sum ${LOCALSCANCONF}.rul | cut -d\ -f1`" = "${DISABLELOCALSCANMD5}" ]; then
+ rm ${LOCALSCANCONF}.rul
+ fi
+ if [ -x /etc/init.d/exim4 ]; then
+ if [ -x /usr/sbin/invoke-rc.d ]; then
+ invoke-rc.d exim4 reload || true
+ else
+ /etc/init.d/exim4 reload || true
+ fi
+ fi
+ # In the rather uncommon event that debconf has been removed before
+ # us, we have no choice but leaving the spool directory alone.
+ if [ -e /var/spool/sa-exim ] &&
+ ! rmdir /var/spool/sa-exim 2>/dev/null &&
+ [ -f /usr/share/debconf/confmodule ]; then
+ db_version 2.0
+ db_input medium sa-exim/purge_spool || true
+ db_go || true
+ db_get sa-exim/purge_spool
+ purge_spool="$RET"
+ if [ "x${purge_spool}" = "xtrue" ] ; then
+ rm -rf /var/spool/sa-exim
+ fi
+ fi
+ ;;
+esac
+
+#DEBHELPER#
Index: 4.2.1-7/debian/po/pt.po
===================================================================
--- 4.2.1-7/debian/po/pt.po (nonexistent)
+++ 4.2.1-7/debian/po/pt.po (revision 23)
@@ -0,0 +1,46 @@
+# Portuguese translation for sa-exim debconf messages.
+# Copyright (C) 2007 Pedro Ribeiro <p.m42.ribeiro@gmail.com>
+# This file is distributed under the same license as the sa-exim package.
+# Pedro Ribeiro <p.m42.ribeiro@gmail.com>, 2007
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.2.1-5\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2007-03-19 22:08+0100\n"
+"Last-Translator: Pedro Ribeiro <p.m42.ribeiro@gmail.com>\n"
+"Language-Team: Portuguese <traduz@debianpt.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Remover os mails guardados no directório de spool?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Existem alguns mails guardados em sub-directórios de /var/spool/sa-exim. "
+"Dependendo da configuração, o sa-exim guarda os mails que obedecem a certos "
+"critérios (ocorreu um erro, rejeitada como spam, aceite mas marcada como "
+"spam, ...) em sub-directórios de /var/spool/sa-exim."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Pode mantê-las para análise posterior e removê-las mais tarde manualmente ou "
+"apagá-las agora."
Index: 4.2.1-7/debian/po/gl.po
===================================================================
--- 4.2.1-7/debian/po/gl.po (nonexistent)
+++ 4.2.1-7/debian/po/gl.po (revision 23)
@@ -0,0 +1,45 @@
+# Galician translation of sa-exim's debconf templates
+# This file is distributed under the same license as the sa-exim package.
+# Jacobo Tarrio <jtarrio@debian.org>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2007-02-28 10:34+0100\n"
+"Last-Translator: Jacobo Tarrio <jtarrio@debian.org>\n"
+"Language-Team: Galician <proxecto@trasno.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "¿Borrar as mensaxes gravadas do directorio de traballo?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Hai algunhas mensaxes gravadas nos subdirectorios de /var/spool/sa-exim. "
+"Dependendo da configuración, sa-exim ha gravar as mensaxes que encaixen en "
+"determinados criterios (houbo un erro, rexeitada coma spam, pasada aínda que "
+"se recoñeceu coma spam, ...) en subdirectorios de /var/spool/sa-exim."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Pode conservalas para seguir analizándoas e eliminalas despois manualmente "
+"ou decidir eliminalas agora."
Index: 4.2.1-7/debian/po/nl.po
===================================================================
--- 4.2.1-7/debian/po/nl.po (nonexistent)
+++ 4.2.1-7/debian/po/nl.po (revision 23)
@@ -0,0 +1,35 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2007-02-28 19:43+0100\n"
+"Last-Translator: Bart Cornelis <cobaco@skolelinux.no>\n"
+"Language-Team: debian-l10n-dutch <debian-l10n-dutch@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Wilt u dat opgeslagen e-mails verwijderd worden uit de spool-map?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "There are some saved mails in subdirectories of /var/spool/sa-exim. Depending on the configuration sa-exim will save mails matching specific criterias (an error occured, rejected as spam, passed through although recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr "Er zijn een aantal opgeslagen e-mails in de submappen van /var/spool/sa-exim. Afhankelijk van de configuratie slaat sa-exim e-mails die aan specifieke criteria voldoen (bv. fout opgetreden, geweigerd als spam, doorgelaten maar gemarkeerd als spam, ...) op in submappen van /var/spool/sa-exim ."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "You can keep them for further analysis and later remove them manually or decide to delete them now."
+msgstr "U kunt deze behouden voor verdere analyse, en ze dan later handmatig verwijderen, of u kunt ze nu laten verwijderen."
+
Index: 4.2.1-7/debian/po/it.po
===================================================================
--- 4.2.1-7/debian/po/it.po (nonexistent)
+++ 4.2.1-7/debian/po/it.po (revision 23)
@@ -0,0 +1,47 @@
+# Italian (it) translation of debconf templates for sa-exim
+# Copyright (C) 2007 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sa-exim package.
+# Luca Monducci <luca.mo@tiscali.it>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.2.1 italian debconf templates\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2007-02-18 16:41+0100\n"
+"Last-Translator: Luca Monducci <luca.mo@tiscali.it>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Eliminare le mail salvate nella directory di spool?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Nelle sottodirectory di /var/spool/sa.exim sono state salvate delle mail. A "
+"seconda della configurazione di sa-exim le mail vengono salvate se verificano "
+"determinati criteri (si è verificato un errore, rifiutata per spam, passata "
+"nonostante identificata come spam, ecc.) nelle sottodirectory di /var/spool/"
+"sa-exim."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Si possono tenere per una successiva analisi e poi eliminarle manualmente "
+"oppure cancellarle adesso."
Index: 4.2.1-7/debian/po/es.po
===================================================================
--- 4.2.1-7/debian/po/es.po (nonexistent)
+++ 4.2.1-7/debian/po/es.po (revision 23)
@@ -0,0 +1,63 @@
+# sa-exim po-debconf translation to spanish
+# Copyright (C) 2004 Software in the Public Interest
+# This file is distributed under the same license as the sa-exim package.
+#
+# Changes:
+# - Initial translation
+# Rudy Godoy <rudy@kernel-panik.org>, 2006
+#
+#
+# Traductores, si no conoce el formato PO, merece la pena leer la
+# documentación de gettext, especialmente las secciones dedicadas a este
+# formato, por ejemplo ejecutando:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Equipo de traducción al español, por favor lean antes de traducir
+# los siguientes documentos:
+#
+# - El proyecto de traducción de Debian al español
+# http://www.debian.org/intl/spanish/coordinacion
+# especialmente las notas de traducción en
+# http://www.debian.org/intl/spanish/notas
+#
+# - La guía de traducción de po's de debconf:
+# /usr/share/doc/po-debconf/README-trans
+# o http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.2.1\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2006-12-25 11:42-0500\n"
+"Last-Translator: Rudy Godoy <rudy@kernel-panik.org>\n"
+"Language-Team: Debian l10n Spanish <debian-l10n-spanish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "¿Desea eliminar los correos guardados en el directorio «spool»?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr "Existen algunos correos guardados en subdirectorios de «/var/spool/sa-exim». Dependiendo de la configuración, sa-exim guardará los correos que cumplan con un criterio específico (si ha ocurrido un fallo, rechazado como spam, aceptado aunque se ha reconocido como spam, ...) en los subdirectorios de «/var/spool/sa-exim»."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr "Puede conservarlos para un análisis posterior, y eliminarlos de forma manual más tarde, o decidir eliminarlos ahora."
Index: 4.2.1-7/debian/po/de.po
===================================================================
--- 4.2.1-7/debian/po/de.po (nonexistent)
+++ 4.2.1-7/debian/po/de.po (revision 23)
@@ -0,0 +1,59 @@
+# translation of po-debconf template to German
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+# Developers do not need to manually edit POT or PO files.
+#
+# Matthias Julius <mdeb@julius-net.net>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.2.1-2\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2006-11-23 00:53-0500\n"
+"Last-Translator: Matthias Julius <mdeb@julius-net.net>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Gespeicherte E-Mails in Spool-Verzeichnis löschen?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Es befinden sich einige gespeicherte E-Mails in Unterverzeichnissen von /var/"
+"spool/sa-exim. Abhängig von der Konfiguration wird sa-exim E-Mails, die "
+"bestimmte Kriterien erfüllen (ein Fehler ereignete sich, als Spam "
+"abgewiesen, durchgelassen obwohl als Spam erkannt, ...), in "
+"Unterverzeichnissen von /var/spool/sa-exim speichern."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Sie können diese zur späteren Analyse aufbewahren und später löschen, oder "
+"Sie entscheiden, sie jetzt zu löschen."
+
+#~ msgid "Should they be removed?"
+#~ msgstr "Sollen die E-Mails gelöscht werden?"
Index: 4.2.1-7/debian/po/templates.pot
===================================================================
--- 4.2.1-7/debian/po/templates.pot (nonexistent)
+++ 4.2.1-7/debian/po/templates.pot (revision 23)
@@ -0,0 +1,41 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
Index: 4.2.1-7/debian/po/da.po
===================================================================
--- 4.2.1-7/debian/po/da.po (nonexistent)
+++ 4.2.1-7/debian/po/da.po (revision 23)
@@ -0,0 +1,60 @@
+# translation of sa-exim_3.1-4-da.po to Danish
+# translation of sa-exim_3.1-4_templates.po to Danish
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+# Developers do not need to manually edit POT or PO files.
+# Claus Hindsgaul <claus_h@image.dk>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim_3.1-4-da\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2004-11-19 17:21+0100\n"
+"Last-Translator: Claus Hindsgaul <claus_h@image.dk>\n"
+"Language-Team: Danish <dansk@klid.dk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Fjern gemte breve fra spool-mappen?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Der er nogle gemte breve i mapperne under /var/spool/sa-exim. Afhængig af "
+"opsætningen vil sa-exim gemme breve, der opfylder bestemte kriterier (der "
+"opstod en fejl, afvist som spam, lod brevet passere på trods af at det blev "
+"genkendt som spam,...) gemme breve i mapperne under /var/spool/sa-exim."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Du kan beholde dem til yderligere efterforskning og selv fjerne dem senere "
+"eller vælge at få dem slettet nu."
+
+#~ msgid "Should they be removed?"
+#~ msgstr "Skal de slettes?"
Index: 4.2.1-7/debian/po/cs.po
===================================================================
--- 4.2.1-7/debian/po/cs.po (nonexistent)
+++ 4.2.1-7/debian/po/cs.po (revision 23)
@@ -0,0 +1,57 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2005-06-27 20:12+0200\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Odstranit emaily v adresáři spool?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"V podadresářích adresáře /var/spool/sa-exim se nachází nějaké uložené "
+"emaily. Podle nastavení může sa-exim ukládat do těchto adresářů emaily, "
+"které se shodují s danými kritérii (výskyt chyby, odmítnuto jako spam, "
+"předáno dále, přestože vypadá jako spam, ...)."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Emaily si můžete ponechat pro budoucí analýzu a poté je smazat ručně, nebo "
+"je můžete smazat přímo teď."
+
+#~ msgid "Should they be removed?"
+#~ msgstr "Mají se odstranit?"
Index: 4.2.1-7/debian/po/fr.po
===================================================================
--- 4.2.1-7/debian/po/fr.po (nonexistent)
+++ 4.2.1-7/debian/po/fr.po (revision 23)
@@ -0,0 +1,58 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2004-08-17 11:00+0200\n"
+"Last-Translator: Eric Madesclair <eric-m@wanadoo.fr>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Faut-il supprimer les courriers du répertoire de dépôt ? "
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Il y a plusieurs courriers sauvegardés dans les sous-répertoires de /var/"
+"spool/sa-exim. Selon la configuration, sa-exim sauvegarde les courriers qui "
+"correspondent à des critères spécifiques (p. ex. une erreur est survenue, "
+"rejeté comme spam, passé à travers, reconnu comme spam ...) dans des sous-"
+"répertoires de /var/spool/sa-exim."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Vous pouvez les garder pour des analyses approfondies et les supprimer par "
+"la suite ou vous pouvez décider de les effacer maintenant."
+
+#~ msgid "Should they be removed?"
+#~ msgstr "Vous pouvez les supprimer maintenant."
Index: 4.2.1-7/debian/po/sv.po
===================================================================
--- 4.2.1-7/debian/po/sv.po (nonexistent)
+++ 4.2.1-7/debian/po/sv.po (revision 23)
@@ -0,0 +1,56 @@
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+# Developers do not need to manually edit POT or PO files.
+# , fuzzy
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.2-2\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2006-12-02 02:07+0100\n"
+"Last-Translator: Magnus Holmgren <magnus@kibibyte.se>\n"
+"Language-Team: Swedish <sv@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Ta bort sparad e-post i spool-mappen?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Det finns några sparade e-postmeddelanden i undermappar till /var/spool/sa-"
+"exim. Beroende på konfigurationen kan sa-exim spara e-post som matchar "
+"specifika kriterier (ett fel inträffade, avvisat som spam, genomsläppt trots "
+"spamklassat, ...) i undermappar till /var/spool/sa-exim."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Du kan spara dom för vidare analys och senare ta bort dom manuellt eller "
+"välja att ta bort dom nu."
+
+#~ msgid "Should they be removed?"
+#~ msgstr "Ska de tas bort?"
Index: 4.2.1-7/debian/po/ja.po
===================================================================
--- 4.2.1-7/debian/po/ja.po (nonexistent)
+++ 4.2.1-7/debian/po/ja.po (revision 23)
@@ -0,0 +1,57 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.0-2\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2004-08-19 15:21+0900\n"
+"Last-Translator: Hideki Yamane <henrich@samba.gr.jp>\n"
+"Language-Team: Japanese <debian-japanese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=EUC-JP\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "¥¹¥×¡¼¥ë¥Ç¥£¥ì¥¯¥È¥ê¤ËÊݸ¤·¤¿¥á¡¼¥ë¤òºï½ü¤·¤Þ¤¹¤«?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"/var/spool/sa-exim ¤Î²¼¤ËÊݸ¤µ¤ì¤¿¥á¡¼¥ë¤¬¤¢¤ê¤Þ¤¹¡£sa-exim ¤ÎÀßÄê¤Ë¤è¤Ã¤Æ¡¢"
+"sa-exim ¤ÏÆÃÄê¤Î¹àÌÜ (¥¨¥é¡¼¤¬µ¯¤­¤¿¡¢spam¤È¤·¤ÆµñÈݤµ¤ì¤¿¡¢spam ¤Èǧ¼±¤µ¤ì¤¿"
+"¤Ë¤â´Ø¤ï¤é¤ºÄ̤êÈ´¤±¤¿¡¢¤Ê¤É...) ¤Ë¥Þ¥Ã¥Á¤·¤¿¥á¡¼¥ë¤ò /var/spool/sa-exim ¤Î²¼"
+"¤ËÊݸ¤·¤Þ¤¹¡£"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"ʬÀϤΤ¿¤á¤Ë»Ä¤·¤Æ¸å¤Ë¼êÆ°¤Çºï½ü¤¹¤ë¤«¡¢º£¤¹¤°ºï½ü¤¹¤ë¤«¤ò·è¤á¤é¤ì¤Þ¤¹¡£"
+
+#~ msgid "Should they be removed?"
+#~ msgstr "ºï½ü¤·¤Þ¤¹¤«?"
Index: 4.2.1-7/debian/po/vi.po
===================================================================
--- 4.2.1-7/debian/po/vi.po (nonexistent)
+++ 4.2.1-7/debian/po/vi.po (revision 23)
@@ -0,0 +1,50 @@
+# Vietnamese translation for sa-exim.
+# Copyright © 2005 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sa-exim 4.2-2\n"
+"Report-Msgid-Bugs-To: magnus@kibibyte.se\n"
+"POT-Creation-Date: 2006-12-02 20:15+0100\n"
+"PO-Revision-Date: 2005-07-12 15:07+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <gnomevi-list@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"X-Generator: LocFactoryEditor 1.2.2\n"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid "Remove saved mails in spool directory?"
+msgstr "Loại bỏ các thư đã lưu trong thư mục ống chỉ không?"
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"There are some saved mails in subdirectories of /var/spool/sa-exim. "
+"Depending on the configuration sa-exim will save mails matching specific "
+"criterias (an error occured, rejected as spam, passed through although "
+"recognized as spam, ...) in subdirectories of /var/spool/sa-exim."
+msgstr ""
+"Có một số thư đã lưu trong thư mục con của «/var/spool/sa-exim». Phụ thuộc "
+"vào cấu hình, trình sa-exim sẽ lưu thư khớp với tiêu chuẩn dứt khoát (gặp "
+"lỗi, thư bị từ chối vì rác, thư qua được dù phân loại là rác v.v.) vào thư "
+"mục con của «/var/spool/sa-exim»."
+
+#. Type: boolean
+#. Description
+#: ../templates:1001
+msgid ""
+"You can keep them for further analysis and later remove them manually or "
+"decide to delete them now."
+msgstr ""
+"Bạn có thể giữ các thư ấy để phân tích thêm nữa rồi sau đó tự loại bỏ chúng, "
+"hoặc quyết định xóa bỏ chúng ngay bây giờ."
+
+#~ msgid "Should they be removed?"
+#~ msgstr "Bạn có muốn loại bỏ các lưu ấy không?"
Index: 4.2.1-7/debian/po/POTFILES.in
===================================================================
--- 4.2.1-7/debian/po/POTFILES.in (nonexistent)
+++ 4.2.1-7/debian/po/POTFILES.in (revision 23)
@@ -0,0 +1 @@
+[type: gettext/rfc822deb] templates
Index: 4.2.1-7/debian/watch
===================================================================
--- 4.2.1-7/debian/watch (nonexistent)
+++ 4.2.1-7/debian/watch (revision 23)
@@ -0,0 +1,3 @@
+version=3
+
+http://marc.merlins.org/linux/exim/sa.html files/sa-exim-(\d+(?:\.\d+)*)\.tar\.gz
Index: 4.2.1-7/debian/dirs
===================================================================
--- 4.2.1-7/debian/dirs (nonexistent)
+++ 4.2.1-7/debian/dirs (revision 23)
@@ -0,0 +1,7 @@
+usr/lib/exim4/local_scan
+usr/share/doc/sa-exim/patches
+etc/exim4/conf.d/main
+usr/share/perl5/Mail/SpamAssassin/Plugin
+usr/share/sa-exim
+etc/cron.d
+usr/sbin
Index: 4.2.1-7/debian/copyright
===================================================================
--- 4.2.1-7/debian/copyright (nonexistent)
+++ 4.2.1-7/debian/copyright (revision 23)
@@ -0,0 +1,33 @@
+This package was adopted by the current Debian maintainer,
+Magnus Holmgren <magnus@debian.org>, on Fri, 1 Dec 2006 19:05:58 +0100.
+
+Before that, it was maintained by Sander Smeenk <ssmeenk@debian.org>, who
+adopted it on Tue, 24 Feb 2004 19:47:11 +0100.
+
+The package was originally debianized by Andreas Metzler
+<ametzler@debian.org> on Thu, 13 Mar 2003 17:16:46 +0100.
+
+Upstream Author: Marc MERLIN <marc_soft@merlins.org>
+
+It was downloaded from http://marc.merlins.org/linux/exim/sa.html
+
+
+Copyright:
+
+ This package 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; version 2 dated June, 1991.
+
+ This package 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 package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301, USA
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
Index: 4.2.1-7/debian/README.Debian
===================================================================
--- 4.2.1-7/debian/README.Debian (nonexistent)
+++ 4.2.1-7/debian/README.Debian (revision 23)
@@ -0,0 +1,164 @@
+********************************
+* SHOULD YOU USE THIS PACKAGE? *
+********************************
+
+Since version 4.50, Exim has the content-scanning extension formerly
+known as "exiscan" built-in. It has a number of advantages and
+disadvantages compared to SA-Exim.
+
+Advantages of built-in content-scanning interface:
+
+ * One less configuration file to edit.
+ * Spam control policy integrates better with Exim's ACL system.
+ * It's possible to tell SA which user to scan for (the -u parameter of
+ spamc). SA-Exim can't do that (yet).
+ * Finer control over the mail header is possible, but not in a clean
+ way (it involves putting all header fields you might possibly want
+ to add in the report template, and using rather complicated
+ expansion expressions to extract the wanted ones from
+ $spam_report). At any rate, you can choose a prefix different from
+ "X-Spam-".
+
+Advantages of SA-Exim:
+
+ * It is possible to use the report_safe feature, which turns mail
+ deemed to be spam into a message/rfc822 attachment of a report
+ message. (Note however that if you do, then any X-SA-* fields added
+ to help the greylisting module can't be removed.)
+ * All the add_header and rewrite_header options in
+ /etc/spamassassin/local.cf will be obeyed. In other words,
+ everything will be *almost* as if you filtered the mail through
+ spamassassin on the command line.
+ * So-called teergrubing ("tarpitting") is possible in a way that
+ isn't possible with exiscan (I'm not in any way saying that it
+ works as a counterattack against spammers).
+ * You can simply add the sa-exim package to a standard exim4
+ installation and it should, in principle, instantly work (except
+ you have to uncomment one line in sa-exim.conf).
+
+Both alternatives enable you to defer, greylist, reject, and blackhole
+mail, optionally saving copies, at configurable score levels.
+
+*****************
+* CONFIGURATION *
+*****************
+
+This version of the sa-exim package defaults to placing a configuration
+sniplet in /etc/exim4/conf.d/. Depending on what you have answered to the
+DebConf questions while configuring Exim4, the module will be loaded
+automatically, or human intervention is required.
+
+To find out what configuration file Exim4 is using, issue:
+
+ $ exim4 -bV | tail -1
+ Configuration file is /path/to/configfile
+
+If /path/to/configfile shows:
+
+ - /etc/exim4/exim4.conf
+ You are using the hand-crafted configuration file.
+ See the 'HAND-CRAFTED' section below.
+
+ - /var/lib/exim4/config.autogenerated
+ You are using the debianized configuration scheme - with either
+ 'split' or 'unsplit' configuration file.
+ See the 'DEBIANIZED' section below.
+
+
+HAND-CRAFTED
+------------
+
+Use 'grep "local_scan_path" /etc/exim4/exim4.conf" to see if the sa-exim
+line is included in the configuration. If grep returns something, check
+if it matches the following line. If grep returns nothing, you have to
+manually add the following line to the exim4.conf file and restart exim4.
+
+ local_scan_path = /usr/lib/exim4/local_scan/sa-exim.so
+
+Change or add the line above and manually restart exim4 by issuing
+'invoke-rc.d exim4 reload' or '/etc/init.d/exim4 reload' as root.
+
+
+DEBIANIZED
+----------
+
+Use 'grep "local_scan_path" /var/lib/exim4/config.autogenerated' to
+see if the sa-exim line is included in the configuration. If grep
+returns something, you're set and already using the sa-exim module. If
+grep returns nothing, we need to figure out a few things:
+
+Issue:
+ $ grep "use_split_config" /etc/exim4/update-exim4.conf.conf
+ dc_use_split_config='true'
+
+If your result shows 'false' where mine shows 'true', then you're
+using the unsplit configuration, generated from
+/etc/exim4/exim4.conf.template. If you haven't customized that file
+you could edit /etc/exim4/update-exim4.conf.conf by hand, change the
+'false' to 'true' and issue 'update-exim4.conf' as root. Then, check
+again if the sa-exim module line is included. It should. If it still
+isn't: mail me. If it is, restart exim4 by issuing 'invoke-rc.d exim4
+restart' or '/etc/init.d/exim4 restart' as root. If you *have*
+customized /etc/exim4/exim4.conf.template, then you'd better stick
+with the unsplit configuration scheme and add the local_scan_path
+setting by hand, like with the hand-crafted configuration file.
+
+Next, read all about greylisting and sa-exim:
+
+***************
+* GREYLISTING *
+***************
+Notes on greylisting with sa-exim.
+
+If you use SpamAssassin 3.0 or better, you do not need to patch it, you
+can just use the Greylisting module shipped with sa-exim.
+The only thing you need to do to enable it, is to copy the 4 lines below
+loadplugin in the greylisting README, and adjust the score if you wish (see
+README.Greylisting for details)
+
+
+If you use a version of SA older than 3.0 (if you are, you really,
+really should upgrade!), you will need to patch spamassassin's sources
+to support greylisting.
+
+There are two versions of the patches:
+ - /usr/share/doc/sa-exim/patches/SA-greylisting-2.4x.diff
+ This patch can be applied to versions 2.4x of SpamAssassin. Note
+ that this patch is not fully functional anymore, it is just left as
+ a template should you want to backport the current 2.6x patch.
+ That said, you really ought to upgrade SA to 2.6x or 3.x
+
+ - /usr/share/doc/sa-exim/patches/SA-greylisting-2.6.diff
+ This patch can be applied to versions 2.6x of SpamAssassin.
+
+Please read README.Greylisting for more information on how to enable
+this feature, and what further changes are needed.
+Note that this configuration won't be supported in the future, and you
+are encouraged to upgrade to SA 3.0 or better.
+
+*************
+* BE WARNED *
+*************
+
+By applying these patches, you change the sourcecode of SpamAssassin
+(again, this is if you use a version of SpamAssassin earlier than 3.0)
+This also means that when the SpamAssassin package gets upgraded, the
+changes made by the patch are LOST.
+This *MIGHT* cause your mail setup to break. It might be best to put
+SpamAssassin on hold:
+
+ $ echo "spamassassin hold" | dpkg --set-selections
+
+You can later set it to install again with:
+
+ $ echo "spamassassin install" | dpkg --set-selections
+
+
+**********************************
+* NOTICE ABOUT SPAMC CONFIG FILE *
+**********************************
+
+Recent versions of spamc can read command-line parameters and switches
+from a configuration file called /etc/spamassassin/spamc.conf. If that
+file specifies conflicting options, it will prevent SA-Exim from
+working. For now, you'll have to make sure that it doesn't.
Index: 4.2.1-7/debian/templates
===================================================================
--- 4.2.1-7/debian/templates (nonexistent)
+++ 4.2.1-7/debian/templates (revision 23)
@@ -0,0 +1,11 @@
+Template: sa-exim/purge_spool
+Type: boolean
+Default: false
+_Description: Remove saved mails in spool directory?
+ There are some saved mails in subdirectories of /var/spool/sa-exim.
+ Depending on the configuration sa-exim will save mails matching specific
+ criterias (an error occured, rejected as spam, passed through although
+ recognized as spam, ...) in subdirectories of /var/spool/sa-exim.
+ .
+ You can keep them for further analysis and later remove them manually or
+ decide to delete them now.
Index: 4.2.1-7/debian/postinst
===================================================================
--- 4.2.1-7/debian/postinst (nonexistent)
+++ 4.2.1-7/debian/postinst (revision 23)
@@ -0,0 +1,55 @@
+#!/bin/sh
+set -e
+
+. /usr/share/debconf/confmodule
+
+LOCALSCANCONF=/etc/exim4/conf.d/main/15_sa-exim_plugin_path
+DISABLELOCALSCANTEXT='# sa-exim plugin is disabled, because it was uninstalled'
+DISABLELOCALSCANMD5=`echo "${DISABLELOCALSCANTEXT}" | md5sum | cut -d\ -f1`
+
+OLDCRONJOB=/etc/cron.hourly/greylistclean
+OLDCRONJOBREN=/etc/cron.hourly/.greylistclean.insecure.deleteme
+if test -f $OLDCRONJOB; then
+ echo "disabling old insecure $OLDCRONJOB"
+ echo "(renamed to $OLDCRONJOBREN)"
+ echo "See new cronjob in /etc/cron.d/greylistclean"
+ /bin/mv $OLDCRONJOB $OLDCRONJOBREN
+fi
+
+case "$1" in
+ configure)
+ if [ ! -e /var/spool/sa-exim ] ; then
+ # Debian-exim should exist as we depend on exim4-base
+ install -d -m771 -oDebian-exim -gDebian-exim \
+ /var/spool/sa-exim
+ elif [ -d /var/spool/sa-exim ]; then
+ # Fix permissions
+ chmod 771 /var/spool/sa-exim
+ chown Debian-exim:Debian-exim /var/spool/sa-exim
+ fi
+ # Support for greylisting tuplets (written as nobody by spamd)
+ if [ ! -e /var/spool/sa-exim/tuplets ] ; then
+ install -d -m750 -onobody -gDebian-exim \
+ /var/spool/sa-exim/tuplets
+ elif [ -d /var/spool/sa-exim/tuplets ]; then
+ # Fix permissions
+ chmod 771 /var/spool/sa-exim/tuplets
+ chown nobody:Debian-exim /var/spool/sa-exim/tuplets
+ fi
+ # clean up temporary file generated by postrm uninstall
+ if [ -e "${LOCALSCANCONF}.rul" ] && \
+ [ "`md5sum ${LOCALSCANCONF}.rul | cut -d\ -f1`" = "${DISABLELOCALSCANMD5}" ]; then
+ rm ${LOCALSCANCONF}.rul
+ fi
+ if [ -x /etc/init.d/exim4 ]; then
+ if [ -x /usr/sbin/invoke-rc.d ]; then
+ invoke-rc.d exim4 reload || true
+ else
+ /etc/init.d/exim4 reload || true
+ fi
+ fi
+ ;;
+
+esac
+
+#DEBHELPER#
Index: 4.2.1-7/debian/15_sa-exim_plugin_path
===================================================================
--- 4.2.1-7/debian/15_sa-exim_plugin_path (nonexistent)
+++ 4.2.1-7/debian/15_sa-exim_plugin_path (revision 23)
@@ -0,0 +1,9 @@
+# This will enable sa-exim, but it won't actually scan and possibly reject
+# messsages before you enable this in sa-exim.conf (see SAEximRunCond)
+#
+# For a starter, you'd probably want to read the documentation at:
+# /usr/share/doc/sa-exim/README.Debian
+# and
+# /usr/share/doc/sa-exim/README.gz
+#
+local_scan_path = /usr/lib/exim4/local_scan/sa-exim.so
Index: 4.2.1-7/debian/config
===================================================================
--- 4.2.1-7/debian/config (nonexistent)
+++ 4.2.1-7/debian/config (revision 23)
@@ -0,0 +1,5 @@
+#!/bin/sh -e
+
+. /usr/share/debconf/confmodule
+
+exit 0
Index: 4.2.1-7/debian/docs
===================================================================
--- 4.2.1-7/debian/docs (nonexistent)
+++ 4.2.1-7/debian/docs (revision 23)
@@ -0,0 +1,8 @@
+ACKNOWLEDGEMENTS
+Acknowledgements.html
+README
+README.greylisting
+sa.html
+TODO
+contrib/sa-exim-stats.txt
+contrib/spam_resend.txt
Index: 4.2.1-7/sa-exim.c
===================================================================
--- 4.2.1-7/sa-exim.c (nonexistent)
+++ 4.2.1-7/sa-exim.c (revision 23)
@@ -0,0 +1,1542 @@
+/* Spamassassin in local_scan by Marc MERLIN <marc_soft@merlins.org> */
+/* $Id: sa-exim.c,v 1.71 2005/03/08 20:39:51 marcmerlin Exp $ */
+/*
+
+The inline comments and minidocs were moved to the distribution tarball
+
+You can get the up to date version of this file and full tarball here:
+http://sa-exim.sourceforge.net/
+http://marc.merlins.org/linux/exim/sa.html
+The discussion list is here:
+http://lists.merlins.org/lists/listinfo/sa-exim
+*/
+
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "sa-exim.h"
+
+/* Exim includes */
+#include "local_scan.h"
+extern FILE *smtp_out; /* Exim's incoming SMTP output file */
+extern int body_linecount; /* Line count in body */
+extern uschar *primary_hostname;
+
+#ifdef DLOPEN_LOCAL_SCAN
+
+/* Karsten Engelke <me@kaeng.org> says this is missing on openbsd */
+#ifndef RTLD_NOW
+#define RTLD_NOW 0x002
+#endif
+
+/* Return the verion of the local_scan ABI, if being compiled as a .so */
+int local_scan_version_major(void)
+{
+ return LOCAL_SCAN_ABI_VERSION_MAJOR;
+}
+
+int local_scan_version_minor(void)
+{
+ return LOCAL_SCAN_ABI_VERSION_MINOR;
+}
+
+/* Left over for compatilibility with old patched exims that didn't have
+ a version number with minor an major. Keep in mind that it will not work
+ with older exim4s (I think 4.11 is required) */
+#ifdef DLOPEN_LOCAL_SCAN_OLD_API
+int local_scan_version(void)
+{
+ return 1;
+}
+#endif
+#endif
+
+#ifndef SAFEMESGIDCHARS
+#define SAFEMESGIDCHARS "!#%( )*+,-.0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~";
+#endif
+
+
+/******************************/
+/* Compile time config values */
+/******************************/
+#ifndef SPAMC_LOCATION
+#define SPAMC_LOCATION "/usr/bin/spamc"
+#endif
+
+#ifndef SPAMASSASSIN_CONF
+#define SPAMASSASSIN_CONF "/etc/exim4/sa-exim.conf"
+#endif
+static const char conffile[]=SPAMASSASSIN_CONF;
+
+
+/********************/
+/* Code starts here */
+/********************/
+static const char nospamstatus[]="<error finding status>";
+
+static char *buffera[4096];
+static char *buffer=(char *)buffera;
+static int SAEximDebug=0;
+static int SAPrependArchiveWithFrom=1;
+static jmp_buf jmp_env;
+
+static char *where="Error handler called without error string";
+static int line=-1;
+static char *panicerror;
+
+#define MIN(a,b) (a<b?a:b)
+
+#define CHECKERR(mret, mwhere, mline) \
+ if (mret < 0) \
+ { \
+ where=mwhere; \
+ line=mline; \
+ goto errexit; \
+ }
+
+#define PANIC(merror) \
+ panicerror=merror; \
+ goto panicexit;
+
+
+static void alarm_handler(int sig)
+{
+ sig = sig; /* Keep picky compilers happy */
+ longjmp(jmp_env, 1);
+}
+
+
+/* Comparing header lines isn't fun, especially since the comparison has to
+ be caseless, so we offload this to this function
+ You can scan on partial headers, just give the root to scan for
+ Return 1 if the header was found, 0 otherwise */
+static int compare_header(char *buffertocompare, char *referenceheader)
+{
+ int idx;
+ int same=1;
+
+ for (idx=0; idx<strlen(referenceheader); idx++)
+ {
+ if ( tolower(referenceheader[idx]) != tolower(buffertocompare[idx]) )
+ {
+ same=0;
+ break;
+ }
+ }
+
+ if (SAEximDebug > 7)
+ {
+ if (same)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug8: Found %s in %s", referenceheader, buffertocompare);
+ }
+ else if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: Did not find %s in %s", referenceheader, buffertocompare);
+ }
+ }
+
+ return same;
+}
+
+
+/* returns a header from a buffer line */
+static char *get_header(char *buffer)
+{
+ char *start;
+ char *end;
+ char *header;
+
+ start=buffer;
+ end=strstr(buffer, ":");
+
+ header=string_copyn(start, end-start);
+
+ if (SAEximDebug>5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: Extracted header %s in buffer %s", header, buffer);
+ }
+
+ return header;
+}
+
+
+/* Rejected mails can be archived in a spool directory */
+/* filename will contain a double / before the filename, I prefer two to none */
+static int savemail(int readfd, off_t fdstart, char *dir, char *dirvarname,
+ char *filename, int SAmaxarchivebody, char *condition)
+{
+ header_line *hl;
+ int writefd=0;
+ int ret;
+ ssize_t stret;
+ off_t otret;
+ char *expand;
+ char *fake_env_from;
+ int towrite;
+ int chunk;
+ struct stat bufst;
+
+ if (dir == NULL)
+ {
+ if (SAEximDebug>4)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug5: Not saving message because %s in undefined", dirvarname);
+ }
+ return 0;
+ }
+
+ if (condition[0] != '1' || condition[1] != 0)
+ {
+ expand=expand_string(condition);
+ if (expand == NULL)
+ {
+ /* Can't use PANIC within this function :( */
+ CHECKERR(-1, string_sprintf("savemail condition expansion failure on %s", condition), __LINE__ - 1);
+ }
+
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: savemail condition expand returned: '%s'", expand);
+ }
+
+ if (expand[0] == 0 || (expand[0] == '0' && expand[1] == 0))
+ {
+ if (SAEximDebug > 1)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug2: savemail condition expanded to false, not saving message to disk");
+ }
+ return 0;
+ }
+ }
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: Writing message to %s/new/%s", dir, filename);
+
+ }
+
+ if (stat(string_sprintf("%s/new/", dir), &bufst) == -1)
+ {
+ log_write(0, LOG_MAIN, "SA: Notice: creating maildir tree in %s", dir);
+ if (stat(dir, &bufst) == -1)
+ {
+ ret=mkdir (dir, 0770);
+ CHECKERR(ret,string_sprintf("mkdir %s", dir),__LINE__);
+ }
+ ret=mkdir (string_sprintf("%s/new", dir), 0770);
+ CHECKERR(ret,string_sprintf("mkdir %s/new/", dir),__LINE__);
+ ret=mkdir (string_sprintf("%s/cur", dir), 0770);
+ CHECKERR(ret,string_sprintf("mkdir %s/cur/", dir),__LINE__);
+ ret=mkdir (string_sprintf("%s/tmp", dir), 0770);
+ CHECKERR(ret,string_sprintf("mkdir %s/tmp/", dir),__LINE__);
+ }
+
+ /* Let's not worry about you receiving two spams at the same second
+ * with the same message ID. If you do, the second one will overwrite
+ * the first one */
+ writefd=creat(string_sprintf("%s/new/%s", dir, filename), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ CHECKERR(writefd, string_sprintf("creat %s/new/%s", dir, filename),__LINE__);
+
+ /* make the file look like a valid mbox -- idea from dman */
+ /* Although now that we use maildir format, this isn't really necessary */
+ /* Richard Lithvall made this an option */
+ if(SAPrependArchiveWithFrom == 1)
+ {
+ fake_env_from=string_sprintf("From %s Thu Jan 1 00:00:01 1970\n",sender_address);
+ stret=write(writefd, fake_env_from, strlen(fake_env_from));
+ CHECKERR(stret,string_sprintf("'From ' line write in %s", filename),__LINE__);
+ }
+
+ /* First we need to get the header lines from exim, and then we can read
+ the body from writefd */
+ hl=header_list;
+ while (hl != NULL)
+ {
+ /* type '*' means the header is internal, don't print it */
+ if (hl->type == '*')
+ {
+ hl=hl->next;
+ continue;
+ }
+ stret=write(writefd,hl->text,strlen(hl->text));
+ CHECKERR(stret,string_sprintf("header line write in %s", filename),__LINE__);
+ hl=hl->next;
+ }
+ stret=write(writefd,"\n",1);
+ CHECKERR(stret,string_sprintf("header separation write in %s", filename),__LINE__);
+
+ /* Now copy the body to the save file */
+ /* we already read from readfd, so we need to reset it */
+ otret=lseek(readfd, fdstart, SEEK_SET);
+ CHECKERR(otret, "lseek reset on spooled message", __LINE__);
+
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: Archive body write starts: writing up to %d bytes in %d byte blocks", SAmaxarchivebody, sizeof(buffera));
+ }
+
+ towrite=SAmaxarchivebody;
+ chunk=0;
+ while (towrite>0 && (stret=read(readfd, buffer, MIN(sizeof(buffera), towrite))) > 0)
+ {
+ chunk++;
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: Processing archive body chunk %d (read %.0f, and %.0f can still be written)", chunk, (double)stret, (double)towrite);
+ }
+ towrite-=stret;
+ stret=write(writefd, buffer, stret);
+ CHECKERR(stret,string_sprintf("body write in %s", filename),__LINE__);
+ }
+ CHECKERR(stret, "read body for archival", __LINE__ - 8);
+ ret=close(writefd);
+ CHECKERR(ret, "Closing spooled message",__LINE__);
+ return 0;
+
+ /* catch the global errexit, clean up, and return the error up */
+ errexit:
+ close(writefd);
+ return -1;
+}
+
+/*
+ * let's add the X-SA-Exim-Connect-IP, X-SA-Exim-Rcpt-To, and
+ * X-SA-Exim-Mail-From headers.
+ * Those are all required by the greylisting with SA implementation
+ * And From/Rcpt-To can also be used for personalized SA rules
+ */
+void AddSAEheaders(char *rcptlist, int SAmaxrcptlistlength)
+{
+ if (sender_host_address)
+ {
+ header_add(' ', "X-SA-Exim-Connect-IP: %s\n", sender_host_address);
+ }
+ else
+ {
+ header_add(' ', "X-SA-Exim-Connect-IP: <locally generated>\n");
+ }
+
+ /* Create a mega envelope-to header with all the recipients */
+ /* Note, if you consider this a privacy violation, you can remove the header
+ * in exim's system filter.
+ * This is very useful to see who a message was really sent to, and can
+ * be used by Spamassassin to do additional scoring */
+ if (strlen(rcptlist) <= SAmaxrcptlistlength)
+ {
+ header_add(' ', "X-SA-Exim-Rcpt-To: %s\n", rcptlist);
+ }
+ /* Therefore SAmaxrcptlistlength set to 0 disables the header completely */
+ else if (SAmaxrcptlistlength)
+ {
+ header_add(' ', "X-SA-Exim-Rcpt-To: too long (recipient list exceeded maximum allowed size of %d bytes)\n", SAmaxrcptlistlength);
+ }
+
+ header_add(' ', "X-SA-Exim-Mail-From: %s\n", sender_address);
+}
+
+void RemoveHeaders(char *headername)
+{
+ header_line *hl;
+
+ /* Remove headers that SA can set */
+ hl=header_list;
+ while (hl != NULL)
+ {
+
+ /* type '*' means the header is internal or deleted */
+ if (hl->type == '*')
+ {
+ hl=hl->next;
+ continue;
+ }
+
+ /* Strip all SA and SA-Exim headers on incoming mail */
+ if ( compare_header((char *)hl->text, headername) )
+ {
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: removing header %s on incoming mail '%s'", headername, (char *)hl->text);
+ }
+ hl->type = '*';
+ }
+ hl=hl->next;
+ }
+}
+
+
+/*
+ * Headers can be multi-line (in theory all of them can I think). Parsing them
+ * is a little more work than a simple line scan, so we're off-loading this to
+ * a function
+ */
+int parsemlheader(char *buffer, FILE *readfh, char *headername, char **header)
+{
+ header_line *hl;
+ char *dummy;
+ char *foundheadername;
+
+ if (SAEximDebug > 4)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug5: looking for header %s", headername);
+ }
+
+ if (header == NULL)
+ {
+ header=&dummy;
+ }
+
+ if (compare_header(buffer, string_sprintf("%s", headername)))
+ {
+ *header=string_copy(buffer);
+
+ /* Read the next line(s) in case this is a multi-line header */
+ while ((fgets((char *)buffer,sizeof(buffera),readfh)) != NULL)
+ {
+ /* Remove trailing newline */
+ if (buffer[strlen(buffer)-1] == '\n')
+ {
+ buffer[strlen(buffer)-1]=0;
+ }
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: while parsing header %s, read %s", headername, buffer);
+ }
+ /* concatenated lines only start with space or tab. right? */
+ if (buffer[0] != ' ' && buffer[0] != '\t')
+ {
+ break;
+ }
+
+ /* Guard against humongous header lines */
+ if (strlen(*header) < 8000)
+ {
+ /* Slight waste of memory here, oh well... */
+ *header=string_sprintf("%s\n%s", *header, buffer);
+ }
+ else
+ {
+ log_write(0, LOG_MAIN, "SA: Warning: while parsing header %s, ignoring the following trailing line due to header size overflow: %s", headername, buffer);
+
+ }
+ }
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: header pieced up %s as: '%s'", headername, *header);
+ }
+
+ /* Headers need a newline at the end before being handed out to exim */
+ /* Slight waste of memory here, oh well... */
+ *header=string_sprintf("%s\n", *header);
+
+ foundheadername=get_header(*header);
+
+ /* Mark the former header as deleted if it's already present */
+ /* Note that for X-Spam, it won't since we already deleted it earlier */
+ hl=header_list;
+ while (hl != NULL)
+ {
+ /* type '*' means the header is internal or deleted */
+ if (hl->type == '*')
+ {
+ hl=hl->next;
+ continue;
+ }
+
+ if ( compare_header((char *)hl->text, foundheadername) )
+ {
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: removing old copy of header '%s' and replacing with new one: '%s'", (char *)hl->text, *header);
+ }
+ hl->type = '*';
+ break;
+ }
+ hl=hl->next;
+ }
+
+ header_add(' ', "%s", *header);
+ return 1;
+ }
+ return 0;
+}
+
+
+char *cleanmsgid(char *msgid, char *SAsafemesgidchars)
+{
+ char *safemesgid;
+ char *ptr;
+
+ /* In case the message-Id is too long, let's truncate it */
+ safemesgid=string_copyn(msgid, 220);
+ ptr=safemesgid;
+
+ /* Clean Message-ID to make sure people can't write on our FS */
+ while (*ptr)
+ {
+ /* This might be more aggressive than you want, but since you
+ * potentially have shell programs dealing with the resulting filenames
+ * let's make it a bit safer */
+ if (strchr(SAsafemesgidchars, *ptr) == NULL)
+ {
+ *ptr='_';
+ }
+ ptr++;
+ }
+
+ if (SAEximDebug > 1)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug2: Message-Id taken from Exim and cleaned from: %s to: %s", msgid, safemesgid);
+ }
+
+ return safemesgid;
+}
+
+
+/* Exim calls us here, feeds us a fd on the message body, and expects a return
+ message in *return_text */
+int local_scan(volatile int fd, uschar **return_text)
+{
+#warning you should not worry about the "might be clobbered by longjmp", see source
+ int ret;
+ ssize_t stret;
+ int pid;
+ int writefd[2];
+ int readfd[2];
+ char *spamc_argv[10];
+ int i;
+ /* These are the only values that we want working after the longjmp
+ * The automatic ones can be clobbered, but we don't really care */
+ volatile FILE *readfh;
+ volatile char *mesgfn=NULL;
+ volatile off_t fdsize;
+ volatile off_t scansize;
+ volatile off_t fdstart;
+ volatile char *rcptlist;
+ volatile void *old_sigchld;
+ char *safemesgid=NULL;
+ int isspam=0;
+ int gotsa=0;
+ int chunk;
+ off_t towrite;
+ char *mailinfo;
+ float spamvalue=0.0;
+ char *spamstatus=NULL;
+ time_t beforescan;
+ time_t afterscan;
+ time_t afterwait;
+ time_t scantime=0;
+ time_t fulltime=0;
+ struct stat stbuf;
+
+ uschar *expand;
+ header_line *hl;
+
+ static int readconffile=0;
+ static int wrotedebugenabled=0;
+
+ /* Options we read from /etc/exim4/sa-exim.conf */
+ static char *SAspamcpath=SPAMC_LOCATION;
+ static char *SAsafemesgidchars=SAFEMESGIDCHARS
+ static char *SAspamcSockPath=NULL;
+ static char *SAspamcPort="783";
+ static char *SAspamcHost="127.0.0.1";
+ static char *SAspamcUser=NULL;
+ static char *SAEximRunCond="0";
+ static char *SAEximRejCond="1";
+ static int SAmaxbody=250*1024;
+ static char *SATruncBodyCond="0";
+ static int SARewriteBody=0;
+ static int SAmaxarchivebody=20*1048576;
+ static int SAerrmaxarchivebody=1024*1048576;
+ static int SAmaxrcptlistlength=0;
+ static int SAaddSAEheaderBeforeSA=1;
+ static int SAtimeout=240;
+ static char *SAtimeoutsave=NULL;
+ static char *SAtimeoutSavCond="1";
+ static char *SAerrorsave=NULL;
+ static char *SAerrorSavCond="1";
+ static int SAtemprejectonerror=0;
+ static char *SAteergrube="1048576";
+ static float SAteergrubethreshold;
+ /* This is obsolete, since SAteergrube (now a condition) can do the same */
+ static char *SAteergrubecond="1";
+ static int SAteergrubetime=900;
+ static char *SAteergrubeSavCond="1";
+ static char *SAteergrubesave=NULL;
+ static int SAteergrubeoverwrite=1;
+ static char *SAdevnull="1048576";
+ static float SAdevnullthreshold;
+ static char *SAdevnullSavCond="1";
+ static char *SAdevnullsave=NULL;
+ static char *SApermreject="1048576";
+ static float SApermrejectthreshold;
+ static char *SApermrejectSavCond="1";
+ static char *SApermrejectsave=NULL;
+ static char *SAtempreject="1048576";
+ static float SAtemprejectthreshold;
+ static char *SAtemprejectSavCond="1";
+ static char *SAtemprejectsave=NULL;
+ static int SAtemprejectoverwrite=1;
+ static char *SAgreylistiswhitestr="GREYLIST_ISWHITE";
+ static float SAgreylistraisetempreject=3.0;
+ static char *SAspamacceptsave=NULL;
+ static char *SAspamacceptSavCond="0";
+ static char *SAnotspamsave=NULL;
+ static char *SAnotspamSavCond="0";
+ /* Those variables can take a %s to show the spam info */
+ static char *SAmsgteergrubewait="wait for more output";
+ static char *SAmsgteergruberej="Please try again later";
+ static char *SAmsgpermrej="Rejected";
+ static char *SAmsgtemprej="Please try again later";
+ /* Do not put a %s in there, or you'll segfault */
+ static char *SAmsgerror="Temporary local error while processing message, please contact postmaster";
+
+ /* New values we read from spamassassin */
+ char *xspamstatus=NULL;
+ char *xspamflag=NULL;
+
+
+ /* Any error can write the faulty message to mesgfn, so we need to
+ give it a value right now. We'll set the real value later */
+ /* message_id here comes from Exim, it's an internal disk Mesg-Id format
+ which doesn't correlate to the actual message's Mesg-Id. We shouldn't
+ need to clean it, and besides, SAsafemesgidchars hasn't been read from
+ the config file yet, but eh, safety is always a good thing, right? */
+ safemesgid=cleanmsgid(message_id, SAsafemesgidchars);
+ mesgfn=string_sprintf("%d_%s", time(NULL), safemesgid);
+
+ /* We won't scan local messages. I think exim bypasses local_scan for a
+ * bounce generated after a locally submitted message, but better be safe */
+ /* This is commented out now, because you can control it with SAEximRunCond
+ if (!sender_host_address)
+ {
+ return LOCAL_SCAN_ACCEPT;
+ }
+ */
+
+ /* If you discard a mail with exim ACLs, we get 0 recipients, so let's just
+ * accept the mail, which won't matter either way since it'll get dropped
+ * (thanks to John Horne for reporting this corner case) */
+ if (recipients_count == 0)
+ {
+ return LOCAL_SCAN_ACCEPT;
+ }
+
+ /*
+ * We keep track of whether we've alrady read the config file, but since
+ * exim spawns itself, it will get read by exim children even though you
+ * didn't restart exim. That said, after you change the config file, you
+ * should restart exim to make sure all the instances pick up the new
+ * config file
+ */
+ if (!readconffile)
+ {
+ ret=open(conffile, 0);
+ CHECKERR(ret,string_sprintf("conf file open for %s", conffile),__LINE__);
+ readfh=fdopen(ret, "r");
+ CHECKERR(readfh,"fdopen",__LINE__);
+
+ while ((fgets((char *)buffer, sizeof(buffera), (FILE *)readfh)) != NULL)
+ {
+ if (*buffer == '#' || *buffer == '\n' )
+ {
+ continue;
+ }
+
+ if (*buffer != 'S' || *(buffer+1) != 'A')
+ {
+ log_write(0, LOG_MAIN, "SA: Warning: error while reading configuration file %s. Line does not begin with a SA directive: '%s', ignoring", conffile, buffer);
+ continue;
+ }
+
+#define M_CHECKFORVAR(VAR, TYPE) \
+ if (strstr(buffer, #VAR ": ") == buffer) \
+ { \
+ if (sscanf(buffer, #VAR ": " TYPE, &VAR)) \
+ { \
+ if (SAEximDebug > 3) \
+ { \
+ if (SAEximDebug && ! wrotedebugenabled) \
+ { \
+ log_write(0, LOG_MAIN, "SA: Debug4: Debug enabled, reading config from file %s", conffile); \
+ wrotedebugenabled=1; \
+ } \
+ else \
+ { \
+ log_write(0, LOG_MAIN, "SA: Debug4: config read " #VAR " = " TYPE, VAR); \
+ }\
+ }\
+ } \
+ else \
+ { \
+ log_write(0, LOG_MAIN, "SA: Warning: error while reading configuration file %s. Can't parse value in: '%s', ignoring", conffile, buffer); \
+ } \
+ continue; \
+ }
+
+#define M_CHECKFORSTR(VAR) \
+ if (strstr(buffer, #VAR ": ") == buffer) \
+ { \
+ VAR = strdup(buffer+strlen( #VAR )+2); \
+ if (VAR == NULL) \
+ { \
+ log_write(0, LOG_MAIN, "SA: PANIC: malloc failed, quitting..."); \
+ exit(-1); \
+ } \
+ \
+ if (VAR[strlen(VAR)-1] == '\n') \
+ { \
+ VAR[strlen(VAR)-1]=0; \
+ } \
+ if (SAEximDebug > 3) \
+ { \
+ log_write(0, LOG_MAIN, "SA: Debug4: config read " #VAR " = %s", VAR); \
+ } \
+ continue; \
+ }
+
+ M_CHECKFORVAR(SAEximDebug, "%d");
+ M_CHECKFORSTR(SAspamcpath);
+ M_CHECKFORSTR(SAsafemesgidchars);
+ M_CHECKFORSTR(SAspamcSockPath);
+ M_CHECKFORSTR(SAspamcPort);
+ M_CHECKFORSTR(SAspamcHost);
+ M_CHECKFORSTR(SAspamcUser);
+ M_CHECKFORSTR(SAEximRunCond);
+ M_CHECKFORSTR(SAEximRejCond);
+ M_CHECKFORVAR(SAmaxbody, "%d");
+ M_CHECKFORSTR(SATruncBodyCond);
+ M_CHECKFORVAR(SARewriteBody, "%d");
+ M_CHECKFORVAR(SAPrependArchiveWithFrom, "%d");
+ M_CHECKFORVAR(SAmaxarchivebody, "%d");
+ M_CHECKFORVAR(SAerrmaxarchivebody, "%d");
+ M_CHECKFORVAR(SAmaxrcptlistlength, "%d");
+ M_CHECKFORVAR(SAaddSAEheaderBeforeSA, "%d");
+ M_CHECKFORVAR(SAtimeout, "%d");
+ M_CHECKFORSTR(SAtimeoutsave);
+ M_CHECKFORSTR(SAtimeoutSavCond);
+ M_CHECKFORSTR(SAerrorsave);
+ M_CHECKFORSTR(SAerrorSavCond);
+ M_CHECKFORVAR(SAtemprejectonerror, "%d");
+ M_CHECKFORSTR(SAteergrube);
+ M_CHECKFORSTR(SAteergrubecond);
+ M_CHECKFORVAR(SAteergrubetime, "%d");
+ M_CHECKFORSTR(SAteergrubeSavCond);
+ M_CHECKFORSTR(SAteergrubesave);
+ M_CHECKFORVAR(SAteergrubeoverwrite, "%d");
+ M_CHECKFORSTR(SAdevnull);
+ M_CHECKFORSTR(SAdevnullSavCond);
+ M_CHECKFORSTR(SAdevnullsave);
+ M_CHECKFORSTR(SApermreject);
+ M_CHECKFORSTR(SApermrejectsave);
+ M_CHECKFORSTR(SApermrejectSavCond);
+ M_CHECKFORSTR(SAtempreject);
+ M_CHECKFORSTR(SAtemprejectSavCond);
+ M_CHECKFORSTR(SAtemprejectsave);
+ M_CHECKFORVAR(SAtemprejectoverwrite, "%d");
+ M_CHECKFORSTR(SAgreylistiswhitestr);
+ M_CHECKFORVAR(SAgreylistraisetempreject, "%f");
+ M_CHECKFORSTR(SAspamacceptsave);
+ M_CHECKFORSTR(SAspamacceptSavCond);
+ M_CHECKFORSTR(SAnotspamsave);
+ M_CHECKFORSTR(SAnotspamSavCond);
+ M_CHECKFORSTR(SAmsgteergrubewait);
+ M_CHECKFORSTR(SAmsgteergruberej);
+ M_CHECKFORSTR(SAmsgpermrej);
+ M_CHECKFORSTR(SAmsgtemprej);
+ M_CHECKFORSTR(SAmsgerror);
+
+
+ }
+
+ readconffile=1;
+ }
+
+#define M_CONDTOFLOAT(VAR) \
+ if ((expand=expand_string( VAR )) == NULL) \
+ { \
+ PANIC(string_sprintf(#VAR " config expansion failure on %s", #VAR ));\
+ } \
+ sscanf(expand, "%f", &VAR ## threshold); \
+ if (SAEximDebug > 2) \
+ { \
+ log_write(0, LOG_MAIN, "SA: Debug3: expanded " #VAR " = %.2f", VAR ## threshold); \
+ }\
+
+ M_CONDTOFLOAT(SAteergrube);
+ M_CONDTOFLOAT(SAdevnull);
+ M_CONDTOFLOAT(SApermreject);
+ M_CONDTOFLOAT(SAtempreject);
+
+ /* Initialize the list of recipients here */
+ rcptlist=string_copy(recipients_list[0].address);
+ for (i=1; i < recipients_count && strlen((char *)rcptlist) < 7998 - strlen(recipients_list[i].address); i++)
+ {
+ rcptlist=string_sprintf("%s, %s", rcptlist, recipients_list[i].address);
+ }
+
+ if (sender_host_address != NULL)
+ {
+ mailinfo=string_sprintf("From <%s> (host=%s [%s]) for",
+ sender_address, sender_host_name, sender_host_address);
+ }
+ else
+ {
+ mailinfo=string_sprintf("From <%s> (local) for", sender_address);
+ }
+ mailinfo=string_sprintf("%s %s", mailinfo, rcptlist);
+
+
+ /* Remove SA-Exim headers that could have been set before we add ours*/
+ RemoveHeaders("X-SA-Exim-");
+
+ if(SAaddSAEheaderBeforeSA)
+ {
+ AddSAEheaders((char *)rcptlist, SAmaxrcptlistlength);
+ }
+
+ /* This is used later if we need to rewind and save the body elsewhere */
+ fdstart=lseek(fd, 0, SEEK_CUR);
+ CHECKERR(fdstart,"lseek SEEK_CUR",__LINE__);
+
+ ret=fstat(fd, &stbuf);
+ CHECKERR(ret,"fstat fd",__LINE__);
+ /* this is the body size plus a few bytes (exim msg ID) */
+ /* it should be 18 bytes, but I'll assume it could be more or less */
+ fdsize=stbuf.st_size;
+
+ if (SAEximDebug > 3)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug4: Message body is about %.0f bytes and the initial offset is %.0f", (double)(fdsize-18), (double)fdstart);
+ }
+
+ if (fdsize > SAmaxbody)
+ {
+ if (SATruncBodyCond[0] != '1' || SATruncBodyCond[1] != 0)
+ {
+ expand=expand_string(SATruncBodyCond);
+ if (expand == NULL)
+ {
+ PANIC(string_sprintf("SATruncBodyCond expansion failure on %s", SATruncBodyCond));
+ }
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: SATruncBodyCond expand returned: '%s'", expand);
+ }
+
+ if (expand[0] == 0 || (expand[0] == '0' && expand[1] == 0))
+ {
+ log_write(0, LOG_MAIN, "SA: Action: check skipped due to message size (%.0f bytes) and SATruncBodyCond expanded to false (Message-Id: %s). %s", (double)(fdsize-18), safemesgid, mailinfo);
+ header_add(' ', "X-SA-Exim-Scanned: No (on %s); Message bigger than SAmaxbody (%d)\n", primary_hostname, SAmaxbody);
+ return LOCAL_SCAN_ACCEPT;
+ }
+ }
+
+ if (SAEximDebug > 1)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug2: Message body is about %.0f bytes and SATruncBodyCond expanded to true, will feed a truncated body to SA", (double)(fdsize-18));
+ }
+
+ /* Let's feed exactly spamc will accept */
+ scansize=SAmaxbody;
+ header_add(' ', "X-SA-Exim-Scan-Truncated: Fed %.0f bytes of the body to SA instead of %.0f\n", (double)scansize, (double)fdsize);
+ }
+ else
+ {
+ scansize=fdsize;
+ }
+
+ expand=expand_string(SAEximRunCond);
+ if (expand == NULL)
+ {
+ PANIC(string_sprintf("SAEximRunCond expansion failure on %s", SAEximRunCond));
+ }
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: SAEximRunCond expand returned: '%s'", expand);
+ }
+
+
+ /* Bail from SA if the expansion string says so */
+ if (expand[0] == 0 || (expand[0] == '0' && expand[1] == 0))
+ {
+ log_write(0, LOG_MAIN, "SA: Action: Not running SA because SAEximRunCond expanded to false (Message-Id: %s). %s", safemesgid, mailinfo);
+ header_add(' ', "X-SA-Exim-Scanned: No (on %s); SAEximRunCond expanded to false\n", primary_hostname);
+ return LOCAL_SCAN_ACCEPT;
+ }
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: check succeeded, running spamc");
+ }
+
+ /* Ok, so now that we know we're running SA, we remove the X-Spam headers */
+ /* that might have been there */
+ RemoveHeaders("X-Spam-");
+
+
+ beforescan=time(NULL);
+ /* Fork off spamc, and get ready to talk to it */
+ ret=pipe(writefd);
+ CHECKERR(ret,"write pipe",__LINE__);
+ ret=pipe(readfd);
+ CHECKERR(ret,"read pipe",__LINE__);
+
+ /* Ensure that SIGCHLD isn't being ignored. */
+ old_sigchld = signal(SIGCHLD, SIG_DFL);
+
+ if ((pid=fork()) < 0)
+ {
+ CHECKERR(pid, "fork", __LINE__ - 1);
+ }
+
+ if (pid == 0)
+ {
+ close(readfd[0]);
+ close(writefd[1]);
+
+ ret=dup2(writefd[0],0);
+ CHECKERR(ret,"dup2 stdin",__LINE__);
+ ret=dup2(readfd[1],1);
+ CHECKERR(ret,"dup2 stdout",__LINE__);
+ ret=dup2(readfd[1],2);
+ CHECKERR(ret,"dup2 stderr",__LINE__);
+
+ i = 0;
+ spamc_argv[i++] = "spamc";
+ if (SAspamcUser && SAspamcUser[0])
+ {
+ expand=expand_string(SAspamcUser);
+ if (expand == NULL)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "SA: SAspamcUser expansion failure on %s, will run as Exim user instead.", SAspamcUser);
+ }
+ else if (expand[0] != '\0')
+ {
+ spamc_argv[i++] = "-u";
+ spamc_argv[i++] = expand;
+ }
+ }
+
+ /*
+ * I could implement the spamc protocol and talk to spamd directly
+ * instead of forking spamc, but considering the overhead spent
+ * in spamd, forking off spamc seemed acceptable rather than
+ * re-implementing and tracking the spamc/spamd protocol or linking
+ * with a possibly changing library
+ */
+ /* Ok, we cheat, spamc cares about how big the whole message is and
+ * we only know about the body size, so I'll give an extra 16K
+ * to account for any headers that can accompany the message */
+
+ spamc_argv[i++] = "-s";
+ spamc_argv[i++] = string_sprintf("%d", SAmaxbody+16384);
+
+ if(SAspamcSockPath)
+ {
+ spamc_argv[i++] = "-U";
+ spamc_argv[i++] = SAspamcSockPath;
+ }
+ else
+ {
+ spamc_argv[i++] = "-d";
+ spamc_argv[i++] = SAspamcHost;
+ spamc_argv[i++] = "-p";
+ spamc_argv[i++] = SAspamcPort;
+ }
+ spamc_argv[i++] = NULL;
+
+ ret=execv(SAspamcpath, spamc_argv);
+ CHECKERR(ret,string_sprintf("exec %s", SAspamcpath),__LINE__);
+ }
+
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: forked spamc");
+ }
+
+ ret=close(readfd[1]);
+ CHECKERR(ret,"close r",__LINE__);
+ ret=close(writefd[0]);
+ CHECKERR(ret,"close w",__LINE__);
+ readfh=fdopen(readfd[0], "r");
+
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: closed filehandles");
+ }
+
+ /* Ok, we're ready for spewing the mail at spamc */
+ /* First we need to get the header lines from exim, and then we can read
+ the body from fd */
+ hl=header_list;
+ while (hl != NULL)
+ {
+ /* type '*' means the header is internal, don't print it */
+ if (hl->type == '*')
+ {
+ hl=hl->next;
+ continue;
+ }
+
+ stret=write(writefd[1],hl->text,strlen(hl->text));
+ CHECKERR(stret,"header line write",__LINE__);
+
+ hl=hl->next;
+ }
+ stret=write(writefd[1],"\n",1);
+ CHECKERR(stret,"header separation write",__LINE__);
+
+ if (SAEximDebug > 6)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug7: sent headers to spamc pipe. Sending body...");
+ }
+
+ towrite=scansize;
+ chunk=0;
+ while (towrite>0 && (stret=read(fd, buffer, MIN(sizeof(buffera), towrite))) > 0)
+ {
+ chunk++;
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: spamc body going to write chunk %d (read %.0f, %.0f left to write)", chunk, (double)stret, (double)towrite);
+ }
+ towrite-=stret;
+ stret=write(writefd[1], buffer, stret);
+ CHECKERR(stret,"body write in",__LINE__);
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: Spamc body wrote chunk %d (wrote %.0f, %.0f left to write)", chunk, (double)stret, (double)towrite);
+ }
+ }
+ CHECKERR(stret, "read body", __LINE__ - 14);
+ close(writefd[1]);
+
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: fed spam to spamc, reading result");
+ }
+
+ if (SAtimeout)
+ {
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: Setting timeout of %d secs before reading from spamc", SAtimeout);
+ }
+ /* SA can take very long to run for various reasons, let's not wait
+ * forever, that's just bad at SMTP time */
+ if (setjmp(jmp_env) == 0)
+ {
+ signal(SIGALRM, alarm_handler);
+ alarm (SAtimeout);
+ }
+ else
+ {
+ /* Make sure that all your variables here are volatile or static */
+ signal(SIGCHLD, old_sigchld);
+ fclose((FILE *)readfh);
+
+ header_add(' ', "X-SA-Exim-Scanned: No (on %s); SA Timed out after %d secs\n", primary_hostname, SAtimeout);
+
+ /* We sent it to LOG_REJECT too so that we get a header dump */
+ log_write(0, LOG_MAIN | LOG_REJECT, "SA: Action: spamd took more than %d secs to run, accepting message (scanned in %d/%d secs | Message-Id: %s). %s", SAtimeout, scantime, fulltime, safemesgid, mailinfo);
+
+ ret=savemail(fd, fdstart, SAtimeoutsave, "SAtimeoutsave", (char *)mesgfn, SAerrmaxarchivebody, SAtimeoutSavCond);
+ CHECKERR(ret,where,line);
+
+ /* Make sure we kill spamc in case SIGPIPE from fclose didn't */
+ kill(pid, SIGTERM);
+ return LOCAL_SCAN_ACCEPT;
+
+ }
+ }
+
+ /* Let's see what SA has to tell us about this mail and store the headers */
+ while ((fgets((char *)buffer,sizeof(buffera),(FILE *) readfh)) != NULL)
+ {
+ /* Remove trailing newline */
+ if (buffer[strlen(buffer)-1] == '\n')
+ {
+ buffer[strlen(buffer)-1]=0;
+ }
+restart:
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: spamc read: %s", buffer);
+ }
+
+ /* Let's handle special multi-line headers first, what a pain... */
+ /* We feed the one line we read and the filehandle because we'll need
+ to check whether more lines need to be concatenated */
+ /* This is ugly, there is an order dependency so we return to the
+ beginning of the loop without reading a new line since we already
+ did that */
+ if (parsemlheader(buffer, (FILE *)readfh, "Subject", NULL)) goto restart;
+ if ((SARewriteBody == 1) && parsemlheader(buffer, (FILE *)readfh, "Content-Type", NULL)) goto restart;
+ if ((SARewriteBody == 1) && parsemlheader(buffer, (FILE *)readfh, "Content-Transfer-Encoding", NULL)) goto restart;
+
+ if (parsemlheader(buffer, (FILE *)readfh, "X-Spam-Flag", &xspamflag))
+ {
+ if (xspamflag[13] == 'Y')
+ {
+ isspam=1;
+ }
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: isspam read from X-Spam-Flag: %d", isspam);
+ }
+ goto restart;
+ }
+
+ if (parsemlheader(buffer, (FILE *)readfh, "X-Spam-Status", &xspamstatus))
+ {
+ char *start;
+ char *end;
+
+ gotsa=1;
+
+ /* if we find the preconfigured greylist string (and it is defined
+ * in sa-exim.conf), we can raise the threshold for tempreject just
+ * for this mail, since it's been whitelisted */
+ if (SAgreylistiswhitestr && strstr(xspamstatus, SAgreylistiswhitestr))
+ {
+ SAtemprejectthreshold+=SAgreylistraisetempreject;
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: read %s string, SAtempreject is now changed to %f", SAgreylistiswhitestr, SAtemprejectthreshold);
+ }
+ }
+ else
+ {
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: did not find read GREYLIST_ISWHITE string in X-Spam-Status");
+ }
+ }
+
+ start=strstr(xspamstatus, "hits=");
+ /* Support SA 3.0 format */
+ if (start == NULL)
+ {
+ start=strstr(xspamstatus, "score=");
+ }
+
+ end=strstr(xspamstatus, " tests=");
+ if (end == NULL)
+ {
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: Could not find old spamstatus format, trying new one...");
+ }
+ end=strstr(xspamstatus, "\n tests=");
+ }
+ if (start!=NULL && end!=NULL)
+ {
+ spamstatus=string_copyn(start, end-start);
+ if (SAEximDebug > 2)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug3: Read from X-Spam-Status: %s", spamstatus);
+ }
+ }
+ else
+ {
+ PANIC(string_sprintf("SA: could not parse X-Spam-Status: to extract hits and required. Bad!. Got: '%s'", xspamstatus));
+ }
+
+ start=strstr(spamstatus, "=");
+ end=strstr(spamstatus, " ");
+ if (start!=NULL && end!=NULL)
+ {
+ start++;
+ sscanf(start, "%f", &spamvalue);
+ }
+ else
+ {
+ PANIC(string_sprintf("SA: spam value extract failed in '%s'. Bad!", xspamstatus));
+ }
+
+ goto restart;
+ }
+
+ if (parsemlheader(buffer, (FILE *)readfh, "X-Spam-", NULL)) goto restart;
+
+ /* Ok, now we can do normal processing */
+
+ /* If no more headers here, we're done */
+ if (buffer[0] == 0)
+ {
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: spamc read got newline, end of headers", buffer);
+ }
+ goto exit;
+ }
+
+ if (compare_header(buffer, "Message-Id: "))
+ {
+ char *start;
+ char *end;
+ char *mesgid=NULL;
+
+ start=strchr(buffer, '<');
+ end=strchr(buffer, '>');
+
+ if (start == NULL || end == NULL)
+ {
+ /* we keep the default mesgfn (unix date in seconds) */
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: Could not get Message-Id from %s", buffer);
+ }
+ }
+ else if ((mesgid=string_copyn(start+1,end-start-1)) && mesgid[0])
+ {
+ /* We replace the exim Message-ID with the one read from
+ the message * as we use this to detect dupes when we
+ send 45x and get the same * message multiple times */
+ safemesgid=cleanmsgid(mesgid, SAsafemesgidchars);
+ mesgfn=string_sprintf("%d_%s", time(NULL), safemesgid);
+
+ if (SAEximDebug > 5)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug6: Message-Id received and cleaned as: %s", safemesgid);
+ }
+ }
+ continue;
+ }
+ }
+
+ exit:
+
+
+ if (isspam && SARewriteBody == 1)
+ {
+ int line;
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: SARewriteBody == 1, rewriting message body");
+ }
+
+ /* already read from fd? Better reset it... */
+ ret=lseek(fd, fdstart, SEEK_SET);
+ CHECKERR(ret, "lseek reset on spooled message", __LINE__);
+
+ line=1;
+ while ((fgets((char *)buffer,sizeof(buffera),(FILE *) readfh)) != NULL)
+ {
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: Read body from SA; line %d (read %d)", line, strlen(buffer));
+ }
+
+ stret=write(fd, buffer, strlen(buffer));
+ CHECKERR(stret,string_sprintf("SA body write to msg"),__LINE__);
+ if (SAEximDebug > 8)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug9: Wrote to msg; line %d (wrote %d)", line, ret);
+ }
+ if (buffer[strlen(buffer)-1] == '\n')
+ {
+ line++;
+ }
+ }
+
+ if (SAEximDebug > 1)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug2: body_linecount before SA: %d", body_linecount);
+ }
+
+ /* update global variable $body_linecount to reflect the new body size*/
+ body_linecount = (line - 1);
+
+ if (SAEximDebug > 1)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug2: body_linecount after SA: %d", body_linecount);
+ }
+ }
+
+ fclose((FILE *)readfh);
+
+ afterscan=time(NULL);
+ scantime=afterscan-beforescan;
+
+ wait(&ret);
+ signal(SIGCHLD, old_sigchld);
+
+ if (ret)
+ {
+ sprintf(buffer, "%d", ret);
+ PANIC(string_sprintf("wait on spamc child yielded, %s", buffer));
+ }
+
+ afterwait=time(NULL);
+ fulltime=afterwait-beforescan;
+
+ if(!SAaddSAEheaderBeforeSA)
+ {
+ AddSAEheaders((char *)rcptlist, SAmaxrcptlistlength);
+ }
+
+ header_add(' ', "X-SA-Exim-Version: %s\n",version);
+
+ if (gotsa == 0)
+ {
+ header_add(' ', "X-SA-Exim-Scanned: No (on %s); Unknown failure\n", primary_hostname);
+ log_write(0, LOG_MAIN, "SA: Action: SA didn't successfully run against message, accepting (time: %d/%d secs | Message-Id: %s). %s", scantime, fulltime, safemesgid, mailinfo);
+ return LOCAL_SCAN_ACCEPT;
+ }
+
+ header_add(' ', "X-SA-Exim-Scanned: Yes (on %s)\n", primary_hostname);
+
+ if (spamstatus == NULL)
+ {
+ spamstatus = (char *) nospamstatus;
+ }
+ if (isspam)
+ {
+ int dorej=1;
+ int doteergrube=0;
+
+ if (SAEximRejCond[0] != '1' || SAEximRejCond[1] != 0)
+ {
+ expand=expand_string(SAEximRejCond);
+ if (expand == NULL)
+ {
+ PANIC(string_sprintf("SAEximRejCond expansion failure on %s", SAEximRejCond));
+ }
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: SAEximRejCond expand returned: '%s'", expand);
+ }
+
+ if (expand[0] == 0 || (expand[0] == '0' && expand[1] == 0))
+ {
+ log_write(0, LOG_MAIN, "SA: Notice: SAEximRejCond expanded to false, not applying reject rules");
+ dorej=0;
+ }
+ }
+
+ if (dorej && spamvalue >= SAteergrubethreshold)
+ {
+ doteergrube=1;
+ if (SAteergrubecond[0] != '1' || SAteergrubecond[1] != 0)
+ {
+ expand=expand_string(SAteergrubecond);
+ if (expand == NULL)
+ {
+ PANIC(string_sprintf("SAteergrubecond expansion failure on %s", SAteergrubecond));
+ }
+
+ if (SAEximDebug)
+ {
+ log_write(0, LOG_MAIN, "SA: Debug: SAteergrubecond expand returned: '%s'", expand);
+ }
+
+ if (expand[0] == 0 || (expand[0] == '0' && expand[1] == 0))
+ {
+ log_write(0, LOG_MAIN, "SA: Notice: SAteergrubecond expanded to false, not teergrubing known peer");
+ doteergrube=0;
+ }
+ }
+ }
+
+ if (dorej && doteergrube)
+ {
+ /* By default, we'll only save temp bounces by message ID so
+ * that when the same message is submitted several times, we
+ * overwrite the same file on disk and not create a brand new
+ * one every single time */
+ if (SAteergrubeoverwrite)
+ {
+ ret=savemail(fd, fdstart, SAteergrubesave, "SAteergrubesave", safemesgid, SAmaxarchivebody, SAteergrubeSavCond);
+ CHECKERR(ret,where,line);
+ }
+ else
+ {
+ ret=savemail(fd, fdstart, SAteergrubesave, "SAteergrubesave", (char *)mesgfn, SAmaxarchivebody, SAteergrubeSavCond);
+ CHECKERR(ret,where,line);
+ }
+
+ spamstatus=string_sprintf("%s trigger=%.1f", spamstatus, SAteergrubethreshold);
+ /* Exim might want to stop us if we run for too long, but that's
+ * exactly what we're trying to do, so let's override that */
+ alarm(0);
+
+ for (i=0;i<SAteergrubetime/10;i++)
+ {
+ char *str;
+
+ /* Unfortunately, we can't use exim's smtp_printf because it
+ * doesn't return an error code if the write gets an EPIPE.
+ * So, we write ourselves, but this won't work if you have a
+ * TLS connection opened (that said, if you are teergrubing
+ * a TLS connection, it's probably a relay host, not a
+ * spammer, and in this case you should not teergrube a
+ * friendly relay, so basically we should be ok).
+ * If you do teergrube an SSL connection with the current
+ * code, you will break it, but that's acceptable */
+ str=string_sprintf(string_sprintf("451- %s\r\n",SAmsgteergrubewait), spamstatus);
+ fprintf(smtp_out, str);
+ ret=fflush(smtp_out);
+ if (ret != 0)
+ {
+ log_write(0, LOG_MAIN | LOG_REJECT, "SA: Action: teergrubed sender for %d secs until it closed the connection: %s (scanned in %d/%d secs | Message-Id: %s). %s", i*10, spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ /* The other side closed the connection, nothing to print */
+ *return_text="";
+ return LOCAL_SCAN_TEMPREJECT_NOLOGHDR;
+ }
+ sleep(10);
+ }
+
+ log_write(0, LOG_MAIN | LOG_REJECT, "SA: Action: teergrubed sender until full configured duration of %d secs: %s (scanned in %d/%d secs | Message-Id: %s). %s", SAteergrubetime, spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ *return_text=string_sprintf(SAmsgteergruberej, spamstatus);
+ return LOCAL_SCAN_TEMPREJECT_NOLOGHDR;
+ }
+ else if (dorej && spamvalue >= SAdevnullthreshold)
+ {
+ ret=savemail(fd, fdstart, SAdevnullsave, "SAdevnullsave", (char *)mesgfn, SAmaxarchivebody, SAdevnullSavCond);
+ CHECKERR(ret,where,line);
+
+ recipients_count=0;
+ spamstatus=string_sprintf("%s trigger=%.1f", spamstatus, SAdevnullthreshold);
+ log_write(0, LOG_REJECT | LOG_MAIN, "SA: Action: silently tossed message: %s (scanned in %d/%d secs | Message-Id: %s). %s", spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ return LOCAL_SCAN_ACCEPT;
+ }
+ else if (dorej && spamvalue >= SApermrejectthreshold)
+ {
+ ret=savemail(fd, fdstart, SApermrejectsave, "SApermrejectsave", (char *)mesgfn, SAmaxarchivebody, SApermrejectSavCond);
+ CHECKERR(ret,where,line);
+
+ spamstatus=string_sprintf("%s trigger=%.1f", spamstatus, SApermrejectthreshold);
+ log_write(0, LOG_MAIN | LOG_REJECT, "SA: Action: permanently rejected message: %s (scanned in %d/%d secs | Message-Id: %s). %s", spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ *return_text=string_sprintf(SAmsgpermrej, spamstatus);
+ return LOCAL_SCAN_REJECT_NOLOGHDR;
+ }
+ else if (dorej && spamvalue >= SAtemprejectthreshold)
+ {
+ /* Yeah, gotos are harmful, but that'd be a function with a lot
+ * of options to send, so, here's a small shortcut */
+ goto dotempreject;
+ }
+ else
+ {
+ ret=savemail(fd, fdstart, SAspamacceptsave, "SAspamacceptsave", (char *)mesgfn, SAmaxarchivebody, SAspamacceptSavCond);
+ CHECKERR(ret,where,line);
+ log_write(0, LOG_MAIN, "SA: Action: flagged as Spam but accepted: %s (scanned in %d/%d secs | Message-Id: %s). %s", spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ return LOCAL_SCAN_ACCEPT;
+ }
+ }
+ else
+ {
+ /* This is an exception to the rule, for grey listing, we allow for
+ * sending back a tempreject on SA scores that aren't considered as
+ * spam (greylisting is now done directly in spamassassin though */
+ if (spamvalue >= SAtemprejectthreshold)
+ {
+ dotempreject:
+
+ /* By default, we'll only save temp bounces by message ID so
+ * that when the same message is submitted several times, we
+ * overwrite the same file on disk and not create a brand new
+ * one every single time */
+ if (SAtemprejectoverwrite)
+ {
+ ret=savemail(fd, fdstart, SAtemprejectsave, "SAtemprejectsave", safemesgid, SAmaxarchivebody, SAtemprejectSavCond);
+ CHECKERR(ret,where,line);
+ }
+ else
+ {
+ ret=savemail(fd, fdstart, SAtemprejectsave, "SAtemprejectsave", (char *)mesgfn, SAmaxarchivebody, SAtemprejectSavCond);
+ CHECKERR(ret,where,line);
+ }
+
+ spamstatus=string_sprintf("%s trigger=%.1f", spamstatus, SAtemprejectthreshold);
+ log_write(0, LOG_MAIN | LOG_REJECT, "SA: Action: temporarily rejected message: %s (scanned in %d/%d secs | Message-Id: %s). %s", spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ *return_text=string_sprintf(SAmsgtemprej, spamstatus);
+ return LOCAL_SCAN_TEMPREJECT_NOLOGHDR;
+ }
+ else
+ {
+ ret=savemail(fd, fdstart, SAnotspamsave, "SAnotspamsave", (char *)mesgfn, SAmaxarchivebody, SAnotspamSavCond);
+ CHECKERR(ret,where,line);
+ log_write(0, LOG_MAIN, "SA: Action: scanned but message isn't spam: %s (scanned in %d/%d secs | Message-Id: %s). %s", spamstatus, scantime, fulltime, safemesgid, mailinfo);
+ return LOCAL_SCAN_ACCEPT;
+ }
+ }
+
+
+
+ errexit:
+ if (SAtemprejectonerror)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "SA: PANIC: Unexpected error on %s, file "__FILE__", line %d: %s", where, line-1, strerror(errno));
+ }
+ else
+ {
+ log_write(0, LOG_MAIN, "SA: PANIC: Unexpected error on %s (but message was accepted), file "__FILE__", line %d: %s", where, line-1, strerror(errno));
+ }
+
+ header_add(' ', "X-SA-Exim-Scanned: No (on %s); Exit with error (see exim mainlog)\n", primary_hostname);
+
+ ret=savemail(fd, fdstart, SAerrorsave, "SAerrorsave", (char *)mesgfn, SAerrmaxarchivebody, SAerrorSavCond);
+ if (ret < 0)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "SA: PANIC: Error in error handler while trying to save mail to %s, file "__FILE__", line %d: %s", string_sprintf("%s/%s", SAerrorsave, mesgfn), __LINE__ - 3, strerror(errno));
+ }
+
+ if (SAtemprejectonerror)
+ {
+ *return_text=SAmsgerror;
+ return LOCAL_SCAN_TEMPREJECT_NOLOGHDR;
+ }
+ else
+ {
+ return LOCAL_SCAN_ACCEPT;
+ }
+
+
+ panicexit:
+ if (SAtemprejectonerror)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "SA: PANIC: %s", panicerror);
+ }
+ else
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "SA: PANIC: %s (but message was accepted)", panicerror);
+ }
+
+ header_add(' ', "X-SA-Exim-Scanned: No (on %s); Panic (see exim mainlog)\n", primary_hostname);
+
+ ret=savemail(fd, fdstart, SAerrorsave, "SAerrorsave", (char *)mesgfn, SAerrmaxarchivebody, SAerrorSavCond);
+ if (ret < 0)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC , "SA: PANIC: Error in error handler while trying to save mail to %s, file "__FILE__", line %d: %s", string_sprintf("%s/%s", SAerrorsave, mesgfn), __LINE__ - 3, strerror(errno));
+ }
+
+ if (SAtemprejectonerror)
+ {
+ *return_text=SAmsgerror;
+ return LOCAL_SCAN_TEMPREJECT_NOLOGHDR;
+ }
+ else
+ {
+ return LOCAL_SCAN_ACCEPT;
+ }
+}
Index: 4.2.1-7/sa-exim.conf
===================================================================
--- 4.2.1-7/sa-exim.conf (nonexistent)
+++ 4.2.1-7/sa-exim.conf (revision 23)
@@ -0,0 +1,376 @@
+# Options for spamassassin running in exim's local_scan (SA Exim)
+# By Marc MERLIN <marc_soft@merlins.org> - Initial version: April 2002
+# Sander Smeenk <ssmeenk@freshdot.net> - Improvements: March 2004
+#
+# Sample file version 1.16 for SA-Exim 4.1 - 2005/01/10
+#
+# The parse routine is minimalistic. It expects "option: value" (exactly
+# one space after the colon, and none before). You should put long lines
+# on one line. The parser isn't capable of parsing multiline values.
+#
+# SA threshold values are parsed as floats and other numerical options
+# are ints. String options have to be set. To unset them, comment out the
+# variable, don't set it to nothing.
+#
+# READ THIS:
+# ---------
+# Watch your logs, you will get errors and your messages will get
+# temporarily bounced if expansions fail. Watch your logs!
+#
+# If you are afraid that spammers might use a header that is used here
+# as a default, have exim set it to another value than 'Yes' and check
+# here for that other value.
+#
+# For every expansion, anything that doesn't expand to "" or "0"
+# (without quotes) will be considered true. If you set the string to 1,
+# it will be true without going through exim's condition evaluator (and
+# if you leave it unset, it will default to 0)
+#
+# You should not put double quotes around expressions!
+# --- snip ---
+
+# Enable basic verbose output by default. Watch your logs!
+SAEximDebug: 1
+
+
+# Default path is /usr/bin/spamc, but you can change it here
+SAspamcpath: /usr/bin/spamc
+
+# Which characters are retained from a Message-Id header (for safety, we
+# remove characters that might cause problems with shell parsing)
+# Change the default at your own risk (you also have to change this in
+# the SA greylisting patch if you use that)
+#SAsafemesgidchars: !#%( )*+,-.0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~
+
+# If SAspamcSockPath is set spamc uses socket to connect to spamd,
+# use --socketpath pathname as argument to spamd (new in SA 2.60).
+# Leave it unset if you want spamc to connect(AF_INET) to spamd at
+# 127.0.0.1 (this is the default shown in the options below), but if
+# you set it, it will override the two TCP connect options below
+#SAspamcSockPath: /var/run/spamd.sock
+
+# SAspamcHost / SAspamcPort: TCP socket where your spamd is listening
+# Shown below are the defaults:
+SAspamcHost: 127.0.0.1
+SAspamcPort: 783
+
+# SAspamcUser: The username passed to spamc. Some tricks are needed to
+# decide on one user when there are many recipients. This string is of
+# course expanded. If unset or empty, spamc will use the user Exim
+# runs as. We suggest that you decide what username to use in the ACLs
+# and set an ACL variable.
+#SAspamcUser: $acl_m2
+
+# Exim configuration string to run before running SA against the message
+# This decides whether SA gets run against the message or not. This
+# default will not reject messages if the message had SA headers but
+# they weren't added by us.
+SAEximRunCond: ${if and {{def:sender_host_address} {!eq {$sender_host_address}{127.0.0.1}} {!eq {$sender_host_address}{::1}}}}
+# If you want more detailed control over when to run SA, it's recommended
+# that you set an ACL variable indicating this from the acl section of
+# your Exim configuration file. The current maintainer sets acl_m0 to
+# "noscan" if the sending host is localhost or has authenticated.
+#SAEximRunCond: ${if !eq{$acl_m0}{noscan}}
+# (This means exactly the same as ${if !eq{$acl_m0}{noscan} {true}{}},
+# where the empty string is considered false.)
+
+#----------------------------------------------------------------------
+# Remove or comment out the following line to enable sa-exim
+SAEximRunCond: 0
+#----------------------------------------------------------------------
+
+# If and only if SAEximRunCond was true, and we did run SA, this
+# expression decides whether we actually consider acting upon SAdevnull,
+# SApermreject, and SAtempreject if you have them set.
+#
+# Use this to tag messages that you shouldn't reject (messages sent to
+# abuse or postmaster for instance).
+#
+# As an example, set acl_m0 to "canreject" if a recipient other than
+# postmaster or abuse is encountered (and the sender isn't local). That
+# way, spammers can't circumvent blocking by sending to postmaster and
+# 99 other recipients. (If acl_m0 is taken, you'll of course have to use
+# a different variable.
+#SAEximRejCond: ${if eq{$acl_m0}{canreject}}
+
+
+# How much of the body we feed to spamassassin (in bytes)
+# Default is 250KB
+SAmaxbody: 256000
+
+# Do you want to feed SAmaxbody's worth of the message body if it is too big?
+# Either, you skip messages that are too big and not scan them, or you can
+# truncate the body and feed that to SA.
+# Note that SA will sometimes raise the spam score if it can't parse
+# the message correctly (since the end is missing, decoding will fail)
+# Default is 0: do not scan messages that are too big
+# (note that this is parsed as a condition)
+SATruncBodyCond: 0
+
+# If you want SA to report_safe you need sa-exim to rewrite the body of
+# the message since SA encapsulates the spam as a mime attachment.
+# You probably want SATruncBodyCond to be 0 or else you'll end up with a
+# partial message if it's larger than SAmaxbody and it's spam
+#
+# Also note that if you enable this option, any saved message will be saved
+# after the body has been modified by SA.
+# (this is not a condition as SA's report_safe is not conditional)
+SARewriteBody: 0
+
+# Prepend saved messages with an fake From-header to make the file look like a
+# valid mbox file
+SAPrependArchiveWithFrom: 1
+
+# If you are archiving messages that are rejected, how much do you want
+# to archive? Default is 20MB.
+SAmaxarchivebody: 20971520
+
+# On errors, if you are saving messages, you probably want the entire message
+# Default size saved (if you are saving errors) is 1GB
+SAerrmaxarchivebody: 1073741824
+
+# You can have SA-Exim add a X-SA-Exim-Rcpt-To header, which will list all
+# the recipients for the Email, unless the list gets bigger than
+# SAmaxrcptlistlength bytes.
+# The default value of 0 disables the header for privacy reasons (the header
+# exposes Bcced recipients)
+# Any value bigger than 8000 will be ignored because there is a limit on the
+# size of headers that you can have and exim's string_sprintf
+# Note that if you are planning to use greylisting, you should set this
+# value to 8000 since SA's greylisting code needs the recipients.
+SAmaxrcptlistlength: 0
+
+# Add X-SA-Exim-Rcpt-To and X-SA-Exim-Mail-From headers before SA scans
+# the message.
+# If this option is enabled, SARewiteBody is true, and safe_mode is
+# enabled in SA, you end up with the X-SA-Exim-Rcpt-To/X-SA-Exim-Mail-From in
+# the attatched message as well without the ability to remove them later in an
+# exim transport (think privacy).
+# In real life this is usually not a problem because the message is spam anyway,
+# and if you turn this off, you lose the option to use those headers to score
+# the message with SA.
+SAaddSAEheaderBeforeSA: 1
+
+# How many seconds you want to allow spamc to run. Exim 4.04 and better will
+# kill us after a default of 5 minutes. This however is not great, because the
+# mail gets temporarily rejected
+# You should set this and have SA Exim handle the timeout itself and accept the
+# message if spamc takes too long (instead of timing out)
+# A value of 0 means no timeout, and we run until exim stops us.
+# I know of at least one mail server (nanog's merit.edu) that will not
+# wait a full 5mn (which causes tempreject and resends), so the default is 4mn
+#SAtimeout: 240
+
+# Do you want to save mails that were accepted because spamc timed out?
+# Specify a directory to enable the feature.
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SAtimeoutsave: /var/spool/exim/SAtimeoutsave
+
+# You can optionally save or not save messages that matched the above rule
+SAtimeoutSavCond: 1
+
+
+# You should really create this directory for local_scan to save messages that
+# created an error. If you don't want this, comment out this variable
+# Make sure all these directories are owned by the exim user
+# SA-Exim will try to create the directory if it has the permissions to do
+# so, check your maillog for failures (or create the directory yourself and
+# make it writeable by exim)
+SAerrorsave: /var/spool/exim/SAerrorsave
+
+# You can optionally save or not save messages that matched the above rule
+# You should not put double quotes around the expression
+SAerrorSavCond: 1
+
+# If you set to 1, SA will temporarily reject messages that generated an error
+# while they were processed (they'll still be saved if SAerrorsave is set).
+# Otherwise (0 = false), the messages are just accepted, which seems like a
+# more sensible default
+SAtemprejectonerror: 0
+
+
+###############################################################################
+# NOTE: Spamd needs to tell sa-exim that the message SA-Exim gave spamd
+# is spam before sa-exim will consider the SA tresholds.
+# In other words, you cannot reject mails on SA scores if you set that
+# threshold to a lower threshold than SA's required_hits value.
+# The one exception to this rule is SAtempreject (in order to let you
+# temporarily reject mail when you are doing greylisting, see
+# README.greylisting in the documentation for details)
+###############################################################################
+
+# SA score when you start stalling the sender by sending many continuation
+# lines for up to SAteergrubetime
+# This is now a string (without quotes) that gets evaluated at runtime by exim
+# but you can still assign a simple float value to it
+# Note that this is an obvious abuse of SMTP, but eh, they started it :-)
+# Of course, this means that each incoming spam with the right score threshold
+# will keep an exim process busy on your machine. Make sure you can afford it.
+# Default value is 2^20, which should disable the behavior
+
+# Please, don't teergrube people who relay for you or your own MXes :-)
+# This option is left behind for backward compatibility, but you can now
+# get the same result by putting a condition string in SAteergrube
+# The trick is to list your score if the condition succeeds, and a really
+# high score otherwise.
+#SAteergrube: ${if and { {!eq {$sender_host_address}{127.0.0.1}} {!eq {$sender_host_address}{127.0.0.2}} } {25}{1048576}}
+
+# SAteergrubecond is deprecated (replaced by SAteergrube)
+# You used to be say whether you would apply the teergrubing score with this
+# condition, but now that scores are conditions, it is obsolete
+#SAteergrubecond: ${if and { {!eq {$sender_host_address}{127.0.0.1}} {!eq {$sender_host_address}{127.0.0.2}} } {1}{0}}
+
+# How long do you want to stall the sender (in seconds)
+# If you set the value too high, you might get too many exim processes running
+# and run out of process slots
+# Remember, don't come crying if playing with this "feature" causes your mail
+# server to catch fire :-)
+SAteergrubetime: 900
+
+# You can optionally save or not save messages that matched the above rule
+SAteergrubeSavCond: 1
+
+# Do you want to save mails that you stalled for later analysis?
+# Specify a directory to enable the feature.
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SAteergrubesave: /var/spool/exim/SAteergrube
+
+# When you stall the sender, you will probably get the mail again.
+# By default, we'll only save messages by message ID so that we don't save
+# multiple copies every time the sender tries again.
+# Of course, this means someone could fake someone else's message ID to
+# overwrite the saved copy of another spam. Such is life :-)
+SAteergrubeoverwrite: 1
+
+
+
+# If you reach this score, the mail is accepted and tossed (/dev/nulled).
+# The default value is 2^20 which should ensure this never happens.
+# This is now a string (without quotes) that gets evaluated at runtime by exim
+# but you can still assign a simple float value to it
+# You should be really sure that the message is spam because the sender will
+# get no notification
+#SAdevnull: 20.0
+
+# You can optionally save or not save messages that matched the above rule
+SAdevnullSavCond: 1
+
+# Do you want to save mails that are tossed?
+# Specify a directory to enable the feature.
+# This is just in case you do want to keep a copy of the alledge spams somewhere
+# Messages are saved by unixdate_Message-Id or just unix date if there is no
+# Message-Id.
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SAdevnullsave: /var/spool/exim/SAdevnull
+
+
+
+# SA score when you start rejecting Emails (this is better than the above as
+# it can notify the sender in case you reject non-spam by mistake)
+# This is now a string (without quotes) that gets evaluated at runtime by exim
+# but you can still assign a simple float value to it
+# Default value is 2^20, which should disable the behavior if you comment out
+# the line below
+SApermreject: 12.0
+
+# You can optionally save or not save messages that matched the above rule
+SApermrejectSavCond: 1
+
+# Do you want to save mails that are rejected?
+# Specify a directory to enable the feature.
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SApermrejectsave: /var/spool/exim/SApermreject
+
+
+
+# SA score when you start returning a temporary reject.
+# There are few reasons to use this, except if you're reading your tempreject
+# save folder (see below) and ajusting scores on the fly, or if you are using
+# greylisting
+# This is now a string (without quotes) that gets evaluated at runtime by exim
+# but you can still assign a simple float value to it
+# Default value is 2^20, which should disable the behavior
+#SAtempreject: 9.0
+
+# You can optionally save or not save messages that matched the above rule
+SAtemprejectSavCond: 1
+
+# Do you want to save mails that are temporarily rejected?
+# Specify a directory to enable the feature.
+# You could use this to analyse what SA is bouncing and adding an allow rule
+# to accept the mail next time it is sent back to you
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SAtemprejectsave: /var/spool/exim/SAtempreject
+
+# When you send back a temp reject code, you will get the mail again.
+# By default, we'll only save messages by message ID so that we don't save
+# multiple copies every time the sender tries again.
+# Of course, this means someone could fake someone else's message ID to
+# overwrite the saved copy of another spam. Such is life :-)
+SAtemprejectoverwrite: 1
+
+# See README.greylisting in the documentation for the following options
+# This is the string that SpamAssassin adds if the message is whitelisted
+# We use this to optionally increase the score needed for a tempreject
+# (in order to let a message through when it would otherwise have been
+# temprejected)
+# Default value is "GREYLIST_ISWHITE" (as used in the patch provided by SA-Exim)
+SAgreylistiswhitestr: GREYLIST_ISWHITE
+
+# By how much do we temporarly raise tempreject to allow a mail in when it
+# would otherwise have been temp rejected (because SA flagged it was whitelisted
+# by the greylisting code provided as a patch to SA in the SA-Exim distro)
+# Note that greylisting will not work in until you patch SA with the greylist
+# function
+# Note that you most likely want
+# SAtempreject + SAgreylistraisetempreject <= SApermreject
+# Default value is 3.0 but you'd probably to lower the tempreject score and
+# increase this one (see README.greylisting)
+SAgreylistraisetempreject: 3.0
+
+
+# Do you want to save mails that are flagged as spam by SA, but not rejected by
+# any of the above thresholds? Specify a directory to enable the feature.
+# That's one way to track mails thare are going through even though they were
+# flagged by SA (note that you could also save them in exim's system_filter,
+# although copies saved here happen before exim makes modification to the
+# message like rewriting)
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SAspamacceptsave: /var/spool/exim/SAspamaccept
+
+# You can control which messages you want saved if you only want a subset
+SAspamacceptSavCond: 0
+
+
+# Do you want to save mails that are not flagged as spam by SA
+# Specify a directory to enable the feature.
+# This is only here for completeness, if you want to save all messages not
+# flagged as spam by SA (you could also do this in system_filter)
+# SA-Exim will try to create the directory if it has the permissions to do so,
+# check your maillog for failures (or create the directory yourself and make it
+# writeable by exim)
+SAnotspamsave: /var/spool/exim/SAnotspam
+
+# You can control which messages you want saved if you only want a subset
+SAnotspamSavCond: 0
+
+# All the following strings can take one '%s' which will be replaced by
+# spamstatus: "SA score, trigger score"
+SAmsgteergrubewait: Wait for more output
+SAmsgteergruberej: Please try again later
+SAmsgpermrej: Rejected
+SAmsgtemprej: Please try again later
+# This string is a static string, do not include "%s"
+SAmsgerror: Temporary local error while processing message, please contact postmaster.
Index: 4.2.1-7/greylistclean.cron
===================================================================
--- 4.2.1-7/greylistclean.cron (nonexistent)
+++ 4.2.1-7/greylistclean.cron (revision 23)
@@ -0,0 +1,3 @@
+# If you don't run spamd as nobody (you should), change the user below
+# be smart and don't run this as root, it doesn't need those perms
+33 * * * * nobody [ -x /usr/share/sa-exim/greylistclean ] && /usr/share/sa-exim/greylistclean
Index: 4.2.1-7/README
===================================================================
--- 4.2.1-7/README (nonexistent)
+++ 4.2.1-7/README (revision 23)
@@ -0,0 +1,355 @@
+COPYRIGHTS
+----------
+SA-Exim was written by Marc MERLIN <marc_soft@merlins.org>
+You can find the latest version here:
+ http://sa-exim.sf.net/
+or here:
+ http://marc.merlins.org/linux/exim/sa.html
+
+greylisting was written by and is copyright Mark Lawrence <nomad@null.net>
+
+
+INSTALL
+-------
+See the file named INSTALL for installations instructions (either compiled
+in exim, or as a stand-alone shared library)
+
+If you got sa-exim prepackaged (like on debian), you have to make sure that
+your exim supports a dynamically loadable local_scan (which is true on debian
+and probably on other distros too if they shipped sa-exim as a package), and
+that your exim4.conf file contains the following:
+local_scan_path = /usr/lib/exim4/local_scan/sa-exim.so
+If you are using the split configuration file on debian with the sa-exim deb
+package, you'll be fine. If you're using the monolithic file, you are on your
+own until/unless the sa-exim packages try to do an in place edit (i.e. you have
+to add the above configuration line yourself)
+
+
+UPGRADING
+---------
+Deleting greylisting tuplets pre-4.2.1:
+If you are installing this package yourself, and ever installed the old
+greylistclean.cron which contained the complicated shell commands to clean
+old tuplets, you should stop using those commands and upgrade to greylistclean.
+Upgrading Greylisting.pm should also create safer tuplets without whitespace,
+but it's better to get rid of the old shell cron jobs either way
+
+
+PRIVACY WARNING
+---------------
+SA-Exim can add a header with the list of recipients in an Email (including
+Bcced folks).
+X-SA-Exim-Rcpt-To is used to allow you to see who a spam went to easily (i.e.
+without scanning the exim logs), and to write SpamAssassin rules on the envelope
+To (like adding a score if there were too many recipients or a recipient who you
+know only receives spam)
+X-SA-Exim-Rcpt-To is not added anymore by default, you need to enable it by
+setting SAmaxrcptlistlength to a value up to 8000, but if you do add it,
+you should consider removing it in exim's system_filter or in a transport.
+If SARewriteBody is true you should also consider setting
+SAaddSAEheaderBeforeSA to false (see the config) as all the recipients
+will be visible in the attached spam, note that this disables the
+ability to write SpamAssassin rules based on X-SA-Exim-Rcpt-From/To.
+In real life, who a spam was sent to isn't really a problem, but it could be if
+a private message is mis-categorized as spam
+Note however that if you disable X-SA-Exim-Rcpt-To by setting
+SAmaxrcptlistlength to 0, you will not be able to use greylisting, which
+depends on this header (however you'd still be welcome to remove the header in
+system_filter)
+
+
+CONFIGURATION
+-------------
+You should read sa-exim.conf, all the options there should be well
+documented.
+
+Note that the code will not act on any mail before it is flagged as SPAM by SA.
+
+Having SA flag the mail however doesn't mean the code rejects it or throws
+the alleged spam away, you control what you want to do depending on the score.
+The only restriction is that things happen in this order (for increasing SA
+scores)
+
+ - Save in SAnotspamsave if enabled
+ - Save in SAspamacceptsave if enabled
+ - Temporarily reject and optionally save if enabled
+ - Permanently reject and optionally save if enabled
+ - Accept, drop the mail, and optionally save if enabled
+ - Teergrube (i.e. stall) the sender to waste his resources (and yours)
+
+Note that you cannot set a teergrube threshold of 12, and a permreject
+threshold of 20 (not that it would make much sense anyway).
+Threshold scores should decrease as you apply the highest to the lowest penalty
+(i.e. the rules are run in this order: teergrube, devnull, permreject,
+tempreject)
+
+Now, as of SA-Exim 4.2, things get slightly more complicated as scores are
+actually full exim conditions, and therefore you could have:
+SAteergrube: ${if and { {!eq {$sender_host_address}{127.0.0.1}} {!eq {$sender_host_address}{127.0.0.2}} } {25}{1048576}}
+This means that if your condition succeeds, the teergrube score is set to 25,
+and if the condition fails, the teergrube score is set to 2^20, which for all
+intents and purposes, disables teergrubing.
+Regardless of what your scores end up being after the conditions are evaluated,
+sa-exim still tests them in this order: teergrube, devnull, permreject,
+tempreject)
+
+
+
+
+CONFIGURING SPAMASSASSIN
+------------------------
+A good example of spamassassin configuration would be:
+
+ report_safe 0
+ use_terse_report 1 # for SA < 3.x
+
+This will put a non-verbose SPAM-report in the headers, but leave the
+message itself intact for easy analyzing and for easy feeding to
+sa-learn when mis-flagged as spam or ham. The only way to see the
+message is spam, is by looking in the headers.
+
+If you have an older version of SpamAssassin (<= 2.50), you'd probably
+want to add 'report_header 1' to that list. But this is default and
+un-needed in new versions of SA)
+
+If you set 'report_safe' to a true value, you might also want to set
+use_terse_report to a false value, in case you'll get the long header
+which might be friendlier to your users.
+
+For SA before 3.x, add 'always_add_report 1' to always have a spamcheck report
+put in the message. This might be useful to test rules.
+For SA 3.x onward, the syntax you'd want, is:
+add_header all Report _REPORT_
+
+Since SA is usually configured to pass messages on that are beyond the SA
+spam threshold, it can make sense to rewrite the subject line.
+To achieve this, you would use this for SA 2.x:
+ rewrite_subject 1
+ subject_tag SPAM: _HITS_:
+
+For SA 3.x, the syntax is:
+ rewrite_header Subject SPAM: _HITS_:
+
+
+If you are using SA 2.50 or better, by default, you should probably set:
+ report_safe 0
+
+Now, if you are willing to take a small speed and I/O hit, you can have
+sa-exim read the body back from SA, and replace the original mail with
+the new body.
+
+You would use this if you want to set SA's report_safe to 1 or 2 (in
+which case you also have to set SARewriteBody: 1 in SA-Exim's config)
+
+Note that if you do so, unfortunately archived messages will have the
+body modified by SA. This is not very trivial to fix, so if you archive
+anything, you may not want to use SARewriteBody
+
+
+Important:
+You want to run spamd as such:
+/usr/sbin/spamd -d -u nobody -H /var/spool/spamassassin/
+
+It may not work if you run spamd with -c (debian default),
+(you shouldn't run spamassassin as root for this purpose anyway (there
+is no reason to, so why take the risk)
+
+You can edit this in /etc/default/spamassassin (debian) and probably
+/etc/sysconfig/spamassassin (redhat)
+
+With SA 3.x is better, the updated syntax would look like this:
+/usr/sbin/spamd --max-children 50 --daemonize --username=nobody --nouser-config --helper-home-dir=/var/spool/spamassassin/
+
+
+
+CONFIGURING EXIM4.CONF
+----------------------
+This code works without anything in the exim conf, but you probably want to use
+some knobs to disable scanning for some users (like setting X-SA-Do-Not-Rej
+or X-SA-Do-Not-Run in the rcpt ACL and removing those headers in the right
+places)
+
+See http://marc.merlins.org/linux/exim/#conf and more specifically
+http://marc.merlins.org/linux/exim/exim4-conf/exim4.conf
+
+Note that obviously if you set those headers, spammers can set them too, so
+if you are concerned about this, you can either change the header name, or set
+it to something else than 'Yes' and check for that value in sa-exim.conf
+(or as a 3rd option, you can use exim ACL variables to pass values to SA-Exim
+without generating headers; see the section contributed by Chirik, lower in
+this file)
+
+
+
+EXIM4 INTEGRATION / NOT SCANNING YOUR OWN MAILS
+-----------------------------------------------
+For a very complete exim4 config, including settings for SA, you should
+look at sa-exim.conf and play with:
+
+SAEximRunCond: ${if and{ \
+ {def:sender_host_address} \
+ {!eq {$sender_host_address}{127.0.0.1}} \
+ {!eq {$h_X-SA-Do-Not-Run:}{Yes}} \
+ } \
+ {1}{0} \
+ }
+
+PLEASE NOTE: This conditional statement must be on one line. SA-Exim's
+configfile parser does not support \-lineconitunation!!
+
+You may also want to look at my exim4.conf config if you haven't done so yet:
+http://marc.merlins.org/linux/exim/#conf
+
+The check_rcpt ACL has:
+ warn message = X-SA-Do-Not-Rej: Yes
+ local_parts = +nosarej:postmaster:abuse
+
+ warn message = X-SA-Do-Not-Run: Yes
+ hosts = +relay_from_hosts
+
+ warn message = X-SA-Do-Not-Run: Yes
+ authenticated = *
+
+Then, you'll want to strip SA headers for messages that aren't local
+This means you should strip them at least in the remote_smtp transport
+with this configuration snippet:
+
+ # This is generally set on messages originating from local users and it tells
+ # SA-Exim not to scan the message or that the message was scanned.
+ # Let's remove these headers if the message is sent remotely
+ headers_remove = "X-SA-Do-Not-Run:X-SA-Exim-Scanned:X-SA-Exim-Mail-From:X-SA-Exim-Rcpt-To:X-SA-Exim-Connect-IP"
+
+
+You can also use another option, which can't be spoofed by a spammer, but
+won't show you why a mail didn't get scanned if it was sent to multiple
+people (which is why I personally prefer the above, even if it's spoofable)
+
+Contributed by Chirik <chirik@castlefur.com>:
+----------------------------------------------------------------------------
+I have the following:
+
+SAEximRunCond: ${if !eq {$acl_m0}{do-not-scan} {1} {0}}
+SAEximRejCond: ${if !eq {$acl_m0}{do-not-reject} {1} {0}}
+
+Then, in my recipient ACL, I have:
+
+ ##### Checks for postmaster or abuse - we'll scan, still, but not reject
+ ##### Don't reject for certain users
+ warn local_parts = postmaster : abuse
+ set acl_m0 = do-not-reject
+
+ ##### Check for situations we don't even scan (local mail)
+ ##### Don't scan if hosts we relay for (probably dumb MUAs),
+ warn hosts = +relay_from_hosts:127.0.0.1/8
+ set acl_m0 = do-not-scan
+
+ ##### Don't scan non-smtp connections (empty host list)
+ warn hosts = :
+ set acl_m0 = do-not-scan
+
+ ##### Don't scan if authenticated
+ warn authenticated = *
+ set acl_m0 = do-not-scan
+----------------------------------------------------------------------------
+
+
+
+TEERGRUBING: SAteergrube
+------------------------
+The idea is for mail that you know for sure is spam (I use a threshold of 25),
+you can stall the spammer for as long as possible by sending a continuation
+line every 10 seconds:
+451- wait for more output
+451- wait for more output
+451- wait for more output
+(...)
+
+You can go there for details:
+http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html
+
+What should you know?
+1) This is obviously going to use up some of your resources
+2) You should not teergrube SMTP servers that relay mail for you, be
+ courteous (set a condition in SAteergrube like in the example
+ provided). Besides they are real mail relays, so they will diligently
+ try to send you the spam over and over for days)
+ (note that you should probably not teergrube mailling lists you subscribed
+ to either, or you risk getting unsubscribed)
+ See a sample in sa-exim.conf for example syntax.
+3) Because of limitations in the current exim code, teergrubing will not work
+ over TLS.
+ This shouldn't be a problem since real spammers should not be using TLS,
+ and you shouldn't teergrube relays that do TLS with you.
+ If you do teergrube a TLS connection, it will break the connection and you
+ will see this in your logs:
+18640m-0000Vb-00 SSL_write error 5
+TLS error (SSL_write): error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
+ This is not ideal, but in real life, that's ok.
+
+
+
+GREYLISTING
+-----------
+See README.greylisting
+
+
+
+READING ARCHIVED SPAMS
+----------------------
+Spams are optionally saved in individual files in a 'new' subdirectory
+of some place like /var/spool/sa-exim/SAteergrube.
+
+There are two ways to read them:
+1) cat new/* > /tmp/mailbox, and use the resulting file as a standard
+ mbox file with any mail client (if SAPrependArchiveWithFrom is true)
+2) Use a maildir capable mail client, like mutt, and run something like
+ 'mutt -f /var/spool/sa-exim/SAteergrube'. This will read the messages in
+ place, since what sa-exim creates looks like a valid Maildir spool.
+
+If you configured SA-Exim to set X-SA-Exim-Rcpt-To, you can even resend
+archived refused messages to the users they were meant for
+
+Note that sa-exim runs with the same uid/gid than the exim daemon (something
+like mail, exim, or Debian-Exim), so /var/spool/sa-exim/SAteergrube must exist
+and be writeable by exim.
+SA-Exim will then create (sub-)directories with the permissions 0770 as
+needed (those permissions aren't a configuration option, but you can change
+them after the fact or pre-create the directories with the permissions of your
+choice)
+Files are created with 0664 permissions so that anyone who has directory access
+can read (and maybe write) the files.
+If you chgrp the parent 'new' directory to a group of your choice, and give it
+permissions 2770 or 2775, the files will be created with that group instead of
+the default exim group
+
+
+
+LOG AND SMTP OUTPUT
+-------------------
+As of SA-Exim 3.0, SMTP output does not contain the spam score anymore,
+and you can change the messages or re-add the score by changing the
+runtime SAmsg* variables
+
+All SA-Exim log now looks like this:
+- "SA: PANIC: " -> severe errors
+- "SA: Warning: " -> config file parsing errors
+- "SA: Notice: " -> misc info on what SA-Exim is doing or not doing
+- "SA: Action: " -> what action SA-Exim took on a mail after scanning
+- "SA: Debug[X]: " -> misc debug info if enabled
+
+Marin Balvers has written a nice log parser here:
+http://nossie.addicts.nl/projects/sa-exim-stats/
+
+
+
+FAQ
+---
+Why do I get this in my exim logs?
+
+2004-05-15 12:43:57 1BP54T-0002gV-Nu TLS send error on connection from internalmx1.company.tld (internalmx.company.tld) [192.168.1.1]:51552: Error in the push function.
+2004-05-15 12:43:57 TLS recv error on connection from internalmx1.company.tld (internalmx.company.tld)
+[192.168.1.1]:51552: The specified session has been invalidated for some reason.
+
+This is because you are teergrubing a host that is doing TLS. Teergrubing does
+not work with TLS, and people doing TLS with you are probably known relays which
+you should exclude from your teergrube list (SAteergrubecond)
Index: 4.2.1-7/accept.c
===================================================================
--- 4.2.1-7/accept.c (nonexistent)
+++ 4.2.1-7/accept.c (revision 23)
@@ -0,0 +1,45 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2002 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+
+#include "local_scan.h"
+
+/*
+ * This is a basic version of local_scan that always accepts the messge.
+ * It is like the template provided by Philip Hazel, except it is
+ * intended to be compiled as a .so and loaded dynamically by the "real"
+ * local_scan.
+ */
+
+int local_scan_version_major(void)
+{
+ return LOCAL_SCAN_ABI_VERSION_MAJOR;
+}
+
+int local_scan_version_minor(void)
+{
+ return LOCAL_SCAN_ABI_VERSION_MINOR;
+}
+
+int local_scan_version( void )
+{
+ return 1;
+}
+
+
+int local_scan(int fd, uschar **return_text)
+{
+ /* Keep pedantic compilers happy */
+ fd = fd;
+ return_text = return_text;
+
+ log_write(0, LOG_MAIN, "Message accepted by dynamically loaded dummy local_scan");
+ return LOCAL_SCAN_ACCEPT;
+}
+
+
+/* End of local_scan.c */
Index: 4.2.1-7/sa.html.template
===================================================================
--- 4.2.1-7/sa.html.template (nonexistent)
+++ 4.2.1-7/sa.html.template (revision 23)
@@ -0,0 +1,221 @@
+<html>
+<head>
+<title>Exim SpamAssassin at SMTP time</title>
+</head>
+
+<body>
+
+<h1 ALIGN="CENTER">Exim SpamAssassin at SMTP time</h1>
+
+<h3>What's that?</h3>
+<pre>
+mail from: merlin@gandalf
+250 OK
+rcpt to: merlin@gandalf
+250 Accepted
+data
+354 Enter message, ending with "." on a line by itself
+From: merlin@gandalf
+To: merlin@gandalf
+Subject: $$$ Make Money Fast $$$ !!!
+
+viagra 100% GARANTEE AMAZING FULL REFUND
+This is not spam
+.
+550 Rejected
+</pre>
+(logs would show something like this:
+<tt>2004-03-10 08:27:18 1B16Y8-0001UP-4R SA: Action: permanently rejected message: hits=14.8 required=7.0 trigger=11.0 ( scanned in 2/2 secs | Message-Id: CCQPVENACPQBFLTRLICXWQVEK@gandalf). From <merlin@gandalf> (host=gandalf [127.0.0.1]) for merlin@gandalf</tt>)
+
+
+<P>
+An example of teergrube would return this instead
+<pre>
+data
+354 Enter message, ending with "." on a line by itself
+(...)
+body SEE_FOR_YOURSELF /See (?:for|it) yourself\b/i
+describe SEE_FOR_YOURSELF See for yourself
+
+body ORDER_NOW /\border (?:now|soon|fast|quickly|while)\b/i
+describe ORDER_NOW Encourages you to waste no time in ordering
+
+.
+451- wait for more output
+451- wait for more output
+451- wait for more output
+(... one line every 10 secs, 15 minutes elapse ...)
+450 Please try again later
+</pre>
+
+The idea here is to stall and waste the resources of the remote sender (BTW
+teergrube comes from german, and means tar-pitting, or stopping someone in his
+tracks)
+
+<BR><BR>
+<h3>Why?</h3>
+SpamAssassin can be run inside exim after the mail has been accepted, as shown
+<a href="http://bogmog.sourceforge.net/document_show.php3?doc_id=28">here</a>,
+but if you're not going to use my patch and you just want to run SA as an exim
+transport,
+<a href="http://dman13.dyndns.org/~dman/config_docs/exim-spamassassin/">this</a>
+version is recommended
+<P>
+Now, while this will work, we can do better, hence the reason for my code
+(just to make things clear, you do not want to run both my code, and dman's
+transports. It'd work, but you'd be scanning the message twice)
+<P>
+The reason why I wanted SpamAssassin in local scan is that I don't want to
+accept the damn spam in the first place.
+
+<ul>
+<li>While my code lets you do that, I don't like to send mails to the bit
+ bucket, so you need to bounce them.
+<li>Once you accept the spam, you can't bounce it half the time, or you
+ bounce it to an innocent whose Email was forged as an envelope sender
+ (some spam even forges the bounce address to <em>you</em>)
+<li>If I refuse spam at SMTP time, it will remove the spam addresses from at
+ least a few lists (they gotta clean their lists eventually otherwise they'd
+ spend more time Emailing dead addresses than good ones)
+<li>I have the option of toying with spammers and stall their connections and
+ waste their resources (see the following page for details on
+ <A HREF="http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html">
+ teergrubing</A>
+</ul>
+
+Note that you can also use this code to simply run SA on all your mails (or
+portion thereof as configured with SAEximRunCond) without having to configure SA
+in your exim.conf. In other words, this code can be configured to not reject
+any mails.
+
+<BR><BR>
+<h3>SpamAssassin? What's that?</h3>
+Ah, you need to visit <a href="http://spamassassin.org/">this page</a> first
+then
+
+
+<BR><BR>
+<h3>How does it work, what knobs are there?</h3>
+You need to configure spamassassin to flags mails as spam after a certain
+threshold (7 for instance). After that, this code can be configured to
+
+<ul>
+<li>Pretend to be processing the Email and send continuation lines to the
+ remote server until it gives up (aka
+ <A HREF="http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html">
+ teergrubing</A>)
+<li>Accept but not deliver mail with a high threshold (i.e. devnull the mail)
+<li>Reject mail with a lower threshold
+<li>Temporarily reject mail with a still lower threshold (you can then inspect
+ your logs to decide if you want to tweak SA so that next time the mail
+ is sent, you can receive it)
+<li>In all 5 cases, mail can be optionally saved to disk so that you can
+ inspect all the mails you've rejected or /dev/nulled
+</ul>
+
+You can also (and probably should <img src="/gifs/people/smile.happy.gif" alt=":-)" align=TOP WIDTH=16 HEIGHT=16>) use the new greylisting support for even
+better spam control
+
+
+<P>
+For more details, you should look at the self-documented
+<a href="files/sa-exim.conf">config file</a> and you can see
+<a href="sa-exim.demo.txt">some sample rejects and what you get in the logs</a>
+
+
+<BR><BR>
+<h3><A NAME="greylisting">Greylisting you say?</A></h3>
+While when sa-exim first came out, its strongest point was being one of the
+first programs (if not the first) that let you reject Spam at SMTP time, its
+coolest feature now is adaptive greylisting support<BR>
+In a nutshell, you get the advantages of greylisting without the disadvantages:
+<ul>
+<li>mails with a low spam score are accepted without delay
+<li>mails with an average spam score are greylisted,
+ <b>and only those are delayed</b>
+<li>mails with high spam scores are rejected regardless (no greylisting)
+</ul>
+
+This method is the best combination I've seen out there so far, and
+while I've been talking about it for a while, I don't yet know of other
+programs that implement this method (if you do, please let me know so that
+I can acknowledge them)
+<BR>
+For more details on how this works, check out the <a href="files/sa-exim-cvs/README.greylisting">greylisting README</a>
+
+
+<BR><BR>
+<h3>Ok, where's the code? / Downloads</h3>
+<ul>
+<li>The latest version is here (<a href="files/sa-exim-current/">browsable tree</a> or <a href="files/sa-exim-current.tar.gz">tar.gz</a>). You can also
+get it from <A href="http://sourceforge.net/projects/sa-exim/">sf.net</a><BR>
+<li>The CVS version is here (<a href="files/sa-exim-cvs/">browsable tree</a>)
+and you can also get the CVS tree from
+<A HREF="http://sourceforge.net/cvs/?group_id=56124">sf.net</A>
+<li>The latest config file with documentation is
+<a href="files/sa-exim.conf">here</a>
+<li>Debian packages (source and binary) are <a href="files/debian/">here</a>
+</ul>
+<P>
+
+As explained in the archive, you can either copy <tt>sa-exim.c</tt> over exim's
+<tt>src/local_scan.c</tt> You need to copy local_scan in src in the exim source
+tree and rebuild it, or you can build sa-exim as a loadable module (you need
+to patch exim to support loadable modules though)
+<P>
+You can also browse all my exim files <A HREF="files/">here</A>
+
+<BR><BR>
+<h3>Mailing list</h3>
+You should probably subscribe to this low traffic
+<a href="http://lists.merlins.org/lists/listinfo/sa-exim">mailing list</a> if
+you download the code to keep apprised of bug fixes and enhancements
+
+<BR><BR>
+<h3>Integration with Exim 4</h3>
+This code works without anything in the exim conf, but you probably want to use
+some knobs to disable scanning for some users (like setting
+<tt>X-SA-Do-Not-Rej</tt> or <tt>X-SA-Do-Not-Run</tt> in the rcpt ACL and
+removing those headers in the right places).<BR>
+See <A HREF="http://marc.merlins.org/linux/exim/#conf">my exim4 conf tree</a>
+and more specifically the
+<A HREF="http://marc.merlins.org/linux/exim/exim4-conf/exim4.conf">exim4.conf</A>
+file
+<P>
+You can look at the <A HREF="files/sa-exim-cvs/README">README</A> for more
+integration details.
+
+
+<BR><BR>
+<h3>Changelog/Download</h3>
+
+<Changelog>
+</Changelog>
+
+<P>
+More generally, all the files can also be found <A HREF="files/">here</A>
+<P>
+<A HREF="/perso/contact.html">Feedback is appreciated</A> (but please
+prefer the use of the
+<a href="http://lists.merlins.org/lists/listinfo/sa-exim">sa-exim list</a>)
+
+<BR><BR>
+<h3>Acknowledgements</h3>
+
+<Acknowledgements>
+</Acknowledgements>
+
+
+<P ALIGN="center">
+<img src="/gifs/lines/misc/lampline.gif" alt="" WIDTH=720 HEIGHT=14>
+</P>
+<br>
+<img src="/gifs/misc/wizard.gif" alt="" align="middle" WIDTH=72 HEIGHT=61>
+<img src="/gifs/linux/damn-powered.gif" alt="" align="right" WIDTH=170 HEIGHT=29>
+<IMG SRC="/gifs/icons/msfree.gif" ALT="[ms free site]" ALIGN="right" WIDTH=95 HEIGHT=31>
+<a href="http://sourceforge.net"><img src="http://sourceforge.net/sflogo.php?group_id=56124&amp;type=1" width="88" height="31" border="0" align="right" alt="SourceForge.net Logo"></a>
+<A HREF="/perso/contact.html">Email</A><BR>
+<A HREF="/">Link to Home Page</A>
+<P>
+</body>
+</html>
Index: 4.2.1-7/LICENSE
===================================================================
--- 4.2.1-7/LICENSE (nonexistent)
+++ 4.2.1-7/LICENSE (revision 23)
@@ -0,0 +1 @@
+GPL version 2.0 ('nuff said :-D)
Index: 4.2.1-7/version
===================================================================
--- 4.2.1-7/version (nonexistent)
+++ 4.2.1-7/version (revision 23)
@@ -0,0 +1 @@
+4.2.1
Index: 4.2.1-7/localscan_dlopen_exim_4.20_or_better.patch
===================================================================
--- 4.2.1-7/localscan_dlopen_exim_4.20_or_better.patch (nonexistent)
+++ 4.2.1-7/localscan_dlopen_exim_4.20_or_better.patch (revision 23)
@@ -0,0 +1,268 @@
+The initial version of this patch was originally posted David Woodhouse, and
+dman gets the credit for first integrating it with SA-Exim.
+
+I have since then maintained it by first making a few minor changes, and
+later switching it to a major/minor number scheme to support upgrades in
+the exim API that don't affect backward compatibility (you can rely on
+a feature denoted by the minor number and be compatible with future versions
+of exim until Philip has to break the API and increase the major number)
+
+Marc MERLIN <marc_soft@merlins.org>
+
+diff -urN exim-4.14-0/src/EDITME exim-4.14-1/src/EDITME
+--- exim-4.14-0/src/EDITME Tue Mar 11 04:20:18 2003
++++ exim-4.14-1/src/EDITME Sun Mar 23 15:34:15 2003
+@@ -388,6 +388,20 @@
+
+
+ #------------------------------------------------------------------------------
++# On systems which support dynamic loading of shared libraries, Exim can
++# load a local_scan function specified in its config file instead of having
++# to be recompiled with the desired local_scan function. For a full
++# description of the API to this function, see the Exim specification.
++
++DLOPEN_LOCAL_SCAN=yes
++
++# If you set DLOPEN_LOCAL_SCAN, then you need to include -rdynamic in the
++# linker flags. Without it, the loaded .so won't be able to access any
++# functions from exim.
++
++LFLAGS=-rdynamic -ldl
++
++#------------------------------------------------------------------------------
+ # The default distribution of Exim contains only the plain text form of the
+ # documentation. Other forms are available separately. If you want to install
+ # the documentation in "info" format, first fetch the Texinfo documentation
+diff -urNad 50_localscan_dlopen.tmp/src/config.h.defaults 50_localscan_dlopen/src/config.h.defaults
+--- 50_localscan_dlopen.tmp/src/config.h.defaults Sun Dec 29 11:55:42 2002
++++ 50_localscan_dlopen/src/config.h.defaults Sun Dec 29 11:56:44 2002
+@@ -17,6 +17,8 @@
+ #define AUTH_PLAINTEXT
+ #define AUTH_SPA
+
++#define DLOPEN_LOCAL_SCAN
++
+ #define BIN_DIRECTORY
+
+ #define CONFIGURE_FILE
+diff -urN exim-4.14-0/src/globals.c exim-4.14-1/src/globals.c
+--- exim-4.14-0/src/globals.c Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/globals.c Sun Mar 23 15:34:15 2003
+@@ -103,6 +103,9 @@
+ uschar *tls_verify_hosts = NULL;
+ #endif
+
++#ifdef DLOPEN_LOCAL_SCAN
++uschar *local_scan_path = NULL;
++#endif
+
+ /* Input-reading functions for messages, so we can use special ones for
+ incoming TCP/IP. The defaults use stdin. We never need these for any
+diff -urN exim-4.14-0/src/globals.h exim-4.14-1/src/globals.h
+--- exim-4.14-0/src/globals.h Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/globals.h Sun Mar 23 15:34:15 2003
+@@ -67,6 +67,9 @@
+ extern uschar *tls_verify_hosts; /* Mandatory client verification */
+ #endif
+
++#ifdef DLOPEN_LOCAL_SCAN
++extern uschar *local_scan_path; /* Path to local_scan() library */
++#endif
+
+ /* Input-reading functions for messages, so we can use special ones for
+ incoming TCP/IP. */
+diff -urN exim-4.14-0/src/local_scan.c exim-4.14-1/src/local_scan.c
+--- exim-4.14-0/src/local_scan.c Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/local_scan.c Sun Mar 23 15:34:15 2003
+@@ -5,60 +5,131 @@
+ /* Copyright (c) University of Cambridge 1995 - 2003 */
+ /* See the file NOTICE for conditions of use and distribution. */
+
++#include "exim.h"
+
+-/******************************************************************************
+-This file contains a template local_scan() function that just returns ACCEPT.
+-If you want to implement your own version, you should copy this file to, say
+-Local/local_scan.c, and edit the copy. To use your version instead of the
+-default, you must set
+-
+-LOCAL_SCAN_SOURCE=Local/local_scan.c
+-
+-in your Local/Makefile. This makes it easy to copy your version for use with
+-subsequent Exim releases.
+-
+-For a full description of the API to this function, see the Exim specification.
+-******************************************************************************/
+-
+-
+-/* This is the only Exim header that you should include. The effect of
+-including any other Exim header is not defined, and may change from release to
+-release. Use only the documented interface! */
+-
+-#include "local_scan.h"
+-
+-
+-/* This is a "do-nothing" version of a local_scan() function. The arguments
+-are:
+-
+- fd The file descriptor of the open -D file, which contains the
+- body of the message. The file is open for reading and
+- writing, but modifying it is dangerous and not recommended.
+-
+- return_text A pointer to an unsigned char* variable which you can set in
+- order to return a text string. It is initialized to NULL.
+-
+-The return values of this function are:
+-
+- LOCAL_SCAN_ACCEPT
+- The message is to be accepted. The return_text argument is
+- saved in $local_scan_data.
+-
+- LOCAL_SCAN_REJECT
+- The message is to be rejected. The returned text is used
+- in the rejection message.
+-
+- LOCAL_SCAN_TEMPREJECT
+- This specifies a temporary rejection. The returned text
+- is used in the rejection message.
+-*/
++#ifdef DLOPEN_LOCAL_SCAN
++#include <dlfcn.h>
++static int (*local_scan_fn)(int fd, uschar **return_text) = NULL;
++static int load_local_scan_library(void);
++#endif
+
+ int
+ local_scan(int fd, uschar **return_text)
+ {
+ fd = fd; /* Keep picky compilers happy */
+ return_text = return_text;
+-return LOCAL_SCAN_ACCEPT;
++#ifdef DLOPEN_LOCAL_SCAN
++/* local_scan_path is defined AND not the empty string */
++if (local_scan_path && *local_scan_path)
++ {
++ if (!local_scan_fn)
++ {
++ if (!load_local_scan_library())
++ {
++ char *base_msg , *error_msg , *final_msg ;
++ int final_length = -1 ;
++
++ base_msg=US"Local configuration error - local_scan() library failure\n";
++ error_msg = dlerror() ;
++
++ final_length = strlen(base_msg) + strlen(error_msg) + 1 ;
++ final_msg = (char*)malloc( final_length*sizeof(char) ) ;
++ *final_msg = '\0' ;
++
++ strcat( final_msg , base_msg ) ;
++ strcat( final_msg , error_msg ) ;
++
++ *return_text = final_msg ;
++ return LOCAL_SCAN_TEMPREJECT;
++ }
++ }
++ return local_scan_fn(fd, return_text);
++ }
++else
++#endif
++ return LOCAL_SCAN_ACCEPT;
++}
++
++#ifdef DLOPEN_LOCAL_SCAN
++
++static int load_local_scan_library(void)
++{
++/* No point in keeping local_scan_lib since we'll never dlclose() anyway */
++void *local_scan_lib = NULL;
++int (*local_scan_version_fn)(void);
++int vers_maj;
++int vers_min;
++
++local_scan_lib = dlopen(local_scan_path, RTLD_NOW);
++if (!local_scan_lib)
++ {
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library open failed - "
++ "message temporarily rejected");
++ return FALSE;
++ }
++
++local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_major");
++if (!local_scan_version_fn)
++ {
++ dlclose(local_scan_lib);
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
++ "local_scan_version_major() function - message temporarily rejected");
++ return FALSE;
++ }
++
++/* The major number is increased when the ABI is changed in a non
++ backward compatible way. */
++vers_maj = local_scan_version_fn();
++
++local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_minor");
++if (!local_scan_version_fn)
++ {
++ dlclose(local_scan_lib);
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
++ "local_scan_version_minor() function - message temporarily rejected");
++ return FALSE;
++ }
++
++/* The minor number is increased each time a new feature is added (in a
++ way that doesn't break backward compatibility) -- Marc */
++vers_min = local_scan_version_fn();
++
++
++if (vers_maj != LOCAL_SCAN_ABI_VERSION_MAJOR)
++ {
++ dlclose(local_scan_lib);
++ local_scan_lib = NULL;
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible major"
++ "version number, you need to recompile your module for this version"
++ "of exim (The module was compiled for version %d.%d and this exim provides"
++ "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
++ LOCAL_SCAN_ABI_VERSION_MINOR);
++ return FALSE;
++ }
++else if (vers_min > LOCAL_SCAN_ABI_VERSION_MINOR)
++ {
++ dlclose(local_scan_lib);
++ local_scan_lib = NULL;
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible minor"
++ "version number, you need to recompile your module for this version"
++ "of exim (The module was compiled for version %d.%d and this exim provides"
++ "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
++ LOCAL_SCAN_ABI_VERSION_MINOR);
++ return FALSE;
++ }
++
++local_scan_fn = dlsym(local_scan_lib, "local_scan");
++if (!local_scan_fn)
++ {
++ dlclose(local_scan_lib);
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
++ "local_scan() function - message temporarily rejected");
++ return FALSE;
++ }
++
++return TRUE;
+ }
++
++#endif /* DLOPEN_LOCAL_SCAN */
+
+ /* End of local_scan.c */
+diff -urN exim-4.14-0/src/readconf.c exim-4.14-1/src/readconf.c
+--- exim-4.14-0/src/readconf.c Tue Mar 11 04:20:22 2003
++++ exim-4.14-1/src/readconf.c Sun Mar 23 15:34:15 2003
+@@ -182,6 +182,9 @@
+ { "local_from_prefix", opt_stringptr, &local_from_prefix },
+ { "local_from_suffix", opt_stringptr, &local_from_suffix },
+ { "local_interfaces", opt_stringptr, &local_interfaces },
++#ifdef DLOPEN_LOCAL_SCAN
++ { "local_scan_path", opt_stringptr, &local_scan_path },
++#endif
+ { "local_scan_timeout", opt_time, &local_scan_timeout },
+ { "local_sender_retain", opt_bool, &local_sender_retain },
+ { "localhost_number", opt_stringptr, &host_number_string },
Index: 4.2.1-7/Changelog.html
===================================================================
--- 4.2.1-7/Changelog.html (nonexistent)
+++ 4.2.1-7/Changelog.html (revision 23)
@@ -0,0 +1,291 @@
+<!-- <li>2004/08/23 - v4.2.1+cvs (<a href="files/sa-exim-cvs.tar.gz">sa-exim cvs tar.gz</a>
+ (latest version available via CVS only, or a somewhat recent via
+ <a href="files/sa-exim-cvs.tar.gz">this link</a>) -->
+
+<li>2006/01/09 - v4.2.1 (<a href="files/sa-exim-4.2.1.tar.gz">sa-exim.tar.gz</a>
+or <a href="files/local_scan/local_scan.c_4.2.1">local_scan only</a>)
+ <br><b>Security update</b> (reported by Chris Morris)
+ <ul>
+ <li>Modified Greylisting.pm not to generate tuplets with spaces, although
+ the cleaning cron job is now safe with regard to whitespace
+ <li>Included Mark Lawrence's perl script to better clean old tuplets
+ <li>The default config now ships with the greylistclean cronjob running
+ as nobody (which spamd should be running as, too)
+ </ul>
+
+<li>2005/01/17 - v4.2 (<a href="files/sa-exim-4.2.tar.gz">sa-exim.tar.gz</a>
+or <a href="files/local_scan/local_scan.c_4.2">local_scan only</a>)
+ <br><b>Do not use, greylistclean is insecure, use 4.2.1 instead</b>
+ <ul>
+ <li>Fixed code so that it compiles inside the exim tree too (thanks Jason)
+ <li>Support SA 3.0 new score reporting format (score= instead of hits=)
+ <li>Proper SA 3.0 plugin support
+ <li>Documentation updates
+ <li>greylisting files now also save the last SA score, just in case
+ <li>Saved files are now group read/write too, if you need to shut off group
+ access, do it at the directory level
+ <li>Only rewrite Content-Type/Content-Transfer-Encoding if SARewriteBody is
+ on now (this used to be useful with old SA versions and defang_mime
+ but those options are gone). Suggested by Adam Tilghman.
+ <li>Finally made all score threshold variables exim conditions that are
+ evaluated at runtime
+ <li>SAteergrubecond is deprecated as a result
+ </ul>
+
+<li>2004/08/16 - v4.1 (<a href="files/sa-exim-4.1.tar.gz">sa-exim.tar.gz</a>
+or <a href="files/local_scan/local_scan.c_4.1">local_scan only</a>)
+ <b>Please see the mailing list, or use the CVS version if you are compiling
+ sa-exim inside your exim tree</b> (there is a small mistake in the source
+ which will prevent proper building) / <b>You also need CVS if you are
+ using SA 3.0</b>
+ <ul>
+ <li>Deal with being called with the number of recipients is 0 (reported by
+ John Horne)
+ <li>Made hopefully fully 64 bit clean (well, it was written that way,
+ except for that pesky printf in C, which got in the way). Kudos go to
+ Adam D. Barratt for finding and explaining the bug
+ <li>Switched to using strchr instead of index to remove compilation warnings
+ on some systems (reported by John Horne/Jeff Carter)
+ <li>Added SAspamcHost/SAspamcPort at the request of several people
+ <li>Fixed mbox From file to be standards complaint (reported by Cliff Hones)
+ <li>Added SAFEMESGIDCHARS option for safer message-id based filenames
+ <li>New version of the SA patch, with safe file creation (clean env from
+ and rcpt to before using as directory names)
+ <li><b>IMPORTANT</b>: if you are using greylisting, and applied the
+ previous greylisting patch, it didn't create shell safe filenames,
+ it is therefore highly recommended that you apply the new version
+ <li>Added a quick patch to sa-exim to deal with headers that are longer
+ than 8K (and drop the remaining lines)
+ </ul>
+
+
+<li>2004/03/16 - v4.0 (<a href="files/sa-exim-4.0.tar.gz">sa-exim.tar.gz</a>
+or <a href="files/local_scan/local_scan.c_4.0">local_scan only</a>)
+ <ul>
+ <li>Added SAspamcpath (from Richard Lithvall)
+ <li>Makefile fixes for version.h and dependencies
+ <li>Added exim acl_m trick from Chirik in README
+ <li>New code to read and pass on any X-Spam- header from SpamAssassin
+ <li>Message-Id is now logged in SA log entries to allow you track down
+ a message in other logfiles, like SA's log
+ <li>Add X-SA-Exim-Connect-IP header for greylisting
+ <li>Allow for tempreject on messages not flagged as spam by SA (for
+ greylisting)
+ <li>Added greylisting support (see README.greylisting)
+ <li>Added the following options to sa-exim.conf:
+ <ul>
+ <li>SAspamcSockPath
+ <li>SAgreylistiswhitestr
+ <li>SAgreylistraisetempreject
+ </ul>
+ <li>Lots of documentation fixes and updates
+ <li>Basic debian tree shipped by default (but real deb package from Sander
+ Smeenk)
+ </ul>
+
+<li>2003/08/18 - v3.1 (<a href="files/sa-exim-3.1.tar.gz">sa-exim tar.gz</a>
+ or <a href="files/local_scan/local_scan.c_3.1">local_scan only</a>)
+ <ul>
+ <li>Fixed <em>SA: Action: teergrubed sender until full configured duration</em> output
+ <li>spamassassin.conf was renamed sa-exim.conf (bad initial name choice)
+ <li>Changed teergrubing so that it works with exim 4.20 and above
+ <li>Added the much requested SARewriteBody option for SA 2.50's report_safe
+ (courtesy of Richard Lithvall)
+ <li>Added SAaddSAEheaderBeforeSA to deal with SARewriteBody and privacy
+ <li>Added SAPrependArchiveWithFrom option (Richard Lithvall)
+ <li>As announced in the previous version, SAStallSender was removed.
+ Use Teergrubing instead
+ <li>Message-Id is read directly from Exim now that the API allows for that
+ (we used to parse the Message-Id header ourselves) -&gt; except that
+ we don't use this for logging or saving messages: as soon as we can
+ read the real Message-Id from the headers, we use that Message-Id for
+ logging (this is to facilitate tracking of messages from the logs and
+ correlating with something like SA timelog files)
+ <li>Logging improved some more: Message-Id is added to log entries, as
+ well as the full mailinfo whether the message is spam or not
+ </ul>
+
+<li>2003/04/30 - v3.0 (<a href="files/sa-exim-3.0.tar.gz">sa-exim tar.gz</a>
+ or <a href="files/local_scan/local_scan.c_3.0">local_scan only</a>)
+ <ul>
+ <li>Makefile can generate a short sa-exim.conf (for Brian Kendig)
+ <li>Added a contrib directory with 3rd party scripts
+ <li>Since we already had X-SA-Exim-Rcpt-To: to show the envelope to
+ (disabled by default), I added X-SA-Exim-Mail-From: to show the
+ envelope from (always enabled, but you can delete it in system_filter
+ if you wish). If you can't easily see or parse the envelope sender
+ in your mails, this should definitely help
+ <li>Much improved directory creation and error handling for the reject
+ save directories
+ <li>Added SIGCHLD patch from David Woodhouse
+ <li>Added version header that looks like this:
+ X-SA-Exim-Version: 2.2.x-cvs (built Tue Apr 22 10:28:25 PDT 2003)
+ <li>Rewrote pretty much every log message to be more consistent and grepable
+ (the previous ones were quite bad). Suggested by multiple people
+ including Brian Kendig
+ <li>Made the SMTP error messages finally configurable (suggested by
+ several people). This is now possible since exim lets me output a
+ different message in the log than in the SMTP session. Consequently, new
+ default messages do not show the spam score, this only goes to the exim
+ now.
+ <li>Made SAmaxrcptlistlength and option to control how long of a
+ X-SA-Exim-Rcpt-To header you can output if you want to output it at
+ all
+ <li>Do not output "savemail condition expanded to false" if not in debug
+ mode (as reported by Brian Kendig)
+ <li>Now ships with a sample local_scan.h if we can't find the exim source
+ <li>Change of logic to delete SA headers that were in the original mail
+ but weren't outputted by the SA run (like X-Spam-Flag, as reported
+ by Chad Leigh)
+ <li>Modified local_scan dlopen patch to deal with updates to the exim
+ local_scan API
+ <li>The default location for spamasassin.conf was changed to /etc/exim4
+ (debian default)
+ <li>Updated README and INSTALL
+ <li>Updated localscan_dlopen.patch to deal with minor/major version numbers
+ <li>Added X-SA-Exim-Version
+ </ul>
+<li>2002/10/28 - v2.2 (<a href="files/sa-exim-2.2.tar.gz">sa-exim tar.gz</a>
+ or <a href="files/local_scan/local_scan.c_2.2">local_scan only</a>)
+ <ul>
+ <li>Fixed a bug that affected all mails bigger than what spamc would
+ accept. Doh! (it not clear why, but spamc would hang and stop reading
+ after it had been fed more than it was willing to accept)
+ <li>Added more debugging code to help track the above problem
+ <li>Depending on SATruncBodyCond will now either not pass a message that's
+ too big to spamc, or will optionally truncate it first
+ <li>Now strips any X-SA-Exim-* headers already present in the message before
+ scanning it
+ <li>Added new X-SA-Exim-Rcpt-To: header (see privacy section in README)
+ after a suggestion from Brian Kendig
+ <li>Teergrube is now spelled correctly (note that the option names in
+ sa-exim.conf changed as a result)
+ <li>Teergrubing has been re-implemented to detect that the other side went
+ away so that exim doesn't stay around for nothing.
+ <li>Added SAteergrubecond so that you don't teergrube your neighbours
+ <li>Small cleanups
+ </ul>
+<li>2002/10/13 - v2.1 (buggy) (<a href="files/sa-exim-2.1.tar.gz">sa-exim tar.gz</a>
+ or <a href="files/local_scan/local_scan.c_2.1">local_scan only</a>)
+ <ul>
+ <li>Default mail config is now in /etc/exim instead of /etc/mail
+ <li>Fixed SAstallsender so that exim doesn't leave spool files behind
+ <li>Fixed comparison for spam values as suggested by Patrice Fournier
+ <li>Returned a header saying whether SA-Exim was able to scan the mail
+ or not (based on a suggestion from Patrice Fournier)
+ <li>Added support for teergrubing as suggested by Robert Strickler
+ (see
+ <A HREF="http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html">
+ http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html</A>)
+ <li>We now make sure that we feed spamc a little more data than it's
+ willing to accept. That way, we don't feed a truncated message
+ <li>sa-exim.conf now appends /new on save directories so that they
+ are valid maildir spool and you can run mutt -f dirname to read
+ <li>Small cleanups
+ </ul>
+
+<li>2002/07/07 - v2.0.1 (<a href="files/sa-exim-2.0.1.tar.gz">sa-exim tar.gz</a>
+ or <a href="files/local_scan/local_scan.c_2.0.1">local_scan only</a>)
+ <ul>
+ <li>Removed unneeded ## concatenation in macro
+ <li>Fixed lseek call, as reported by Peter N Lewis
+ <li>Improved Makefile for documentation
+ <li>Suggestion from dman to allow for config options overrides in Makefile
+ <li>Fixed all the compiler warnings that were fixable
+ <li>Handle more kinds of Message-Id as suggested by Patrice Fournier
+ </ul>
+
+<li>2002/06/14 - v2.0 (<a href="files/sa-exim-2.0.tar.gz">sa-exim tar.gz</a>
+ or <a href="files/local_scan/local_scan.c_2.0">local_scan only</a>)
+ <ul>
+ <li>Allow for stalling SMTP sessions from spammers (caution)
+ <li>Support X-Spam-Status from SA pre 2.30
+ <li>Build patches from Norm <norm@sandbox.org.uk>
+ <li>Documented that spamd shouldn't be run with -c
+ <li>dman's patch to allow for this to be a shared library
+ <li>dman's indirect request for saved files to be 660
+ </ul>
+<li><a href="files/local_scan/local_scan.c_2.0b1">2002/06/01 - v2.0b1</a><br>
+ This is how 1.0 would have been if I had done it right :-)
+ <ul>
+ <li>We now attempt to create directories we write to
+ (suggestion from Patrice Fournier)
+ <li>Log envelope sender, recipients and connecting host
+ on rejected messages (suggestion from Patrice Fournier)
+ <li>We can now save non rejected messages whether they were
+ flagged as spam or not (based on request from Patrice)
+ <li>Each save rule now has its own condition that lets you
+ decide which messages you want to save or not
+ <li>Fixed parsing of Message-Id. May not parse all of them
+ but won't do anything stupid with bad input
+ <li>Fixed a buglet where we removed old headers before knowing
+ whether they were going to be replaced.
+ <li>Added much needed internal alarm so that we don't run
+ too long
+ <li>I added lots of options, but weren't able to test all
+ of them and their combinations, please reports problems
+ you may notice and documentation issues (in config file)
+ <li>Thanks also go to dman for his plentiful feedback
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.3">2002/05/21 - v1.3</a>
+ <ul>
+ <li>We now close the files we create on disk. Duh!
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.2.2">2002/05/17 - v1.2.2</a>
+ <ul>
+ <li>SA options are now kept in memory. Small cleanups
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.2.1">2002/05/13 - v1.2.1</a>
+ <ul>
+ <li>v1.2 (unreleased) didn't work right: it tagged messages
+ properly, but failed to see what was marked as spam and
+ couldn't reject messages. Fixed.
+ <li>Stripped newlines in header lines (better for logging)
+ <li>fixed header_add bug if headers contained '%'
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.2">2002/05/12 - v1.2</a> (unreleased)
+ <ul>
+ <li>According to Craig R Hughes, any X-Spam header can be multiline.
+ Let's parse them accordingly
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.1.1">2002/05/08 - v1.1.1</a>
+ <ul>
+ <li>Added fake envelope from to mails that we save on disk
+ so that they can be opened with MUAs (idea from dman)
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.1">2002/05/07 - v1.1</a>
+ <ul>
+ <li>Cleaned up and fixed multiline header parsing
+ <li>Added parsing of Subject back from Spamc (suggestion from dman)
+ <li>We now log how long spamc took, and all messages processed
+ by spamc get logged in mainlog so that we know the outcome
+ <li>Added custom header compare function to handle mixed case headers
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.0.1">2002/05/06 - v1.0.1</a>
+ <ul>
+ <li>Fixed problems with reading Content-Type back from spamc
+ (we used to read whole body too, ooops...)
+ <li>Handle multi-line Content-Type headers.
+ <li>All log entries now start with "SA: "
+ <li>If SA gets run twice, we drop the previous X-Spam headers
+ <li>Support for X-Spam-Prev-Content-Transfer-Encoding
+ </ul>
+<li><a href="files/local_scan/local_scan.c_1.0">2002/05/05 - v1.0</a>
+ <ul>
+ <li>*Many* changes. This is now a real program with hopefully
+ most of the configuration options people could need
+ <li>Fully configurable through external config file
+ <li>Condition to run or not run SA against a message
+ <li>3 Levels of spam handling
+ <li>Option to save messages that are rejected or cause errors
+ <li>Very complete error checking
+ </ul>
+<li><a href="files/local_scan/local_scan.c_0.9.1">2002/04/17 - v0.9.1</a>
+ <ul>
+ <li>Added a few checks for possible failures
+ </ul>
+<li><a href="files/local_scan/local_scan.c_0.9">2002/04/16 - v0.9</a>
+ <ul>
+ <li>Pre-release
+ </ul>
+</ul>
Index: 4.2.1-7/eximinc/mytypes.h
===================================================================
--- 4.2.1-7/eximinc/mytypes.h (nonexistent)
+++ 4.2.1-7/eximinc/mytypes.h (revision 23)
@@ -0,0 +1,95 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2003 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+
+/* This header file contains type definitions and macros that I use as
+"standard" in the code of Exim and its utilities. Make it idempotent because
+local_scan.h includes it and exim.h includes them both (to get this earlier). */
+
+#ifndef MYTYPES_H
+#define MYTYPES_H
+
+
+#define FALSE 0
+#define TRUE 1
+#define TRUE_UNSET 2
+
+
+/* If gcc is being used to compile Exim, we can use its facility for checking
+the arguments of printf-like functions. This is done by a macro. */
+
+#ifdef __GNUC__
+#define PRINTF_FUNCTION __attribute__((format(printf,1,2)))
+#else
+#define PRINTF_FUNCTION
+#endif
+
+
+/* Some operating systems (naughtily, imo) include a definition for "uchar" in
+the standard header files, so we use "uschar". Solaris has u_char in
+sys/types.h. This is just a typing convenience, of course. */
+
+typedef int BOOL;
+typedef unsigned char uschar;
+
+
+/* These macros save typing for the casting that is needed to cope with the
+mess that is "char" in ISO/ANSI C. Having now been bitten enough times by
+systems where "char" is actually signed, I've converted Exim to use entirely
+unsigned chars, except in a few special places such as arguments that are
+almost always literal strings. */
+
+#define CS (char *)
+#define CSS (char **)
+#define US (unsigned char *)
+#define USS (unsigned char **)
+
+/* The C library string functions expect "char *" arguments. Use macros to
+avoid having to write a cast each time. We do this for string and file
+functions; for other calls to external libraries (which are on the whole
+special-purpose) we just use casts. */
+
+
+#define Uatoi(s) atoi(CS(s))
+#define Uatol(s) atol(CS(s))
+#define Uchdir(s) chdir(CS(s))
+#define Uchmod(s,n) chmod(CS(s),n)
+#define Uchown(s,n,m) chown(CS(s),n,m)
+#define Ufgets(b,n,f) fgets(CS(b),n,f)
+#define Ufopen(s,t) fopen(CS(s),CS(t))
+#define Ulink(s,t) link(CS(s),CS(t))
+#define Ulstat(s,t) lstat(CS(s),t)
+#ifdef O_BINARY /* This is for Cygwin, */
+#define Uopen(s,n,m) open(CS(s),(n)|O_BINARY,m) /* where all files must */
+#else /* be opened as binary */
+#define Uopen(s,n,m) open(CS(s),n,m) /* to avoid problems */
+#endif /* with CRLF endings. */
+#define Uread(f,b,l) read(f,CS(b),l)
+#define Urename(s,t) rename(CS(s),CS(t))
+#define Ustat(s,t) stat(CS(s),t)
+#define Ustrcat(s,t) strcat(CS(s),CS(t))
+#define Ustrchr(s,n) US strchr(CS(s),n)
+#define Ustrcmp(s,t) strcmp(CS(s),CS(t))
+#define Ustrcpy(s,t) strcpy(CS(s),CS(t))
+#define Ustrcspn(s,t) strcspn(CS(s),CS(t))
+#define Ustrftime(s,m,f,t) strftime(CS(s),m,f,t)
+#define Ustrlen(s) (int)strlen(CS(s))
+#define Ustrncat(s,t,n) strncat(CS(s),CS(t),n)
+#define Ustrncmp(s,t,n) strncmp(CS(s),CS(t),n)
+#define Ustrncpy(s,t,n) strncpy(CS(s),CS(t),n)
+#define Ustrpbrk(s,t) strpbrk(CS(s),CS(t))
+#define Ustrrchr(s,n) US strrchr(CS(s),n)
+#define Ustrspn(s,t) strspn(CS(s),CS(t))
+#define Ustrstr(s,t) US strstr(CS(s),CS(t))
+#define Ustrtod(s,t) strtod(CS(s),CSS(t))
+#define Ustrtol(s,t,b) strtol(CS(s),CSS(t),b)
+#define Ustrtoul(s,t,b) strtoul(CS(s),CSS(t),b)
+#define Uunlink(s) unlink(CS(s))
+
+#endif
+
+/* End of mytypes.h */
Index: 4.2.1-7/eximinc/store.h
===================================================================
--- 4.2.1-7/eximinc/store.h (nonexistent)
+++ 4.2.1-7/eximinc/store.h (revision 23)
@@ -0,0 +1,53 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2003 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* Header for Exim's memory allocation functions */
+
+#ifndef STORE_H
+#define STORE_H
+
+/* Define symbols for identifying the two store pools. */
+
+#define POOL_MAIN 0
+#define POOL_PERM 1
+
+/* This variable is set by store_get() to its yield, and by store_reset() to
+NULL. This allows string_cat() to optimize its store handling. */
+
+extern void *store_last_get;
+
+/* This variable contains the current store pool number. */
+
+extern int store_pool;
+
+/* Macros for calling the memory allocation routines with
+tracing information for debugging. */
+
+#define store_extend(addr,old,new) \
+ store_extend_3(addr, old, new, __FILE__, __LINE__)
+
+#define store_free(addr) store_free_3(addr, __FILE__, __LINE__)
+#define store_get(size) store_get_3(size, __FILE__, __LINE__)
+#define store_get_perm(size) store_get_perm_3(size, __FILE__, __LINE__)
+#define store_malloc(size) store_malloc_3(size, __FILE__, __LINE__)
+#define store_release(addr) store_release_3(addr, __FILE__, __LINE__)
+#define store_reset(addr) store_reset_3(addr, __FILE__, __LINE__)
+
+
+/* The real functions */
+
+extern BOOL store_extend_3(void *, int, int, char *, int); /* These use */
+extern void store_free_3(void *, char *, int); /* char * */
+extern void *store_get_3(int, char *, int); /* because */
+extern void *store_get_perm_3(int, char *, int); /* the */
+extern void *store_malloc_3(int, char *, int); /* value is */
+extern void store_release_3(void *, char *, int); /* always */
+extern void store_reset_3(void *, char *, int); /* __FILE__ */
+
+#endif /* STORE_H */
+
+/* End of store.h */
Index: 4.2.1-7/eximinc/local_scan.h
===================================================================
--- 4.2.1-7/eximinc/local_scan.h (nonexistent)
+++ 4.2.1-7/eximinc/local_scan.h (revision 23)
@@ -0,0 +1,150 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2003 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* This file is the header that is the only Exim header to be included in the
+source for the local_scan.c() function. It contains definitions that are made
+available for use in that function, and which are documented. */
+
+
+/* Some basic types that make some things easier, and the store functions. */
+
+#include <sys/types.h>
+#include "mytypes.h"
+#include "store.h"
+
+
+/* The function and its return codes. */
+
+extern int local_scan(int, uschar **);
+
+enum {
+ LOCAL_SCAN_ACCEPT, /* Accept */
+ LOCAL_SCAN_ACCEPT_FREEZE, /* Accept, but freeze */
+ LOCAL_SCAN_ACCEPT_QUEUE, /* Accept, but no immediate delivery */
+ LOCAL_SCAN_REJECT, /* Permanent rejection */
+ LOCAL_SCAN_REJECT_NOLOGHDR, /* Permanent rejection, no log header */
+ LOCAL_SCAN_TEMPREJECT, /* Temporary rejection */
+ LOCAL_SCAN_TEMPREJECT_NOLOGHDR /* Temporary rejection, no log header */
+};
+
+
+/* Return codes from the support functions lss_match_xxx(). */
+
+#define OK 0 /* Successful match */
+#define DEFER 1 /* Defer - some problem */
+#define FAIL 2 /* Matching failed */
+#define ERROR 3 /* Internal or config error */
+
+
+/* Available logging destinations */
+
+#define LOG_MAIN 1 /* Write to the main log */
+#define LOG_PANIC 2 /* Write to the panic log */
+#define LOG_REJECT 16 /* Write to the reject log, with headers */
+
+
+/* Accessible debugging bits */
+
+#define D_v 0x00000001
+#define D_local_scan 0x00000002
+
+
+/* Option types that can be used for local_scan_options. The boolean ones
+MUST be last so that they are contiguous with the internal boolean specials. */
+
+enum { opt_stringptr, opt_int, opt_octint, opt_mkint, opt_fixed, opt_time,
+ opt_bool };
+
+
+/* The length of message identification strings. This is the id used internally
+by exim. The external version for use in Received: strings has a leading 'E'
+added to ensure it starts with a letter. */
+
+#define MESSAGE_ID_LENGTH 16
+
+/* The offset to the start of the data in the data file - this allows for
+the name of the data file to be present in the first line. */
+
+#define SPOOL_DATA_START_OFFSET (MESSAGE_ID_LENGTH+3)
+
+/* local_scan() ABI version number for dynamic libraries
+ The major number is increased when the ABI is changed in a non
+ backward compatible way.
+ The minor number is increased each time a new feature is added (in a
+ way that doesn't break backward compatibility) -- Marc */
+#define LOCAL_SCAN_ABI_VERSION_MAJOR 1
+#define LOCAL_SCAN_ABI_VERSION_MINOR 0
+
+/* Structure definitions that are documented as visible in the function. */
+
+typedef struct header_line {
+ struct header_line *next;
+ int type;
+ int slen;
+ uschar *text;
+} header_line;
+
+/* Entries in lists options are in this form. */
+
+typedef struct {
+ char *name;
+ int type;
+ void *value;
+} optionlist;
+
+/*Structure for holding information about an envelope address. The errors_to
+field is always NULL except for one_time aliases that had errors_to on the
+routers that generated them. */
+
+typedef struct recipient_item {
+ uschar *address; /* the recipient address */
+ int pno; /* parent number for "one_time" alias, or -1 */
+ uschar *errors_to; /* the errors_to address or NULL */
+} recipient_item;
+
+
+/* Global variables that are documented as visible in the function. */
+
+extern unsigned int debug_selector; /* Debugging bits */
+
+extern uschar *expand_string_message; /* Error info for failing expansion */
+extern header_line *header_last; /* Final header */
+extern header_line *header_list; /* First header */
+extern BOOL host_checking; /* Set when checking a host */
+extern uschar *interface_address; /* Interface for incoming call */
+extern int interface_port; /* Port number for incoming call */
+extern uschar *message_id; /* Internal id of message being handled */
+extern uschar *received_protocol; /* Name of incoming protocol */
+extern int recipients_count; /* Number of recipients */
+extern recipient_item *recipients_list;/* List of recipient addresses */
+extern unsigned char *sender_address; /* Sender address */
+extern uschar *sender_host_address; /* IP address of sender, as chars */
+extern uschar *sender_host_authenticated; /* Name of authentication mechanism */
+extern uschar *sender_host_name; /* Host name from lookup */
+extern int sender_host_port; /* Port number of sender */
+
+
+/* Functions that are documented as visible in local_scan(). */
+
+extern int child_close(pid_t, int);
+extern pid_t child_open_exim(int *);
+extern void debug_printf(char *, ...) PRINTF_FUNCTION;
+extern uschar *expand_string(uschar *);
+extern void header_add(int, char *, ...);
+extern void log_write(unsigned int, int, char *format, ...);
+extern int lss_b64decode(uschar *, uschar **);
+extern uschar *lss_b64encode(uschar *, int);
+extern int lss_match_domain(uschar *, uschar *);
+extern int lss_match_local_part(uschar *, uschar *, BOOL);
+extern int lss_match_address(uschar *, uschar *, BOOL);
+extern int lss_match_host(uschar *, uschar *, uschar *);
+extern void receive_add_recipient(uschar *, int);
+extern uschar *string_copy(uschar *);
+extern uschar *string_copyn(uschar *, int);
+extern uschar *string_sprintf(char *, ...);
+
+/* End of local_scan.h */
Index: 4.2.1-7/eximinc/version
===================================================================
--- 4.2.1-7/eximinc/version (nonexistent)
+++ 4.2.1-7/eximinc/version (revision 23)
@@ -0,0 +1 @@
+exim-4.14
Index: 4.2.1-7/eximinc/README
===================================================================
--- 4.2.1-7/eximinc/README (nonexistent)
+++ 4.2.1-7/eximinc/README (revision 23)
@@ -0,0 +1,6 @@
+In order to faciliate building on systems that have exim installed but don't
+have the exim source, I am including includes from a recent exim version.
+While I am keeping track of which version, this shouldn't be necessary as
+the local_scan API is supposed to be upward compatible
+(technically, we should raise LOCAL_SCAN_ABI_VERSION every time Philip
+adds a feature to the API -- Marc)
Index: 4.2.1-7/README.greylisting
===================================================================
--- 4.2.1-7/README.greylisting (nonexistent)
+++ 4.2.1-7/README.greylisting (revision 23)
@@ -0,0 +1,258 @@
+ GREYLISTING with SA-Exim
+ ------------------------
+
+
+INTRODUCTION
+------------
+SA-Exim allows for intelligent greylisting by combining the idea of greylisting
+with Spam scores from SpamAssassin
+
+If you don't know what greylisting is, you should probably go read up there:
+http://projects.puremagic.com/greylisting/
+(note that this implementation works differently than the one described there)
+
+So, SA-Exim isn't just yet another greylisting implementation. By tying it
+into SA-Exim, and especially by running SA at SMTP time, you can do the
+following things:
+- do not bother greylisting people who send messages detected as spam by SA
+ (indeed, regular greylisting will accept mail from a spammer if he retries
+ or sends it from an open relay)
+ SA-Exim will never greylist, or whitelist a sender based on a mail clearly
+ marked as spam by SA.
+
+- do not delay mail from people who aren't spamming you (this one is the most
+ important feature of SA-Exim greylisting, as it removes the biggest
+ disadvantage linkes to greylisting)
+
+- only greylist (and maybe later whitelist) hosts that send you mail with
+ a certain SA score.
+
+
+IMPLEMENTATION
+--------------
+So how does this all work?
+SA comes with a patch for SA 2.x (and a module for SA 3.x) that does the
+following things:
+- add a greylisting rule which gets run at the very end, and where if
+ the score is already higher than a configured value, we do not bother
+ greylisting the host. We just return a rule failure, which doesn't
+ change the score and lets SA-Exim reject the mail as usual
+- if the score is lower than the "surely spam" threshold (shown as 11 in the
+ example below), check for a file in
+ /var/spool/sa-exim/messageids/co/nn/ect/ip/envfrom/envto
+ - if it's there, check if it was written more than x seconds ago (1800s/30mn
+ in the example below)
+ - if so, change the status to whitelisted and return true so that SA applies
+ the whitelist negative score
+ - if not, simply increase counters, host is still greylisted
+ - if the file is not there, create it
+- every x time (like 4 hours or two days), remove all greylist entries that
+ only saw one mail (i.e. still greylisted, not whitelisted yet).
+ This is done with a find cron job
+- every y time (like 1 week), remove whitelisted entries so that your filesystem
+ doesn't clutter up with hosts you're not going to hear from again in a while
+
+
+Then, you call the greylisting rule with this (in SA's local.cf)
+# reseval is a special eval which only runs after you have the result from
+# everything else (lets us not greylist a host that is sending spam, otherwise
+# this rule might set a sufficiently negative score that the next spam would
+# be allowed in)
+# Note the 'key' -> 'value'; syntax. It's a special hack to go through SA's
+# config parser. You need to keep that exact syntax
+# greylistsecs: how long you greylist a tuplet because whitelisting it
+# greylistnullfrom: set to 1 to also greylist mail with a null env from
+# greylistfourthbyte: keep the 4 bytes of the connecting host instead of 3
+header GREYLIST_ISWHITE reseval:greylisting("( 'dir' => '/var/spool/sa-exim/tuplets'; 'method' => 'dir'; 'greylistsecs' => '1800'; 'dontgreylistthreshold' => 11; 'connectiphdr' => 'X-SA-Exim-Connect-IP'; 'envfromhdr' => 'X-SA-Exim-Mail-From'; 'rcpttohdr' => 'X-SA-Exim-Rcpt-To'; 'greylistnullfrom' => 0; 'greylistfourthbyte' => 0 )")
+describe GREYLIST_ISWHITE The incoming server has been whitelisted for this rece
+ipient and sender
+score GREYLIST_ISWHITE -1.5
+
+Note that SA greylisting depends on X-SA-Exim-Rcpt-To, so you have to ensure
+that SAmaxrcptlistlength is set to a reasonably high value (up to 8000) instead
+of the current default of 0 (you can remove the header in exim's system_filter
+or a transport if you don't want it to show in user's mails, see "privacy
+warning" in README)
+
+
+Now, in case you aren't confused yet, you get even more knobs to play with :)
+If a spammer resends you a spam until it gets whitelisted (or typically, it
+gets sent to a relay that resends it to you), even if you are setup to
+accept the spam at the point, you don't want to lower the SA score too much
+just because the mail was resent to you several times (i.e. a rather negative
+score for GREYLIST_ISWHITE). So, you can actually configure SA-Exim to temp
+reject messages on a much higher score than usual, if they don't have the
+GREYLIST_ISWHITE tag.
+
+In other words, let's say you have this in sa-exim.conf:
+SApermreject: 11.0
+SAtempreject: 3.0
+SAgreylistraisetempreject: 6.5
+
+If a mail comes in at less than 3.0, the SA patch/module remembers the sending
+server's connecting IP, the env from, and the rcpt to(s), and whitelists those.
+(those will be referred to as tuplets, one for each rcpt to)
+
+If the score is between 3.0 and 11.0,
+- if at least one of the tuplets is already whitelisted, SA applies the -1.5
+ score and yields an end score below 9.5, Now, at the same time, SAtempreject
+ is temporarily raised by 6.5, so everything under 9.5 is accepted, which
+ basically means that the mail goes through.
+- if none of the tuplets are whitelisted, they get greylisted
+- if they are greylisted, they can get upgraded to whitelisted status if the
+ sending server has been trying for long enough (1800secs in the example given
+ above). At this point the same thing happens as in case #1 and the mail is
+ accepted
+
+If a tuplet that is going to be whitelisted or greylisted, already is, SA
+updates counters to let you run reports and anything else you want, like
+deciding if or when you'd like to expire the entry
+
+If by now you wonder why you would want to both decrease the SA score and
+increase the maximum score you'll accept mails on, the reason is as follows:
+You probably don't want to lower the SA score by 8 just because the tuplet
+is whitelisted (not only does it mess with the SA scoring of messages that used
+to be flagged as spam, but a spam with a score of 13.5 would then be lowered
+to 5.5, be temprejected, and be close to the accept range).
+Instead, giving an SA score of -1.5, a message with 13.5 becomes 12.0 and still
+gets rejected right away. You also do not overly (and artifically) lower the
+score of a message, just for SA-Exim's sake
+
+If you so wish, you can also give the SA rule a score of -0.1, and only
+dynamically raise the tempreject score for messages that are whitelisted.
+
+
+SCORE SETUP
+-----------
+It makes little sense to have
+SAtempreject + SAgreylistraisetempreject + SA GREYLIST_ISWHITE > SApermreject
+as there is little point to raise SAtempreject if the message that's
+whitelisted still gets refused by the SApermreject score
+
+As to whether you want to put more points into SA GREYLIST_ISWHITE or
+SAgreylistraisetempreject, this is your call, but as a general rule, you only
+want to change the SA score in a way that makes sense for spam scoring,
+as it similarly affects the score of all messages, whether SA-Exim sees them
+in the non spam range, tempreject range, or "this is spam that I would never
+let in" range.
+
+
+FILE SETUP
+----------
+Make very sure that uid nobody can traverse /var/spool/sa-exim and
+create tuplets writeable by nobody (or whoever you run SA as)
+
+Then, setup a cron job to delete tuplets that are older than 14 days for
+whitelisted entries, and 2 days for greylisted entries (or whatever
+values you fancy).
+Note that because this implementation does not systematically force the senders to resend you mail, unless they sent something that looks too much like spam,
+you will typically see few whitelisted entries, and those will either be
+potential spam that was actually resent to you at least 30mn after the
+initial copy (or whatever value you setup in "header GREYLIST_ISWHITE"), or
+people who sent you several Emails (where the second Email will just happen to
+trigger a whitelisting).
+
+
+FILE SETUP
+----------
+You should install greylistclean.cron in /etc/cron.d/ on your system to
+call greylistclean and clean up greylisted entries and whitelisted entries
+that haven't been used in a while.
+You can optionally modify it to tweak the cleanup times.
+Note that you need to tweak greylistclean.cron to match the user spamd runs
+as if you aren't using the recommended --username=nobody
+
+
+SA PATCH (SA 2.x)
+-----------------
+For all this to work, you also need to patch SA with SA-greylist.diff
+from the source tar (or /usr/share/doc/sa-exim*/ for a precompiled package).
+This patch never made it to the main SA 2.x branch as the developers had mostly
+switched to 3.x where you can use plugins.
+If you still use SA 3.x, you can go to /usr/share/perl5/Mail (or wherever
+appropriate on your system), and run
+patch -p0 -s < /path/to/sa-exim/SA-greylisting.diff
+Note that while the patch works, it will not be maintained anymore since
+it is deprecated for the SA 3.x plugin
+
+
+SA PLUGIN (SA 3.x)
+------------------
+Newer versions of SpamAssassin support plugins, so there is no need to
+patch SA anymore, you can just install the Greylisting.pm module on your
+system and get SA to use it
+This is how you call the module in SA 3.x (i.e. put this in your
+/etc/spamassassin/local.cf)
+
+# Note the 'key' -> 'value'; syntax. It's a special hack to go through SA's
+# config parser. You need to keep that exact syntax
+# greylistsecs: how long you greylist a tuplet because whitelisting it
+# greylistnullfrom: set to 1 to also greylist mail with a null env from
+# greylistfourthbyte: keep the 4 bytes of the connecting host instead of 3
+loadplugin Greylisting /usr/share/perl5/Mail/SpamAssassin/Plugin/Greylisting.pm
+header GREYLIST_ISWHITE eval:greylisting("( 'dir' => '/var/spool/sa-exim/tuplets'; 'method' => 'dir'; 'greylistsecs' => '1800'; 'dontgreylistthreshold' => 11; 'connectiphdr' => 'X-SA-Exim-Connect-IP'; 'envfromhdr' => 'X-SA-Exim-Mail-From'; 'rcpttohdr' => 'X-SA-Exim-Rcpt-To'; 'greylistnullfrom' => 1; 'greylistfourthbyte' => 0 )")
+describe GREYLIST_ISWHITE The incoming server has been whitelisted for this recipient and sender
+score GREYLIST_ISWHITE -1.5
+# Run SpamAssassin last, after all other rules.
+# (lets us not greylist a host that is sending spam, otherwise this rule might
+# set a sufficiently negative score that the next spam would be allowed in)
+priority GREYLIST_ISWHITE 99999
+
+
+SA-EXIM NEW BEHAVIOR CONCERNS
+-----------------------------
+What greylisting changes as far as spam accepting or rejection is concerned:
+Once a tuplet has been whitelisted, spam from that host is more likely
+to be accepted until the tuplet expires. In the case of a mailing list,
+unless you run a find / rm based on the creation time and not the last
+modified time, you will then be a bit more likely to accept spam from
+that list.
+If this turns out to not be acceptable in your case, there isn't a whole
+lot you can do about this, except deleting greylist entries for the host
+from cron before they get promoted to whitelist.
+
+What you can do on top of the existing greylisting code:
+Parse the SA-Exim logs and if you get spam from an IP, you can decide
+to delete greylist entries in /var/spool/sa-exim/tuplets/IP or just
+/var/spool/sa-exim/tuplets/IP/envfrom
+This may not may not be a good thing if you receive the occasional spam
+from a mailing list as you'll then re-delay mail for that list, but then
+again, it will also remove whitelisting for a host that spammed you once
+with an Email that managed to get under the SA scoring radar
+
+
+GREYLISTING AND MXES
+--------------------
+Depending on your configuration, you may have realized that SA-Exim doesn't
+play very well with secondary MXes for your domain if they don't run SA-Exim
+too (for instance, you'd send a tempreject on spam and clog up your
+secondary, or maybe even teergrube it if you forgot to add your MX's IP
+in the do not teergrube list.
+For greylisting, it's even more simple:
+If your secondary MXes aren't running SA-Exim with greylisting, then
+greylisting's efficiency will be greatly reduced as most spammers will send
+their spams to your secondary MXes which will accept the mail for you,
+even if it's sent only once, and then your MXes will resend the spam to you
+until you accept it (rendering greylisting useless)
+
+Now, if your secondaries are running greylisting too, most mail will flow
+through with no delay whatsoever. However, in the worst case scenario, a mail
+that isn't spam, but triggers greylisting because its score is high enough to
+generate a tempreject, could be delayed up to twice the whitelisting time
+if it were to go to your secondary MX first (assuming your primary is
+unreachable or temporarily overloaded), and then be resent to your primary
+MX, which would trigger a second greylisting delay
+FIXME: implement a whitelist of sending IPs so that greylisting returns
+whitelisted right away
+
+
+SECURITY
+--------
+The greylisting function works around the SA parser by sending all the options
+as a hash inside a string. In turn, greylisting evals the said string.
+This is a security problem if you allow your users to run custom rules and it
+gives them access to run spamassassin as a user different from their own, or
+in a way that they otherwise wouldn't be able to.
+Do not run greylisting if this a problem for you (in the default SA/SA-Exim
+setup, this shouldn't be a concern since it doesn't even parse users' config
+files)
Index: 4.2.1-7/localscan_dlopen_up_to_exim_4.14.patch
===================================================================
--- 4.2.1-7/localscan_dlopen_up_to_exim_4.14.patch (nonexistent)
+++ 4.2.1-7/localscan_dlopen_up_to_exim_4.14.patch (revision 23)
@@ -0,0 +1,287 @@
+The initial version of this patch was originally posted David Woodhouse, and
+dman gets the credit for first integrating it with SA-Exim.
+
+I have since then maintained it by first making a few minor changes, and
+later switching it to a major/minor number scheme to support upgrades in
+the exim API that don't affect backward compatibility (you can rely on
+a feature denoted by the minor number and be compatible with future versions
+of exim until Philip has to break the API and increase the major number)
+
+Marc MERLIN <marc_soft@merlins.org>
+
+diff -urN exim-4.14-0/src/EDITME exim-4.14-1/src/EDITME
+--- exim-4.14-0/src/EDITME Tue Mar 11 04:20:18 2003
++++ exim-4.14-1/src/EDITME Sun Mar 23 15:34:15 2003
+@@ -388,6 +388,20 @@
+
+
+ #------------------------------------------------------------------------------
++# On systems which support dynamic loading of shared libraries, Exim can
++# load a local_scan function specified in its config file instead of having
++# to be recompiled with the desired local_scan function. For a full
++# description of the API to this function, see the Exim specification.
++
++DLOPEN_LOCAL_SCAN=yes
++
++# If you set DLOPEN_LOCAL_SCAN, then you need to include -rdynamic in the
++# linker flags. Without it, the loaded .so won't be able to access any
++# functions from exim.
++
++LFLAGS=-rdynamic -ldl
++
++#------------------------------------------------------------------------------
+ # The default distribution of Exim contains only the plain text form of the
+ # documentation. Other forms are available separately. If you want to install
+ # the documentation in "info" format, first fetch the Texinfo documentation
+diff -urNad 50_localscan_dlopen.tmp/src/config.h.defaults 50_localscan_dlopen/src/config.h.defaults
+--- 50_localscan_dlopen.tmp/src/config.h.defaults Sun Dec 29 11:55:42 2002
++++ 50_localscan_dlopen/src/config.h.defaults Sun Dec 29 11:56:44 2002
+@@ -17,6 +17,8 @@
+ #define AUTH_PLAINTEXT
+ #define AUTH_SPA
+
++#define DLOPEN_LOCAL_SCAN
++
+ #define BIN_DIRECTORY
+
+ #define CONFIGURE_FILE
+diff -urN exim-4.14-0/src/globals.c exim-4.14-1/src/globals.c
+--- exim-4.14-0/src/globals.c Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/globals.c Sun Mar 23 15:34:15 2003
+@@ -103,6 +103,9 @@
+ uschar *tls_verify_hosts = NULL;
+ #endif
+
++#ifdef DLOPEN_LOCAL_SCAN
++uschar *local_scan_path = NULL;
++#endif
+
+ /* Input-reading functions for messages, so we can use special ones for
+ incoming TCP/IP. The defaults use stdin. We never need these for any
+diff -urN exim-4.14-0/src/globals.h exim-4.14-1/src/globals.h
+--- exim-4.14-0/src/globals.h Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/globals.h Sun Mar 23 15:34:15 2003
+@@ -67,6 +67,9 @@
+ extern uschar *tls_verify_hosts; /* Mandatory client verification */
+ #endif
+
++#ifdef DLOPEN_LOCAL_SCAN
++extern uschar *local_scan_path; /* Path to local_scan() library */
++#endif
+
+ /* Input-reading functions for messages, so we can use special ones for
+ incoming TCP/IP. */
+diff -urN exim-4.14-0/src/local_scan.c exim-4.14-1/src/local_scan.c
+--- exim-4.14-0/src/local_scan.c Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/local_scan.c Sun Mar 23 15:34:15 2003
+@@ -5,60 +5,131 @@
+ /* Copyright (c) University of Cambridge 1995 - 2003 */
+ /* See the file NOTICE for conditions of use and distribution. */
+
++#include "exim.h"
+
+-/******************************************************************************
+-This file contains a template local_scan() function that just returns ACCEPT.
+-If you want to implement your own version, you should copy this file to, say
+-Local/local_scan.c, and edit the copy. To use your version instead of the
+-default, you must set
+-
+-LOCAL_SCAN_SOURCE=Local/local_scan.c
+-
+-in your Local/Makefile. This makes it easy to copy your version for use with
+-subsequent Exim releases.
+-
+-For a full description of the API to this function, see the Exim specification.
+-******************************************************************************/
+-
+-
+-/* This is the only Exim header that you should include. The effect of
+-including any other Exim header is not defined, and may change from release to
+-release. Use only the documented interface! */
+-
+-#include "local_scan.h"
+-
+-
+-/* This is a "do-nothing" version of a local_scan() function. The arguments
+-are:
+-
+- fd The file descriptor of the open -D file, which contains the
+- body of the message. The file is open for reading and
+- writing, but modifying it is dangerous and not recommended.
+-
+- return_text A pointer to an unsigned char* variable which you can set in
+- order to return a text string. It is initialized to NULL.
+-
+-The return values of this function are:
+-
+- LOCAL_SCAN_ACCEPT
+- The message is to be accepted. The return_text argument is
+- saved in $local_scan_data.
+-
+- LOCAL_SCAN_REJECT
+- The message is to be rejected. The returned text is used
+- in the rejection message.
+-
+- LOCAL_SCAN_TEMPREJECT
+- This specifies a temporary rejection. The returned text
+- is used in the rejection message.
+-*/
++#ifdef DLOPEN_LOCAL_SCAN
++#include <dlfcn.h>
++static int (*local_scan_fn)(int fd, uschar **return_text) = NULL;
++static int load_local_scan_library(void);
++#endif
+
+ int
+ local_scan(int fd, uschar **return_text)
+ {
+ fd = fd; /* Keep picky compilers happy */
+ return_text = return_text;
+-return LOCAL_SCAN_ACCEPT;
++#ifdef DLOPEN_LOCAL_SCAN
++/* local_scan_path is defined AND not the empty string */
++if (local_scan_path && *local_scan_path)
++ {
++ if (!local_scan_fn)
++ {
++ if (!load_local_scan_library())
++ {
++ char *base_msg , *error_msg , *final_msg ;
++ int final_length = -1 ;
++
++ base_msg=US"Local configuration error - local_scan() library failure\n";
++ error_msg = dlerror() ;
++
++ final_length = strlen(base_msg) + strlen(error_msg) + 1 ;
++ final_msg = (char*)malloc( final_length*sizeof(char) ) ;
++ *final_msg = '\0' ;
++
++ strcat( final_msg , base_msg ) ;
++ strcat( final_msg , error_msg ) ;
++
++ *return_text = final_msg ;
++ return LOCAL_SCAN_TEMPREJECT;
++ }
++ }
++ return local_scan_fn(fd, return_text);
++ }
++else
++#endif
++ return LOCAL_SCAN_ACCEPT;
++}
++
++#ifdef DLOPEN_LOCAL_SCAN
++
++static int load_local_scan_library(void)
++{
++/* No point in keeping local_scan_lib since we'll never dlclose() anyway */
++void *local_scan_lib = NULL;
++int (*local_scan_version_fn)(void);
++int vers_maj;
++int vers_min;
++
++local_scan_lib = dlopen(local_scan_path, RTLD_NOW);
++if (!local_scan_lib)
++ {
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library open failed - "
++ "message temporarily rejected");
++ return FALSE;
++ }
++
++local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_major");
++if (!local_scan_version_fn)
++ {
++ dlclose(local_scan_lib);
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
++ "local_scan_version_major() function - message temporarily rejected");
++ return FALSE;
++ }
++
++/* The major number is increased when the ABI is changed in a non
++ backward compatible way. */
++vers_maj = local_scan_version_fn();
++
++local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_minor");
++if (!local_scan_version_fn)
++ {
++ dlclose(local_scan_lib);
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
++ "local_scan_version_minor() function - message temporarily rejected");
++ return FALSE;
++ }
++
++/* The minor number is increased each time a new feature is added (in a
++ way that doesn't break backward compatibility) -- Marc */
++vers_min = local_scan_version_fn();
++
++
++if (vers_maj != LOCAL_SCAN_ABI_VERSION_MAJOR)
++ {
++ dlclose(local_scan_lib);
++ local_scan_lib = NULL;
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible major"
++ "version number, you need to recompile your module for this version"
++ "of exim (The module was compiled for version %d.%d and this exim provides"
++ "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
++ LOCAL_SCAN_ABI_VERSION_MINOR);
++ return FALSE;
++ }
++else if (vers_min > LOCAL_SCAN_ABI_VERSION_MINOR)
++ {
++ dlclose(local_scan_lib);
++ local_scan_lib = NULL;
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible minor"
++ "version number, you need to recompile your module for this version"
++ "of exim (The module was compiled for version %d.%d and this exim provides"
++ "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
++ LOCAL_SCAN_ABI_VERSION_MINOR);
++ return FALSE;
++ }
++
++local_scan_fn = dlsym(local_scan_lib, "local_scan");
++if (!local_scan_fn)
++ {
++ dlclose(local_scan_lib);
++ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
++ "local_scan() function - message temporarily rejected");
++ return FALSE;
++ }
++
++return TRUE;
+ }
++
++#endif /* DLOPEN_LOCAL_SCAN */
+
+ /* End of local_scan.c */
+diff -urN exim-4.14-0/src/local_scan.h exim-4.14-1/src/local_scan.h
+--- exim-4.14-0/src/local_scan.h Tue Mar 11 04:20:20 2003
++++ exim-4.14-1/src/local_scan.h Sun Mar 23 15:34:57 2003
+@@ -71,6 +71,15 @@
+
+ #define SPOOL_DATA_START_OFFSET (MESSAGE_ID_LENGTH+3)
+
++/* local_scan() ABI version number for dynamic libraries
++ The major number is increased when the ABI is changed in a non
++ backward compatible way.
++ The minor number is increased each time a new feature is added (in a
++ way that doesn't break backward compatibility) -- Marc */
++#define LOCAL_SCAN_ABI_VERSION_MAJOR 1
++#define LOCAL_SCAN_ABI_VERSION_MINOR 0
++#define LOCAL_SCAN_ABI_VERSION \
++ LOCAL_SCAN_ABI_VERSION_MAJOR.LOCAL_SCAN_ABI_VERSION_MINOR
+
+ /* Structure definitions that are documented as visible in the function. */
+
+diff -urN exim-4.14-0/src/readconf.c exim-4.14-1/src/readconf.c
+--- exim-4.14-0/src/readconf.c Tue Mar 11 04:20:22 2003
++++ exim-4.14-1/src/readconf.c Sun Mar 23 15:34:15 2003
+@@ -182,6 +182,9 @@
+ { "local_from_prefix", opt_stringptr, &local_from_prefix },
+ { "local_from_suffix", opt_stringptr, &local_from_suffix },
+ { "local_interfaces", opt_stringptr, &local_interfaces },
++#ifdef DLOPEN_LOCAL_SCAN
++ { "local_scan_path", opt_stringptr, &local_scan_path },
++#endif
+ { "local_scan_timeout", opt_time, &local_scan_timeout },
+ { "local_sender_retain", opt_bool, &local_sender_retain },
+ { "localhost_number", opt_stringptr, &host_number_string },
Index: 4.2.1-7/Acknowledgements.html
===================================================================
--- 4.2.1-7/Acknowledgements.html (nonexistent)
+++ 4.2.1-7/Acknowledgements.html (revision 23)
@@ -0,0 +1,119 @@
+While I wrote SA-Exim after realizing that I didn't want to accept Spam in the
+first place, this package would not have been put together without the help
+and contributions of the following people:
+
+
+<ul>
+<li>Philip Hazel<BR>
+ We wouldn't have exim without him :-)
+
+<li>Justin Mason, Craig R Hughes, Dan Quinlan, and the rest of the SpamAssassin
+ crew<BR>
+
+<li>Derrick 'dman' Hudson<BR>
+ Early adopter, feedback, ideas, first integration with localscan_dlopen
+
+<li>David Woodhouse<BR>
+ Excellent original localscan_dlopen patch for exim 4
+ SIGCHLD patch (was set to ignore by exim)
+
+<li>Norm<BR>
+ Build patches and trailing slash problem for mkdir on netbsd
+
+<li>Patrice Fournier<BR>
+ Several suggestions, including adding the X-SA-Exim-Scanned header
+
+<li>Peter N Lewis<BR>
+ Spotted a buglet in lseek call
+
+<li>Robert Strickler<BR>
+ Suggested that I add teergrube support
+
+<li>Tim Jackson<BR>
+ Narrowed the problem with SA Exim 2.1 to a hang when we feed a message
+ that's too big to spamc and did a lot of research on the bug
+
+<li>Brian Kendig<BR>
+ Suggested the functionality behind X-SA-Exim-Rcpt-To:
+ Noted and requested logging changes
+
+<li>Paul Matthews<BR>
+ Reported string length problem with X-SA-Exim-Rcpt-To:
+
+<li>Chad Leigh<BR>
+ Reported that SA-Exim doesn't delete a X-Spam-Flag header in the original
+ mail if the local config decides that the mail isn't spam
+
+<li>Martin Balvers<BR>
+ Reported that
+ SA: Action: teergrubed sender until full configured duration
+ logging wasn't consistent.
+ Author of http://nossie.addicts.nl/projects/sa-exim-stats/
+
+<li>Andreas Metzler<BR>
+ Has provided invaluable help by being the main maintainer of the exim4
+ debian package and doing most of the work for the sa-exim package, while
+ patiently helping me with my debian build questions
+
+<li>Richard Lithvall<BR>
+ Added the much requested SARewriteBody option for SA 2.50's report_safe
+ Also added SAPrependArchiveWithFrom option<BR>
+ Also added SAspamcSockPath for SA 2.60 and better
+
+<li>Justin F. Knotzke<BR>
+ Reported that Dec 31st 1969 isn't a good idea and upsets some MUAs like mutt
+
+<li>Norihisa Washitake<BR>
+ Pointed out that I should be using date -R to override foreign locales
+
+<li>Chirik<BR>
+ Made suggestions on increasing logging consistency
+ Gave example on how you can trigger mail scans without using headers
+ (using internal exim acl variables)
+
+<li>Ross Boylan<BR>
+ Suggestions for documentation tweaks
+
+<li>Sander Smeenk<BR>
+ Made sa-exim show up in Debian. Yeah! :)
+ Major doc diffs
+
+<li>Stéphane MANHES<BR>
+ Pointed out that greylisting requires X-SA-Exim-Rcpt-To:
+
+<li>John Horne<BR>
+ Reported crash on discard, due to the number of recipients being 0
+
+<li>Adam D. Barratt<BR>
+ Found the problem with sa-exim's indirect use of printf and causing a crash
+ in exim on 64 bit architectures, and gave a detailed explanation on what
+ happened and how to fix it
+
+<li>Jeffrey D. Carter<BR>
+ Suggested strchr instead of index for easier compilation.
+
+<li>Danilo Lotina F. &amp; Others<BR>
+ Suggested adding a destination host for spamc (I added a port too)
+
+<li>Cliff Hones<BR>
+ Reported that From mbox line was in an incorrect format
+
+<li>Jason John Schwarz<BR>
+ Reported compile problem inside the exim tree (i.e. without local_scan)
+
+<li>Kristopher Austin<BR>
+ Initial port of the SA patch to an SA 3.0 plugin
+
+<li>Adam Tilghman<BR>
+ Pointed out that I shouldn't be rewriting Content-Type headers if we don't
+ rewrite the body (and defang_mime is dead now)
+
+<li>Mark Lawrence<BR>
+ He is the author of the greylistclean cron job
+
+<li>Chris Morris<BR>
+ Reported the ealier tuplet deletion cronjob in shell as insecure
+
+<li>Your name here<BR>
+ If you contribute or if you did and I forgot your name (sorry, let me know)
+</ul>
Index: 4.2.1-7/contrib/sa-exim-stats.txt
===================================================================
--- 4.2.1-7/contrib/sa-exim-stats.txt (nonexistent)
+++ 4.2.1-7/contrib/sa-exim-stats.txt (revision 23)
@@ -0,0 +1,3 @@
+See this page:
+
+http://nossie.addicts.nl/projects/sa-exim-stats/
Index: 4.2.1-7/contrib/spam_resend.txt
===================================================================
--- 4.2.1-7/contrib/spam_resend.txt (nonexistent)
+++ 4.2.1-7/contrib/spam_resend.txt (revision 23)
@@ -0,0 +1,70 @@
+From: Richard Lithvall <richard@lithvall.nu>
+Date: Mon, 24 Mar 2003 16:31:40 +0100
+To: sa-exim@lists.merlins.org
+Subject: [SA-exim] Rejecting spam at SMTP but forward it to its recipients
+
+Hi list members!
+
+As the lazy postmaster I am I don't want to check every mail caught by
+SA for false positives but I really want to reject the damn spam at SMTP
+time.
+Therefore I wrote this little perl hack delegating this responsibilty to
+my users (they all use exim filters to file mail tagged as spam into a
+Junk folder).
+
+It works as follows.
+- Configure SA-exim to save rejected mail into a directory
+- Run the perl script attatched below from cron, let's say, once an hour
+(as user mail or whoever that runs your exim)
+- Inform your users how things work and their responsibilites to check
+for false positives.
+
+Please comment this script/hack and I'd really love to get some English
+spelling/grammar check as well :-)
+
+/Richard
+
+
+#!/usr/bin/perl
+$dir = "/var/spool/exim4/SApermrejectsave/new";
+foreach $mail (<$dir/*>) {
+ if(-f $mail){
+ open(MAIL, $mail);
+# print "Working on: " . $mail . "\n";
+ $from = <MAIL>;
+ $from =~ s/^From\s(.+?)\s.+\n/$1/;
+ while (<MAIL>){
+ if(/^X-SA-Exim-Rcpt-To:\s(.+)/){
+ @rcpts = split(/, /, $1);
+ last;
+ }
+ if(/^$/){
+ last;
+ }
+ }
+ open(BSMTP, "| /usr/sbin/exim4 -bS");
+ print BSMTP "mail from:<" . $from . ">\n";
+ foreach $rcpt (@rcpts){
+ print BSMTP "rcpt to:<" . $rcpt . ">\n";
+ }
+ print BSMTP "data\n";
+ print BSMTP "X-Spam-Notice: This mail was rejected
+during reception due to heuristic check marked it as spam,\n";
+ print BSMTP "\tbut forwarded to You for checking for
+false positives.\n";
+ seek(MAIL, 0, 0);
+ $throw_away_first_from_line = <MAIL>;
+ while (<MAIL>){
+ if(/^\./){
+ print BSMTP ".";
+ }
+ print BSMTP;
+ }
+ close(MAIL);
+ print BSMTP ".\n";
+ print BSMTP "quit\n";
+ close(BSMTP);
+ unlink($mail);
+ }
+}
+
Index: 4.2.1-7/SA-greylisting-2.4x.diff
===================================================================
--- 4.2.1-7/SA-greylisting-2.4x.diff (nonexistent)
+++ 4.2.1-7/SA-greylisting-2.4x.diff (revision 23)
@@ -0,0 +1,264 @@
+Note, this patch is unmaintained. It is not supposed to be functional or
+safe anymore, but I'm leaving it behind if you'd like to backport the 2.6
+patch to SA 2.4 (much easier than with 2.6)
+
+-- Marc
+
+
+diff -urN SpamAssassin.orig/Conf.pm SpamAssassin/Conf.pm
+--- SpamAssassin.orig/Conf.pm Mon Jul 14 11:57:40 2003
++++ SpamAssassin/Conf.pm Sun Feb 22 17:17:03 2004
+@@ -66,6 +66,9 @@
+ use constant TYPE_RBL_EVALS => 0x0013;
+ # UNUSED => 0x0014
+ use constant TYPE_RBL_RES_EVALS => 0x0015;
++# Need to reserve a number with the SA folks (needs to be odd as it is an
++# eval test)
++use constant TYPE_RES_EVALS => 0x0021;
+
+ $VERSION = 'bogus'; # avoid CPAN.pm picking up version strings later
+
+@@ -1507,6 +1510,9 @@
+ if (/^header\s+(\S+)\s+rblreseval:(.*)$/) {
+ $self->add_test ($1, $2, TYPE_RBL_RES_EVALS); next;
+ }
++ if (/^header\s+(\S+)\s+reseval:(.*)$/) {
++ $self->add_test ($1, $2, TYPE_RES_EVALS); next;
++ }
+ if (/^header\s+(\S+)\s+eval:(.*)$/) {
+ my ($name,$rule) = ($1, $2);
+ # Backward compatibility with old rule names -- Marc
+@@ -2096,6 +2102,9 @@
+ }
+ elsif ($type == TYPE_RBL_RES_EVALS) {
+ $self->{rbl_res_evals}->{$name} = \@args;
++ }
++ elsif ($type == TYPE_RES_EVALS) {
++ $self->{res_evals}->{$name} = \@args;
+ }
+ elsif ($type == TYPE_RAWBODY_EVALS) {
+ $self->{rawbody_evals}->{$name} = \@args;
+diff -urN SpamAssassin.orig/EvalTests.pm SpamAssassin/EvalTests.pm
+--- SpamAssassin.orig/EvalTests.pm Mon Feb 23 23:28:37 2004
++++ SpamAssassin/EvalTests.pm Tue Feb 24 21:34:36 2004
+@@ -1863,6 +1863,195 @@
+ return 0;
+ }
+
++
++# This was originally written to implement greylisting in SA-Exim, although
++# I have tried to make it more general and allow for reuse in other MTAs
++# (although they will need to
++# 1) be running SA at SMTP time
++# 2) Provide the list of rcpt to and env from in some headers for SA to read
++# 3) Provide the IP of the connecting host )
++#
++# This rule should get a negative score so that if we've already seen the
++# greylisting tuplet before, we lower the score, which hopefully brings us from
++# a tempreject to an accept (at least that's how sa-exim does it)
++# -- Marc <marc_soft@merlins.org> 2004/01/19
++
++sub greylisting {
++ # db/file/dir / pointer type / how many secs to greylist after 1st connection
++ # SA score after which we don't bother running / SMTP time data header names
++ my ($self, $dirorfileordb, $method, $greylisttime, $dontcheckscore,
++ $connectiphdr, $envfromhdr, $rcpttohdr) = @_;
++ my $dirorfile = shift @_;
++
++ my $connectip;
++ my $envfrom;
++ my $rcptto;
++ my @rcptto;
++ my $iswhitelisted=0;
++ my $err;
++ my $mesgid = $self->get ('Message-Id')."\n";
++ my $tuplet;
++
++ # No newlines, thank you (yes, you need this twice apparently)
++ chomp ($mesgid);
++ chomp ($mesgid);
++ $mesgid =~ s/\012/|/g;
++
++ # For stuff that we know is spam, don't greylist the host
++ # (that might help later spam with a lower score to come in)
++ if ($self->{hits} >= $dontcheckscore)
++ {
++ #warn "debug: skipping greylisting on $mesgid, since score is already ".$self->{hits}." and you configured greylisting to not bother with anything above $dontcheckscore\n";
++ return 0;
++ }
++
++
++ if (not $connectip = $self->get($connectiphdr))
++ {
++ warn "Couldn't get Connecting IP header $connectiphdr for message $mesgid, skipping greylisting call\n";
++ return 0;
++ }
++ chomp($connectip);
++ # Clean up input (for security, if you use files/dirs)
++ $connectip =~ s#/#-#g;
++
++ if (not $envfrom = $self->get($envfromhdr))
++ {
++ warn "Couldn't get Envelope From header $envfromhdr for message $mesgid, skipping greylisting call\n";
++ return 0;
++ }
++ chomp($envfrom);
++ # Clean up input (for security, if you use files/dirs)
++ $envfrom =~ s#/#-#g;
++
++ if (not $rcptto = $self->get($rcpttohdr))
++ {
++ warn "Couldn't get Rcpt To header $rcpttohdr for message $mesgid, skipping greylisting call\n";
++ return 0;
++ }
++ chomp($rcptto);
++ # Clean up input (for security, if you use files/dirs)
++ $rcptto =~ s#/#-#g;
++ @rcptto = split(/, /, $rcptto);
++
++ umask 0007;
++
++ foreach $rcptto (@rcptto)
++ {
++ my $ipdir = "$dirorfileordb/$connectip";
++ my $tupletdir = "$ipdir/$envfrom";
++
++ $tuplet = "$tupletdir/$rcptto";
++
++ # The dir method is easy to fiddle with and expire records in (with
++ # a find | rm) but it's probably more I/O extensive than a real DB
++ # and suffers from directory size problems if a specific IP is sending
++ # generating tens of thousands of tuplets. -- Marc
++ # That said, I prefer formats I can easily tinker with, and not having to
++ # worry about buggy locking and so forth
++ if ($method eq "dir")
++ {
++ # make directory whether it's there or not (faster than test and set)
++ mkdir $ipdir;
++ mkdir $tupletdir;
++
++ if (not -e $tuplet)
++ {
++ # If the tuplets aren't there, we create them and continue in
++ # case there are other ones (one of them might be whitelisted already)
++ $err="creating $tuplet";
++ open (TUPLET, ">$tuplet") or goto greylisterror;
++ print TUPLET time."\n";
++ print TUPLET "Status: Greylisted\n";
++ print TUPLET "Last Message-Id: $mesgid\n";
++ print TUPLET "Whitelisted Count: 0\n";
++ print TUPLET "Query Count: 1\n";
++ $err="closing first-written $tuplet";
++ close TUPLET or goto greylisterror;
++ }
++ else
++ {
++ my $time;
++ my $status;
++ my $whitelistcount;
++ my $querycount;
++
++ # Take into account race condition of expiring deletes and us running
++ $err="reading $tuplet";
++ open (TUPLET, "<$tuplet") or goto greylisterror;
++ $err="Couldn't read time";
++ $time=<TUPLET> or goto greylisterror;
++ chomp ($time);
++
++ $err="Couldn't read status";
++ $status=<TUPLET> or goto greylisterror;
++ chomp ($status);
++ $err="Couldn't extract Status from $status";
++ $status =~ s/^Status: // or goto greylisterror;
++
++ # Skip Mesg-Id
++ $err="Couldn't skip Mesg-Id";
++ $_=<TUPLET> or goto greylisterror;
++
++ $err="Couldn't read whitelistcount";
++ $whitelistcount=<TUPLET> or goto greylisterror;
++ chomp ($whitelistcount);
++ $err="Couldn't extract Whitelisted Count from $whitelistcount";
++ $whitelistcount =~ s/^Whitelisted Count: // or goto greylisterror;
++
++ $err="Couldn't read querycount";
++ $querycount=<TUPLET> or goto greylisterror;
++ chomp ($querycount);
++ $err="Couldn't extract Query Count from $querycount";
++ $querycount =~ s/^Query Count: // or goto greylisterror;
++ close (TUPLET);
++
++ $querycount++;
++ if ((time - $time) > $greylisttime)
++ {
++ $status="Whitelisted";
++ $whitelistcount++;
++ }
++
++ $err="re-writing $tuplet";
++ open (TUPLET, ">$tuplet") or goto greylisterror;
++ print TUPLET "$time\n";
++ print TUPLET "Status: $status\n";
++ print TUPLET "Last Message-Id: $mesgid\n";
++ print TUPLET "Whitelisted Count: $whitelistcount\n";
++ print TUPLET "Query Count: $querycount\n";
++ $err="closing re-written $tuplet";
++ close TUPLET or goto greylisterror;
++
++ # We continue processing the other recipients, to setup or
++ # update their counters
++ if ($status="Whitelisted")
++ {
++ $iswhitelisted=1;
++ }
++ }
++ }
++ elsif ($method eq "file")
++ {
++ warn "codeme\n";
++ }
++ elsif ($method eq "db")
++ {
++ warn "codeme\n";
++ }
++ }
++
++ return $iswhitelisted;
++
++ greylisterror:
++ warn "Reached greylisterror: $err / $!";
++ # delete tuplet since it apparently had issues but don't check for errors
++ # in case it was a permission denied on write
++ unlink ($tuplet);
++ return $iswhitelisted;
++}
++
++
+ ###########################################################################
+ # BODY TESTS:
+ ###########################################################################
+diff -urN SpamAssassin.orig/PerMsgStatus.pm SpamAssassin/PerMsgStatus.pm
+--- SpamAssassin.orig/PerMsgStatus.pm Mon May 12 12:15:33 2003
++++ SpamAssassin/PerMsgStatus.pm Sun Feb 22 17:47:11 2004
+@@ -189,6 +189,9 @@
+
+ # add points from Bayes, before adjusting the AWL
+ $self->{hits} += $self->{learned_hits};
++
++ # Now, we can run rules that have to run last
++ $self->do_res_eval_tests();
+
+ # Do AWL tests last, since these need the score to have already been
+ # calculated
+@@ -1866,6 +1869,11 @@
+ my ($self) = @_;
+ # run_rbl_eval_tests doesn't process check returns unless you set needresult
+ $self->run_rbl_eval_tests ($self->{conf}->{rbl_res_evals}, 1);
++}
++
++sub do_res_eval_tests {
++ my ($self) = @_;
++ $self->run_eval_tests ($self->{conf}->{res_evals}, '');
+ }
+
+ sub do_head_eval_tests {
Index: 4.2.1-7/TODO
===================================================================
--- 4.2.1-7/TODO (nonexistent)
+++ 4.2.1-7/TODO (revision 23)
@@ -0,0 +1 @@
+Do per-user SA runs with the exiscan 45x trick
Index: 4.2.1-7/greylistclean
===================================================================
--- 4.2.1-7/greylistclean (nonexistent)
+++ 4.2.1-7/greylistclean (revision 23)
@@ -0,0 +1,177 @@
+#!/usr/bin/perl
+# ----------------------------------------------------------------------
+# Copyright (C) 2005 Mark Lawrence <nomad@null.net>
+#
+# 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.
+# ----------------------------------------------------------------------
+# greylistclean - remove expired SA-Exim greylist entries from the filesystem.
+#
+# This is basically a perl implementation of the old shell commands that
+# used to be shipped with sa-exim, combined with simple syslog reporting.
+# This perl script cleans old tuplets and directories in
+# /var/spool/sa-exim/tuplets/
+#
+# You can call this script with '-v' to see what files and
+# directories are being removed (sent to STDERR).
+# Otherwise during normal operation there is no output.
+#
+# To use this in production you either:
+# 1. Copy this file to your cron.hourly directory if you accept the risk of
+# running this script as root (it is uncessary)
+# or
+# 2. Copy this file to /usr/local/bin and create a crontab entry
+# that looks something like the following (this works on Debian):
+#
+# 33 * * * * debian-exim /usr/local/bin/greylistclean
+# ^^^^^^^^^^^
+# (a)
+# (a) find out under which user tuplets are created, it could be mail, exim
+# or something else depending on your system ("debian-exim" on debian)
+#
+# Changelog
+# ---------
+# 2005-02-14 Original version. Mark Lawrence <nomad@null.net>
+# 2005-02-21 Added example cron entry comment. Mark Lawrence <nomad@null.net>
+# 2006-01-09 Added a few comments on how to run without root, inclusion in
+# sa-exim / verbose is -v ( -d would be debug )
+#
+# ----------------------------------------------------------------------
+use strict;
+use warnings;
+use Sys::Syslog;
+use File::Find;
+use File::stat;
+
+my $tuplet_dir = '/var/spool/sa-exim/tuplets';
+
+my $max_grey_age = 60*60*24*2; # seconds to keep greylisted entries (2 days)
+my $max_age = 60*60*24*14; # seconds to keep all entries (14 days)
+
+my $tcount = 0; # total number of tuplets
+my $rm_tcount = 0; # number of tuplets removed
+
+my $dircount = 0; # total number of directories
+my $rm_dircount = 0; # number of directories removed
+
+my @empty_dirs = (); # list of empty directories
+
+my $verbose = 0;
+my $now = time();
+
+
+if (@ARGV == 1 and $ARGV[0] eq '-v') {
+ $verbose = 1;
+ print STDERR "$0 running at $now\n"
+}
+
+
+#
+# Open the reporting channel
+#
+openlog('sa-exim', 'pid,ndelay', 'mail');
+
+#
+# Process the tuplets
+#
+find({wanted => \&prune, postprocess => \&dircheck}, $tuplet_dir);
+
+syslog('info', 'Removed %d of %d greylist tuplets in %d seconds', $rm_tcount,
+ $tcount, time() - $now);
+
+#
+# Remove empty directories found by dircheck()
+#
+$now = time();
+
+foreach my $dir (@empty_dirs) {
+ rmdir $dir && $rm_dircount++;
+ $verbose && print STDERR "removed empty directory $dir\n";
+}
+
+syslog('info', 'Removed %d of %d greylist directories in %d seconds',
+ $rm_dircount, $dircount, time() - $now);
+
+closelog();
+exit;
+
+
+
+#
+# Called from File::Find::find() function with $_ set to filename/directory.
+# Search for the line 'Status: Greylisted' in files modified more than
+# $max_grey_age seconds ago and remove the files that contain it.
+# Remove any entry that is older than $max_age seconds ago.
+#
+sub prune {
+ return if (-d $_); # we don't do directories
+ $tcount++;
+
+ my $file = $_;
+ my $sb = stat($file);
+ my $age = $now - $sb->mtime;
+
+ #
+ # Remove all old entries (older than $max_age)
+ #
+ if ($age > $max_age) {
+ $verbose && print STDERR 'removing old entry ',
+ "${File::Find::dir}/$file (age: ",
+ $now - $sb->mtime, " seconds)\n";
+ unlink($file);
+ $rm_tcount++;
+ return;
+ }
+
+ #
+ # Do nothing if not old enough to expire
+ #
+ return if ($age < $max_grey_age);
+
+ #
+ # Check if this tuplet has been 'greylisted'. Use the 3 argument
+ # form of 'open', because a lot of these files have funny characters
+ # in their names.
+ #
+ if (!open(FH, '<', $file)) {
+ print STDERR "Could not open ${File::Find::name}: $!\n";
+ return;
+ }
+
+ while (my $line = <FH>) {
+ if ($line =~ /^Status: Greylisted$/) {
+ $verbose && print STDERR 'removing greylisted ',
+ "${File::Find::dir}/$file (age: ",
+ $now - $sb->mtime, " seconds)\n";
+ unlink($file);
+ $rm_tcount++;
+ last;
+ }
+ }
+
+ close FH;
+}
+
+
+#
+# Called from File::Find::find() function when all entries in a directory
+# have been processed. We check if there are any files left in the directory
+# and if not then add it to a list for later deletion
+#
+sub dircheck {
+ return if ($File::Find::dir eq $tuplet_dir); # don't check top dir.
+ $dircount++;
+
+ #
+ # Check if directory is empty and add to $empty_dirs hash
+ #
+ if (opendir(DIR, $File::Find::dir)) {
+ my $files = grep {!/^\./} readdir(DIR);
+ if ($files == 0) {
+ push(@empty_dirs, $File::Find::dir);
+ }
+ closedir(DIR);
+ }
+}
/4.2.1-7/greylistclean
Property changes:
Added: svn:executable
Index: 4.2.1-7/INSTALL
===================================================================
--- 4.2.1-7/INSTALL (nonexistent)
+++ 4.2.1-7/INSTALL (revision 23)
@@ -0,0 +1,100 @@
+READ THIS FIRST
+---------------
+If you try to build with 'make' without editing the makefile for sa-exim to
+see the exim source, and if you haven't patched your exim source with
+localscan_dlopen.patch, sa-exim will not build.
+This is normal, see the BUILDING section below
+
+This version of sa-exim now requires at least exim 4.11
+
+
+
+
+BUILDING
+--------
+The code can be compiled in two ways:
+
+0) Do not set LOCAL_SCAN_HAS_OPTIONS=yes in exim's Makefile. Leave the
+ default which is disabled.
+
+1) Unpack exim 4.11 or better, and overwrite src/local_scan.c with
+ sa-exim.c.
+ In the sa-exim distribution directory, type make sa-exim.h, and copy
+ it in the same place than sa-exim.c.
+ Rebuild exim, and you're done.
+ Note that if you do this, you are responsible for modifying variables
+ in sa-exim.c that would normally have been modified by the Makefile.
+
+ This method might seem simpler, but it requires that you rebuild exim every
+ time you upgrade sa-exim.
+
+2) The better solution is to patch exim with localscan_dlopen.patch originally
+ from David Woodhouse (provided in this archive), and rebuild exim.
+ Here are details on how to patch exim if yours needs it (at least debian's
+ exim4 is prepatched, yours may be too).
+ Choose the patch for your exim version (Philip included the portion that
+ sets LOCAL_SCAN_ABI_VERSION_MAJOR and LOCAL_SCAN_ABI_VERSION_MINOR in exim
+ 4.20)
+ - localscan_dlopen_exim_4.20_or_better.patch
+ - localscan_dlopen_up_to_4.14.patch
+
+
+ What you gain from doing this is that sa-exim, or another local_scan module
+ can be plugged into exim without rebuilding exim itself (here too you need
+ exim 4.11 or better)
+
+ To build, you can edit EXIM_SRC in the Makefile and build sa-exim-x.y.so,
+ or I have also recently modified the build environment so that you can
+ now build sa-exim without having the exim sources.
+ You can look in eximinc/version to see which source I included. While this
+ should work for the forseable future, the exim local_scan API might change
+ one day and not building against the current exim sources could cause issues
+ (hopefully, at worst it will prevent sa-exim from using better functions in
+ newer versions of the local_scan API).
+ To be really safe, I modified the localscan_dlopen patch to include a
+ minor and major version number for the API. Philip has agreed to including
+ the piece of the patch that says which version of the API exim is using,
+ so it will be obvious in the future whether exim becomes potentially
+ incompatible with an older version of sa-exim. Note that when Philip adds
+ this small portion of the patch, you will have a resulting conflict if
+ you try to apply it again. This is obviously normal, just remove it :-)
+
+ Once you're done building, you can copy sa-exim-x.y.so and optionally the
+ dummy/test accept.so in /usr/lib/exim4/local_scan/, and add this to your
+ exim4.conf (at the beginning of the file)
+ #local_scan_path = /usr/lib/exim4/local_scan/accept.so
+ local_scan_path = /usr/lib/exim4/local_scan/sa-exim.so
+
+ If you are a package builder, note that you don't actually have
+ to edit the values in the Makefile, you can override them as such:
+ make SACONF=/etc/mail/sa-exim.conf LDFLAGS="-shared -fPIC"
+
+
+The following is mostly obsolete, but left here for info purposes
+-----------------------------------------------------------------
+I would also recommend to edit exim/src/config.h.defaults as such:
+#define STRING_SPRINTF_BUFFER_SIZE 32768
+The default value is a bit too small for some of the strings that we need to
+expand from SA.
+That said, I found out that exim then complaints that the headers
+it tries to add are too big even after I set "uschar buffer[32768];" in
+src/header.c.
+As a result, I haven't quite found out how to deal with more than 8KB worth
+of SpamAssassin headers, but it may not be a huge deal, 8KB headers are too
+long anyway.
+I asked the SA guys not to output such huge headers and I wrote a patch
+to disable one of the "features" that outputs such huge headers.
+See: http://bugzilla.spamassassin.org/showattachment.cgi?attach_id=195
+This is included and turned on by default in Spamassassin 2.40 and later.
+
+
+INSTALL
+-------
+Copy sa-exim.conf to /etc/exim4 (or whatever you set SACONF to),
+and make sure to read it and edit the values to suit your environment.
+So that you don't make any mistakes, SAEximRunCond is turned off by default.
+This should force you to scan the docs before potentially shooting yourself
+in the foot :)
+
+See README for options
+
Index: 4.2.1-7/SA-greylisting-2.6.diff
===================================================================
--- 4.2.1-7/SA-greylisting-2.6.diff (nonexistent)
+++ 4.2.1-7/SA-greylisting-2.6.diff (revision 23)
@@ -0,0 +1,304 @@
+diff -urN SpamAssassin.orig/Conf.pm SpamAssassin/Conf.pm
+--- SpamAssassin.orig/Conf.pm Mon Dec 15 22:41:57 2003
++++ SpamAssassin/Conf.pm Sun Feb 29 17:42:58 2004
+@@ -107,6 +107,10 @@
+ use constant TYPE_URI_EVALS => 0x0011;
+ use constant TYPE_META_TESTS => 0x0012;
+ use constant TYPE_RBL_EVALS => 0x0013;
++# Need to reserve a number with the SA folks (needs to be odd as it is an
++# eval test)
++use constant TYPE_RES_EVALS => 0x0021;
++
+
+ $VERSION = 'bogus'; # avoid CPAN.pm picking up version strings later
+
+@@ -2000,12 +2004,15 @@
+
+ =cut
+
+- if (/^header\s+(\S+)\s+(?:rbl)?eval:(.*)$/) {
++ if (/^header\s+(\S+)\s+(?:rbl|res)?eval:(.*)$/) {
+ my ($name, $fn) = ($1, $2);
+
+ if ($fn =~ /^check_rbl/) {
+ $self->add_test ($name, $fn, TYPE_RBL_EVALS);
+ }
++ elsif (/^header\s+(\S+)\s+reseval:(.*)$/) {
++ $self->add_test ($name, $fn, TYPE_RES_EVALS);
++ }
+ else {
+ $self->add_test ($name, $fn, TYPE_HEAD_EVALS);
+ }
+@@ -2603,6 +2610,9 @@
+ }
+ elsif ($type == TYPE_RBL_EVALS) {
+ $self->{rbl_evals}->{$name} = \@args;
++ }
++ elsif ($type == TYPE_RES_EVALS) {
++ $self->{res_evals}->{$name} = \@args;
+ }
+ elsif ($type == TYPE_RAWBODY_EVALS) {
+ $self->{rawbody_evals}->{$name} = \@args;
+diff -urN SpamAssassin.orig/EvalTests.pm SpamAssassin/EvalTests.pm
+--- SpamAssassin.orig/EvalTests.pm Sat Jan 17 15:56:08 2004
++++ SpamAssassin/EvalTests.pm Sun Aug 15 15:47:22 2004
+@@ -1941,6 +1941,234 @@
+ return $self->{habeas_swe};
+ }
+
++
++# This was originally written to implement greylisting in SA-Exim, although
++# I have tried to make it more general and allow for reuse in other MTAs
++# (although they will need to
++# 1) be running SA at SMTP time
++# 2) Provide the list of rcpt to and env from in some headers for SA to read
++# 3) Provide the IP of the connecting host )
++#
++# This rule should get a negative score so that if we've already seen the
++# greylisting tuplet before, we lower the score, which hopefully brings us from
++# a tempreject to an accept (at least that's how sa-exim does it)
++# -- Marc <marc_soft@merlins.org> 2004/01/19
++
++sub greylisting {
++ my ($self, $optionhash) = @_;
++
++ $optionhash =~ s/;/,/g;
++ # This is safe, right? (users shouldn't be able to set it in their config)
++ my %option=eval $optionhash;
++ my $connectip;
++ my $envfrom;
++ my $rcptto;
++ my @rcptto;
++ my $iswhitelisted=0;
++ my $err;
++ my $mesgid = $self->get ('Message-Id')."\n";
++ my $mesgidfn;
++ my $tuplet;
++
++ foreach my $reqoption (qw ( method greylistsecs dontgreylistthreshold
++ connectiphdr envfromhdr rcpttohdr greylistnullfrom greylistfourthbyte ))
++ {
++ die "Greylist option $reqoption missing from SA config" unless (defined $option{$reqoption});
++ #warn "found $reqoption -> $option{$reqoption}\n";
++ }
++
++ # No newlines, thank you (yes, you need this twice apparently)
++ chomp ($mesgid);
++ chomp ($mesgid);
++ # Newline in the middle mesgids, are you serious? Get rid of them here
++ $mesgid =~ s/\012/|/g;
++
++ # For stuff that we know is spam, don't greylist the host
++ # (that might help later spam with a lower score to come in)
++ if ($self->{hits} >= $option{'dontgreylistthreshold'})
++ {
++ #warn "debug: skipping greylisting on $mesgid, since score is already ".$self->{hits}." and you configured greylisting to not bother with anything above $dontcheckscore\n";
++ return 0;
++ }
++
++
++ if (not $connectip = $self->get($option{'connectiphdr'}))
++ {
++ warn "Couldn't get Connecting IP header $option{'connectiphdr'} for message $mesgid, skipping greylisting call\n";
++ return 0;
++ }
++ chomp($connectip);
++ # Clean up input (for security, if you use files/dirs)
++ $connectip =~ s#/#-#g;
++
++ # Account for a null envelope from
++ if (not defined ($envfrom = $self->get($option{'envfromhdr'})))
++ {
++ warn "Couldn't get Envelope From header $option{'envfromhdr'} for message $mesgid, skipping greylisting call\n";
++ return 0;
++ }
++ chomp($envfrom);
++ # Clean up input (for security, if you use files/dirs)
++ $envfrom =~ s#/#-#g;
++ if (not $envfrom)
++ {
++ $envfrom="<>";
++ return 0 if (not $option{'greylistnullfrom'});
++ }
++
++ if (not $rcptto = $self->get($option{'rcpttohdr'}))
++ {
++ warn "Couldn't get Rcpt To header $option{'rcpttohdr'} for message $mesgid, skipping greylisting call\n";
++ return 0;
++ }
++ chomp($rcptto);
++ # Clean up input (for security, if you use files/dirs)
++ $rcptto =~ s#/#-#g;
++ @rcptto = split(/, /, $rcptto);
++
++
++ umask 0007;
++
++ foreach $rcptto (@rcptto)
++ {
++ # The dir method is easy to fiddle with and expire records in (with
++ # a find | rm) but it's probably more I/O extensive than a real DB
++ # and suffers from directory size problems if a specific IP is sending
++ # generating tens of thousands of tuplets. -- Marc
++ # That said, I prefer formats I can easily tinker with, and not having to
++ # worry about buggy locking and so forth
++
++ if ($option{'method'} eq "dir")
++ {
++ # The clean strings are hardcoded because it's hard to do a variable
++ # substitution within a tr (and using the eval solution is too resource
++ # expensive)
++ $envfrom =~ tr/!#%( )*+,-.0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~/_/c;
++ # clean variables to run properly under -T
++ $envfrom =~ /(.+)/;
++ $envfrom = $1;
++ $rcptto =~ tr/!#%( )*+,-.0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~/_/c;
++ $rcptto =~ /(.+)/;
++ $rcptto = $1;
++
++ die "greylist option dir not passed, even though method was set to dir" unless ($option{'dir'});
++ my ($ipbyte1, $ipbyte2, $ipbyte3, $ipbyte4) = split(/\./, $connectip);
++ my $ipdir1 = "$option{'dir'}/$ipbyte1";
++ my $ipdir2 = "$ipdir1/$ipbyte2";
++ my $ipdir3 = "$ipdir2/$ipbyte3";
++ my $ipdir4;
++ my $tupletdir;
++
++ $ipdir4 = "$ipdir3";
++ $ipdir4 .= "/$ipbyte4" if ($option{'greylistfourthbyte'});
++ $tupletdir = "$ipdir4/$envfrom";
++
++ $tuplet = "$tupletdir/$rcptto";
++
++ # make directory whether it's there or not (faster than test and set)
++ mkdir $ipdir1;
++ mkdir $ipdir2;
++ mkdir $ipdir3;
++ mkdir $ipdir4;
++ mkdir $tupletdir;
++
++ if (not -e $tuplet)
++ {
++ # If the tuplets aren't there, we create them and continue in
++ # case there are other ones (one of them might be whitelisted already)
++ $err="creating $tuplet";
++ open (TUPLET, ">$tuplet") or goto greylisterror;
++ print TUPLET time."\n";
++ print TUPLET "Status: Greylisted\n";
++ print TUPLET "Last Message-Id: $mesgid\n";
++ print TUPLET "Whitelisted Count: 0\n";
++ print TUPLET "Query Count: 1\n";
++ $err="closing first-written $tuplet";
++ close TUPLET or goto greylisterror;
++ }
++ else
++ {
++ my $time;
++ my $status;
++ my $whitelistcount;
++ my $querycount;
++
++ # Take into account race condition of expiring deletes and us running
++ $err="reading $tuplet";
++ open (TUPLET, "<$tuplet") or goto greylisterror;
++ $err="Couldn't read time";
++ defined ($time=<TUPLET>) or goto greylisterror;
++ chomp ($time);
++
++ $err="Couldn't read status";
++ defined ($status=<TUPLET>) or goto greylisterror;
++ chomp ($status);
++ $err="Couldn't extract Status from $status";
++ $status =~ s/^Status: // or goto greylisterror;
++
++ # Skip Mesg-Id
++ $err="Couldn't skip Mesg-Id";
++ defined ($_=<TUPLET>) or goto greylisterror;
++
++ $err="Couldn't read whitelistcount";
++ defined ($whitelistcount=<TUPLET>) or goto greylisterror;
++ chomp ($whitelistcount);
++ $err="Couldn't extract Whitelisted Count from $whitelistcount";
++ $whitelistcount =~ s/^Whitelisted Count: // or goto greylisterror;
++
++ $err="Couldn't read querycount";
++ defined ($querycount=<TUPLET>) or goto greylisterror;
++ chomp ($querycount);
++ $err="Couldn't extract Query Count from $querycount";
++ $querycount =~ s/^Query Count: // or goto greylisterror;
++ close (TUPLET);
++
++ $querycount++;
++ if ((time - $time) > $option{'greylistsecs'})
++ {
++ $status="Whitelisted";
++ $whitelistcount++;
++ }
++
++ $err="re-writing $tuplet";
++ open (TUPLET, ">$tuplet") or goto greylisterror;
++ print TUPLET "$time\n";
++ print TUPLET "Status: $status\n";
++ print TUPLET "Last Message-Id: $mesgid\n";
++ print TUPLET "Whitelisted Count: $whitelistcount\n";
++ print TUPLET "Query Count: $querycount\n";
++ $err="closing re-written $tuplet";
++ close TUPLET or goto greylisterror;
++
++ # We continue processing the other recipients, to setup or
++ # update their counters
++ if ($status eq "Whitelisted")
++ {
++ $iswhitelisted=1;
++ }
++ }
++ }
++ elsif ($option{'method'} eq "file")
++ {
++ warn "codeme\n";
++ }
++ elsif ($option{'method'} eq "db")
++ {
++ warn "codeme\n";
++ }
++ }
++
++ return $iswhitelisted;
++
++ greylisterror:
++ warn "Reached greylisterror: $err / $!";
++ # delete tuplet since it apparently had issues but don't check for errors
++ # in case it was a permission denied on write
++ unlink ($tuplet);
++ return $iswhitelisted;
++}
++
++
+ ###########################################################################
+ # BODY TESTS:
+ ###########################################################################
+diff -urN SpamAssassin.orig/PerMsgStatus.pm SpamAssassin/PerMsgStatus.pm
+--- SpamAssassin.orig/PerMsgStatus.pm Tue Jan 20 13:40:04 2004
++++ SpamAssassin/PerMsgStatus.pm Sun Feb 29 19:01:19 2004
+@@ -184,6 +184,9 @@
+
+ # add points from Bayes, before adjusting the AWL
+ $self->{hits} += $self->{learned_hits};
++
++ # Now, we can run rules that have to run last
++ $self->do_res_eval_tests();
+
+ # Do AWL tests last, since these need the score to have already been
+ # calculated
+@@ -2010,6 +2013,11 @@
+ }
+
+ ###########################################################################
++
++sub do_res_eval_tests {
++ my ($self) = @_;
++ $self->run_eval_tests ($self->{conf}->{res_evals}, '');
++}
+
+ sub do_head_eval_tests {
+ my ($self) = @_;
Index: 4.2.1-7/Greylisting.pm
===================================================================
--- 4.2.1-7/Greylisting.pm (nonexistent)
+++ 4.2.1-7/Greylisting.pm (revision 23)
@@ -0,0 +1,296 @@
+package Greylisting;
+#
+# $Id: Greylisting.pm,v 1.4 2006/01/11 17:17:28 marcmerlin Exp $
+#
+
+# General Greylisting Plugin, written by Marc MERLIN <marc_soft@merlins.org>
+# (Kristopher Austin gets the credit for the original port to an SA 3.0 plugin)
+#
+# This was originally written to implement greylisting in SA-Exim, although
+# I have tried to make it more general and allow for reuse in other MTAs
+# (although they will need to
+# 1) be running SA at SMTP time
+# 2) Provide the list of rcpt to and env from in some headers for SA to read
+# 3) Provide the IP of the connecting host )
+#
+# This rule should get a negative score so that if we've already seen the
+# greylisting tuplet before, we lower the score, which hopefully brings us from
+# a tempreject to an accept (at least that's how sa-exim does it)
+#
+# -- Marc 2004/01/19
+
+use strict;
+use Mail::SpamAssassin::Plugin;
+our @ISA = qw(Mail::SpamAssassin::Plugin);
+
+sub new
+{
+ my ($class, $mailsa) = @_;
+ $class = ref($class) || $class;
+ my $self = $class->SUPER::new($mailsa);
+ bless ($self, $class);
+ $self->register_eval_rule ("greylisting");
+ return $self;
+}
+
+
+sub check_end
+{
+ my ($self, $permsgstatus) = @_;
+
+ if (not $self->{'rangreylisting'})
+ {
+ Mail::SpamAssassin::Plugin::dbg("GREYLISTING: greylisting didn't run since the configuration wasn't setup to call us");
+ }
+}
+
+# Greylisting happens depending on the SA score, so we want to run it last,
+# which is why we give it a high priority
+sub greylisting
+{
+ my ($self, $permsgstatus, $optionhash) = @_;
+
+ my $connectip;
+ my $envfrom;
+ my $rcptto;
+ my @rcptto;
+ my $iswhitelisted=0;
+ my $err;
+ my $mesgid = $permsgstatus->get('Message-Id')."\n";
+ my $mesgidfn;
+ my $tuplet;
+ my $sascore = $permsgstatus->get_score();
+ my $dontcheckscore;
+ my %option;
+
+ Mail::SpamAssassin::Plugin::dbg("GREYLISTING: called function");
+
+ $optionhash =~ s/;/,/g;
+ # This is safe, right? (users shouldn't be able to set it in their config)
+ %option=eval $optionhash;
+ $self->{'rangreylisting'}=1;
+
+ foreach my $reqoption (qw ( method greylistsecs dontgreylistthreshold
+ connectiphdr envfromhdr rcpttohdr greylistnullfrom greylistfourthbyte ))
+ {
+ die "Greylist option $reqoption missing from SA config" unless (defined $option{$reqoption});
+ }
+
+ $dontcheckscore = $option{'dontgreylistthreshold'};
+
+
+ # No newlines, thank you (yes, you need this twice apparently)
+ chomp ($mesgid);
+ chomp ($mesgid);
+ # Newline in the middle mesgids, are you serious? Get rid of them here
+ $mesgid =~ s/\012/|/g;
+
+ # For stuff that we know is spam, don't greylist the host
+ # (that might help later spam with a lower score to come in)
+ if ($sascore >= $dontcheckscore)
+ {
+ Mail::SpamAssassin::Plugin::dbg("GREYLISTING: skipping greylisting on $mesgid, since score is already $sascore and you configured greylisting not to bother with anything above $dontcheckscore");
+ return 0;
+ }
+ else
+ {
+ Mail::SpamAssassin::Plugin::dbg("GREYLISTING: running greylisting on $mesgid, since score is too low ($sascore) and you configured greylisting to greylist anything under $dontcheckscore");
+ }
+
+ if (not $connectip = $permsgstatus->get($option{'connectiphdr'}))
+ {
+ warn "Couldn't get Connecting IP header $option{'connectiphdr'} for message $mesgid, skipping greylisting call\n";
+ return 0;
+ }
+ chomp($connectip);
+ # Clean up input (for security, if you use files/dirs)
+ $connectip =~ /([\d.:]+)/;
+ $connectip = ($1 or "");
+
+ # Account for a null envelope from
+ if (not defined ($envfrom = $permsgstatus->get($option{'envfromhdr'})))
+ {
+ warn "Couldn't get Envelope From header $option{'envfromhdr'} for message $mesgid, skipping greylisting call\n";
+ return 0;
+ }
+ chomp($envfrom);
+ # Clean up input (for security, if you use files/dirs)
+ $envfrom =~ s#/#-#g;
+ if (not $envfrom)
+ {
+ $envfrom="<>";
+ return 0 if (not $option{'greylistnullfrom'});
+ }
+
+ if (not $rcptto = $permsgstatus->get($option{'rcpttohdr'}))
+ {
+ warn "Couldn't get Rcpt To header $option{'rcpttohdr'} for message $mesgid, skipping greylisting call\n";
+ return 0;
+ }
+ chomp($rcptto);
+ # Clean up input (for security, if you use files/dirs)
+ $rcptto =~ s#/#-#g;
+ @rcptto = split(/, /, $rcptto);
+
+
+ umask 0007;
+
+ foreach $rcptto (@rcptto)
+ {
+ # The dir method is easy to fiddle with and expire records in (with
+ # a find | rm) but it's probably more I/O extensive than a real DB
+ # and suffers from directory size problems if a specific IP is sending
+ # generating tens of thousands of tuplets. -- Marc
+ # That said, I prefer formats I can easily tinker with, and not having
+ # to worry about buggy locking and so forth
+
+ if ($option{'method'} eq "dir")
+ {
+ my $tmpvar;
+
+ # The clean strings are hardcoded because it's hard to do a variable
+ # substitution within a tr (and using the eval solution is too
+ # resource expensive)
+ # envfrom could be cleaned outside of the loop, but the other method
+ # options might now want that
+ $envfrom =~ tr/!#%()*+,-.0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~/_/c;
+ # clean variables to run properly under -T
+ $envfrom =~ /(.+)/;
+ $tmpvar = ($1 or "");
+ # work around bug in perl untaint in perl 5.8
+ $envfrom=undef;
+ $envfrom=$tmpvar;
+ $rcptto =~ tr/!#%()*+,-.0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~/_/c;
+ $rcptto =~ /(.+)/;
+ $tmpvar = ($1 or "");
+ $rcptto=undef;
+ $rcptto=$tmpvar;
+
+ die "greylist option dir not passed, even though method was set to dir" unless ($option{'dir'});
+
+ # connectip is supposed to be untainted now, but I was still getting
+ # some insecure dependecy error messages sometimes (perl 5.8 problem apparently)
+ $connectip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/;
+ my ($ipbyte1, $ipbyte2, $ipbyte3, $ipbyte4) = ($1, $2, $3, $4);
+ my $ipdir1 = "$option{'dir'}/$ipbyte1";
+ my $ipdir2 = "$ipdir1/$ipbyte2";
+ my $ipdir3 = "$ipdir2/$ipbyte3";
+ my $ipdir4;
+ my $tupletdir;
+
+ $ipdir4 = "$ipdir3";
+ $ipdir4 .= "/$ipbyte4" if ($option{'greylistfourthbyte'});
+ $tupletdir = "$ipdir4/$envfrom";
+
+ $tuplet = "$tupletdir/$rcptto";
+
+ # make directory whether it's there or not (faster than test and set)
+ mkdir $ipdir1;
+ mkdir $ipdir2;
+ mkdir $ipdir3;
+ mkdir $ipdir4;
+ mkdir $tupletdir;
+
+ if (not -e $tuplet)
+ {
+ # If the tuplets aren't there, we create them and continue in
+ # case there are other ones (one of them might be whitelisted
+ # already)
+ $err="creating $tuplet";
+ open (TUPLET, ">$tuplet") or goto greylisterror;
+ print TUPLET time."\n";
+ print TUPLET "Status: Greylisted\n";
+ print TUPLET "Last Message-Id: $mesgid\n";
+ print TUPLET "Whitelisted Count: 0\n";
+ print TUPLET "Query Count: 1\n";
+ print TUPLET "SA Score: $sascore\n";
+ $err="closing first-written $tuplet";
+ close TUPLET or goto greylisterror;
+ }
+ else
+ {
+ my $time;
+ my $status;
+ my $whitelistcount;
+ my $querycount;
+
+ # Take into account race condition of expiring deletes and us
+ # running
+ $err="reading $tuplet";
+ open (TUPLET, "<$tuplet") or goto greylisterror;
+ $err="Couldn't read time";
+ defined ($time=<TUPLET>) or goto greylisterror;
+ chomp ($time);
+
+ $err="Couldn't read status";
+ defined ($status=<TUPLET>) or goto greylisterror;
+ chomp ($status);
+ $err="Couldn't extract Status from $status";
+ $status =~ s/^Status: // or goto greylisterror;
+
+ # Skip Mesg-Id
+ $err="Couldn't skip Mesg-Id";
+ defined ($_=<TUPLET>) or goto greylisterror;
+
+ $err="Couldn't read whitelistcount";
+ defined ($whitelistcount=<TUPLET>) or goto greylisterror;
+ chomp ($whitelistcount);
+ $err="Couldn't extract Whitelisted Count from $whitelistcount";
+ $whitelistcount =~ s/^Whitelisted Count: // or goto greylisterror;
+
+ $err="Couldn't read querycount";
+ defined ($querycount=<TUPLET>) or goto greylisterror;
+ chomp ($querycount);
+ $err="Couldn't extract Query Count from $querycount";
+ $querycount =~ s/^Query Count: // or goto greylisterror;
+ close (TUPLET);
+
+ $querycount++;
+ if ((time - $time) > $option{'greylistsecs'})
+ {
+ $status="Whitelisted";
+ $whitelistcount++;
+ }
+
+ $err="re-writing $tuplet";
+ open (TUPLET, ">$tuplet") or goto greylisterror;
+ print TUPLET "$time\n";
+ print TUPLET "Status: $status\n";
+ print TUPLET "Last Message-Id: $mesgid\n";
+ print TUPLET "Whitelisted Count: $whitelistcount\n";
+ print TUPLET "Query Count: $querycount\n";
+ print TUPLET "SA Score: $sascore\n";
+ $err="closing re-written $tuplet";
+ close TUPLET or goto greylisterror;
+
+ # We continue processing the other recipients, to setup or
+ # update their counters
+ if ($status eq "Whitelisted")
+ {
+ $iswhitelisted=1;
+ }
+ }
+ }
+ elsif ($option{'method'} eq "file")
+ {
+ warn "codeme (file greylisting)\n";
+ }
+ elsif ($option{'method'} eq "db")
+ {
+ warn "codeme (db greylisting)\n";
+ }
+ }
+
+ Mail::SpamAssassin::Plugin::dbg("GREYLISTING: computed greylisting on tuplet, saved info in $tuplet and whitelist status is $iswhitelisted");
+ return $iswhitelisted;
+
+ greylisterror:
+ warn "Reached greylisterror: $err / $!";
+ # delete tuplet since it apparently had issues but don't check for errors
+ # in case it was a permission denied on write
+ unlink ($tuplet);
+ return $iswhitelisted;
+}
+
+
+1;
Index: 4.2.1-7/Makefile
===================================================================
--- 4.2.1-7/Makefile (nonexistent)
+++ 4.2.1-7/Makefile (revision 23)
@@ -0,0 +1,107 @@
+# SA-Exim can be built standalone as a loadable module with this Makefile
+# or you can copy sa-exim.c over exim's local_scan.c file if you want to
+# statically build it into exim
+#
+
+VERSION=$(shell cat version)
+
+# The idea is that you don't have to edit these values, you can override
+# them on the command line:
+# make SACONF=/etc/exim/sa-exim.conf LDFLAGS="-shared -fPIC" CC=cc
+CC=gcc
+CFLAGS=-O2 -Wall
+LDFLAGS=-shared
+SACONF=/etc/exim4/sa-exim.conf
+SPAMC=/usr/bin/spamc
+
+
+# I place the directory in exim/debian/local_scan. Adjust the path as needed
+# Actually, we will also look for the versions supplied with this source
+# if we can't find the exim source
+EXIM_SRC= ../../src
+EXIM_SRC_LOCAL = ./eximinc
+SUFF=-$(VERSION)
+
+SAFLAGS=-DSPAMASSASSIN_CONF=\"$(SACONF)\" -DSPAMC_LOCATION=\"$(SPAMC)\"
+BUILDCFLAGS=-I$(EXIM_SRC) -I$(EXIM_SRC_LOCAL) -DDLOPEN_LOCAL_SCAN $(SAFLAGS) $(CFLAGS)
+
+SONAME=$(subst .so,$(SUFF).so,sa-exim.so)
+
+DOCS=sa.html CHANGELOG ACKNOWLEDGEMENTS
+OBJECTS=$(SONAME) accept.so sa-exim_short.conf $(DOCS)
+OTHERTARGETS=sa-exim.h
+
+all: $(OBJECTS)
+
+docs: $(DOCS)
+
+
+$(SONAME) : sa-exim.c sa-exim.h
+ @echo "Building $@"
+ $(CC) $(BUILDCFLAGS) $(LDFLAGS) -o $@ $<
+ chmod a+rx $(SONAME)
+
+accept.so: accept.c
+ @echo "Building $@"
+ $(CC) $(BUILDCFLAGS) $(LDFLAGS) -o $@ $<
+ chmod a+rx $@
+
+ACKNOWLEDGEMENTS: Acknowledgements.html
+ @echo "Generating $@"
+ @links -dump $< > $@
+
+CHANGELOG: Changelog.html
+ @echo "Generating $@"
+ @links -dump $< > $@
+
+sa.html: Changelog.html Acknowledgements.html sa.html.template
+ @echo "Generating $@"
+ @bash -c 'sed "/<Changelog>/,$$ d" < sa.html.template; cat Changelog.html; sed "1,/<\/Changelog>/ d; /<Acknowledgements>/,$$ d" < sa.html.template; cat Acknowledgements.html; sed "1,/<\/Acknowledgements>/ d" < sa.html.template' > sa.html
+
+sa-exim_short.conf: sa-exim.conf
+ @cat sa-exim.conf | sed "/# --- snip ---/,$$ d" > sa-exim_short.conf
+ @cat sa-exim.conf | grep -v "^#" | tr '\012' 'ÿ' | sed "s/ÿÿÿ*/ÿÿ/g" | tr 'ÿ' '\012' >> sa-exim_short.conf
+
+sa-exim.h: sa-exim.c version
+ echo "char *version=\"`cat version` (built `date -R 2>/dev/null || date`)\";" > sa-exim.h
+
+clean:
+ @-rm -rf $(OBJECTS) $(DOCS) $(OTHERTARGETS) build-stamp configure-stamp debian/sa-exim debian/sa-exim.postrm.debhelper debian/sa-exim.substvars debian/files 2>/dev/null
+
+deb: ../sa-exim_$(VERSION).orig.tar.gz debian/*
+ @make clean
+ @dpkg-buildpackage -uc -us -sd -rfakeroot
+ @make clean
+
+../sa-exim_$(VERSION).orig.tar.gz: * */*
+ @make clean
+ @( cd ..; tar chvzf sa-exim_$(VERSION).orig.tar.gz sa-exim-$(VERSION) )
+
+# This didn't work too well, I'll just ship the source with the debian tree
+#deb: ../sa-exim_$(VERSION).orig.tar.gz debian/rules
+# @make clean
+# @dpkg-buildpackage -uc -us -sd -rfakeroot
+#
+#
+#../sa-exim_$(VERSION).tar.gz: * */*
+# @make clean
+# @if [ -d debian ]; then echo "Can't rebuild $@ with debian tree unpacked, please remove it"; exit 1; fi
+# @( cd ..; tar chvzf sa-exim_$(VERSION).tar.gz sa-exim-$(VERSION) )
+#
+#
+#../sa-exim_$(VERSION).orig.tar.gz: ../sa-exim_$(VERSION).tar.gz
+# if [ -e ../sa-exim-$(VERSION).tar.gz ] ; then \
+# cp -a ../sa-exim-$(VERSION).tar.gz ../sa-exim_$(VERSION).orig.tar.gz ; \
+# else \
+# wget http://marc.merlins.org/linux/sa-exim-$(VERSION).tar.gz; \
+# mv sa-exim-$(VERSION).tar.gz ../sa-exim_$(VERSION).orig.tar.gz; \
+# fi
+#
+#
+#debian/rules:
+# @wget http://marc.merlins.org/linux/exim/files/debian/sa-exim_diff.gz
+# @zcat sa-exim_diff.gz | patch -s -p1
+# @/bin/rm sa-exim_diff.gz
+# @chmod 755 debian/rules
+#
+
Index: 4.2.1-7/.cvsignore
===================================================================
--- 4.2.1-7/.cvsignore (nonexistent)
+++ 4.2.1-7/.cvsignore (revision 23)
@@ -0,0 +1,7 @@
+.*
+ACKNOWLEDGEMENTS
+CHANGELOG
+sa.html
+sa-exim.h
+sa-exim_short.conf
+