Re: 2.5.1-1 error
Marco Paganini <[email protected]> Wed, 27 Apr 2005 12:18:13 -0400
| Newsgroups | gmane.mail.spam.active-spam-killer.general |
|---|---|
| Message-ID | <[email protected]> |
Hi Stephen et al, The problem you see was caused by some last minute mixup with CVS. Somehow, I overwrote the correct version of askconfig.py with an older version. :( I will release ASK 2.5.2 soon. In the meantime, please overwrite your askconfig.py file in the ASK distribution with the attached file and tell me if it runs OK. Regards Paga On Sat, Apr 23, 2005 at 06:44:19PM -0500, Stephen Stocker wrote: > Hi, > > I haven't updated ASK since 2.4.1, and tried the beta version. It's > giving me this error, using procmail 3.22 (or for that matter, when > invoked from the command line). I'm using Python 2.2.3, if that helps. > > I've looked through .askrc and tried a completely new setup, with the > same results. Any ideas? Thanks, and please keep up the great work on this > system, it's been a life-saver! :) > > Steve > > > > ------------------------------------- > Hope, Despair and the Triumph of Life > http://www.hdtl.org > Abuse Prevention/Survivor Support > > > ------------------------------------------------------- > SF email is sponsored by - The IT Product Guide > Read honest & candid reviews on hundreds of IT Products from real users. > Discover which products truly live up to the hype. Start reading now. > http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click > _______________________________________________ > A-S-K-users mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/a-s-k-users > -- Marco Paganini | UNIX / Linux / Networking [email protected] | PGP: http://www.paganini.net/pgp/ http://www.paganini.net | Magnus Frater te spectat...
askconfig.py
(text/plain, 12.9 KB)
#------------------------------------------------------------------------------ # askconfig.py - configuration related functions # # (C) 2001-2002 by Marco Paganini ([email protected]) # # This file is part of ASK - Active Spam Killer # # ASK 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. # # ASK 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 ASK; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: askconfig.py,v 1.57 2005/04/27 01:59:52 paganini Exp $ #------------------------------------------------------------------------------ import os import sys import string import rfc822 import md5 import re import time import struct, fcntl import tempfile import getopt import ConfigParser import askversion #------------------------------------------------------------------------------ class AskConfig: """ Manages the configuration related information for ASK. Attributes: - cfg: ConfigParser object - home: home directory (from $HOME) - rc_*: Reflect values set in the configuration file. - RET_PROCMAIL_CONTINUE: Signals procmail to continue delivery - RET_PROCMAIL_STOP: Signals procmail to stop delivery """ #------------------------------------------------------------------------------ def __init__(self, argv): """ Initializes the AskConfig class. 'argv' is used to parse the command line options. """ self.procmail_mode = 0 self.filter_mode = 0 self.loglevel = 0 self.logfile = "" self.home = "" self.rcfile = "" self.__cmdline(argv) ## If self.home is already set, we passed it through command line if (self.home == ""): self.home = os.getenv("HOME") if not self.home: sys.stderr.write("ASK ERROR: Cannot find HOME directory! Aborting...\n") sys.exit(1) ## Acquire python's version number and warn if unsupported. try: self.python_major_version, \ self.python_minor_version, \ self.python_micro_version, \ self.python_releaselevel, \ tmp = sys.version_info except: ## Older versions of python do not define sys.version_info self.python_major_version = 0 self.python_minor_version = 0 self.python_micro_version = 0 self.python_releaselevel = "" if not self.rcfile: self.rcfile = self.home + "/.askrc" self.__read_config(self.rcfile) #------------------------------------------------------------------------------ def __read_config(self, configfile): """ Reads config file pointed to by 'configfile' and process the options accordingly. Note that this function will expand lists and environment variables found inside the options. """ if (os.access(configfile, os.R_OK) == 0): sys.stderr.write("ERROR: %s does not exist or is unreadable. Exiting...\n" % configfile) sys.exit(self.RET_PROCMAIL_CONTINUE) self.cfg = ConfigParser.ConfigParser() try: self.cfg.read(configfile) except ConfigParser.MissingSectionHeaderError: sys.stderr.write("ERROR: Config file has no headers. Exiting...\n") sys.exit(self.RET_PROCMAIL_CONTINUE) ## We now load each of value in turn self.rc_mymails = self.__expand("rc_mymails", listmode = 1) self.rc_myfullname = self.__expand("rc_myfullname", mandatory = 0) self.rc_mymailbox = self.__expand("rc_mymailbox") self.rc_junkmailbox = self.__expand("rc_junkmailbox",mandatory = 0) self.rc_bulkmailbox = self.__expand("rc_bulkmailbox",mandatory = 0) self.rc_mailkey = self.__expand("rc_mailkey") self.rc_md5_key = self.__expand("rc_md5_key") self.rc_askdir = self.__expand("rc_askdir") ## If msgdir ends in "/" we assume messages will be queued in a ## Maildir compatible format. In that case we add the "cur/" directory ## to the path, as it will be the "real" directory where the files reside. ## The delivery routines are smart enough to remove the "cur/new/tmp" part. self.rc_msgdir = self.__expand("rc_msgdir") if (self.rc_msgdir[len(self.rc_msgdir) - 1] == "/"): ## Create dirs if not os.path.exists(self.rc_msgdir): os.mkdir(self.rc_msgdir) if not os.path.exists(self.rc_msgdir + "cur"): os.mkdir(self.rc_msgdir + "cur") if not os.path.exists(self.rc_msgdir + "new"): os.mkdir(self.rc_msgdir + "new") if not os.path.exists(self.rc_msgdir + "tmp"): os.mkdir(self.rc_msgdir + "tmp") self.rc_msgdir = self.rc_msgdir + "/new/" self.queue_is_maildir = 1 else: self.queue_is_maildir = 0 self.rc_tmpdir = self.__expand("rc_tmpdir") self.rc_lockfile = self.__expand("rc_lockfile", mandatory = 0) self.rc_confirm_mailbody = self.__expand("rc_confirm_mailbody", mandatory = 0) self.rc_confirm_dirs = self.__expand("rc_confirm_dirs", listmode = 1, mandatory = 0) self.rc_confirm_langs = self.__expand("rc_confirm_langs", listmode = 1, mandatory = 0) self.rc_whitelist = self.__expand("rc_whitelist", listmode = 1) self.rc_ignorelist = self.__expand("rc_ignorelist", listmode = 1) # This is kept here for backwards compatibility. # The blacklist is now a synonym for ignorelist self.rc_blacklist = self.__expand("rc_blacklist", listmode = 1, mandatory = 0) self.rc_basic_headers = self.__expand("rc_basic_headers", listmode = 1, mandatory = 0) self.rc_mta_command = self.__expand("rc_mta_command") self.rc_junk_unknown_recipients = self.__expand("rc_junk_unknown_recipients", mandatory = 0, boolean = 1) self.rc_whitelist_on_mailkey = self.__expand("rc_whitelist_on_mailkey", mandatory = 0, boolean = 0) self.rc_remote_cmd_enabled = self.__expand("rc_remote_cmd_enabled", mandatory = 0, boolean = 1) self.rc_remote_cmd_htmlmail = self.__expand("rc_remote_cmd_htmlmail", mandatory = 0, boolean = 1) self.rc_smtp_validate = self.__expand("rc_smtp_validate", mandatory = 0, boolean = 1) ## Queued messages older than this will have "Delete" suggested as the default action self.rc_remote_cmd_max_age = self.__expand_int("rc_remote_cmd_max_age", mandatory = 0, default = 10) self.rc_max_attach_lines = self.__expand_int("rc_max_attach_lines", default = 50) ## Set the max number of confirmations we can have in the list ## before we stop sending them to that address self.rc_max_confirmations = self.__expand_int("rc_max_confirmations", default = 5) ## Set the Minimum list size for who we have recently sent ## Confirmation messages to self.rc_min_confirmation_list = self.__expand_int("rc_min_confirmation_list", default = 20) if self.rc_min_confirmation_list < 2: self.rc_min_confirmation_list = 2 ## Set the Maximum list size for who we have recently sent ## Confirmation messages to self.rc_max_confirmation_list = self.__expand_int("rc_max_confirmation_list", default = self.rc_min_confirmation_list * 2) if self.rc_max_confirmation_list < self.rc_min_confirmation_list: self.rc_max_confirmation_list = self.rc_min_confirmation_list * 2 ## Blacklist will always be treated as ignorelist. if self.rc_blacklist: self.rc_ignorelist.extend(self.rc_blacklist) ## We must have either rc_confirm_dirs (in which case we'll use the ## new rc_confirm_langs) or the old style rc_confirm_mailbody. if (self.rc_confirm_dirs != []): ## Assume English if no language specified if (self.rc_confirm_langs == ""): self.rc_confirm_langs = ["en"]; ## Fill in with the filenames self.rc_confirm_filenames = [] for dirname in self.rc_confirm_dirs: for lang in self.rc_confirm_langs: fname = os.path.join(dirname, "confirm_%s.txt" % lang) if os.path.isfile(fname): self.rc_confirm_filenames.append(fname) else: if (self.rc_confirm_mailbody != ""): self.rc_confirm_filenames = [ self.rc_confirm_mailbody ] else: sys.stderr.write("ERROR: No confirm_dirs or confirm_body in rcfile. Exiting...\n") sys.exit(self.RET_PROCMAIL_CONTINUE) ## Verify if we got something... if self.rc_confirm_filenames == []: sys.stderr.write("ERROR: No confirmation templates found! Exiting...\n") sys.exit(self.RET_PROCMAIL_CONTINUE) ## Pipe delivery is only supported for Python 2 if (self.rc_mymailbox[0] == "|" and self.python_major_version < 2): sys.stderr.write("ERROR: You need Python 2 to use pipe delivery. Exiting...\n") sys.exit(self.RET_PROCMAIL_CONTINUE) ## If we are in procmail or filter mode, set rc_mymailbox to "-" ## to indicate stdout delivery. rc_my_original_mailbox always ## points to what was chosen by the user in the config file. ## ## Note: If the mailbox starts with a "|" (pipe symbol), we assume ## "pipe to this program for delivery" (usually sendmail). self.rc_my_original_mailbox = self.rc_mymailbox if self.procmail_mode or self.filter_mode: self.rc_mymailbox = "-" #------------------------------------------------------------------------------ def __expand_int(self, option, listmode = 0, mandatory = 1, boolean = 0, default = None): """ Returns same results as __expand, converted to int. Returns 'None' on exception. """ value = self.__expand(option, listmode, mandatory, boolean, default) try: value = int(value) except: value = None return value #------------------------------------------------------------------------------ def __expand(self, option, listmode = 0, mandatory = 1, boolean = 0, default = None): """ Returns option 'option' within section 'Ask'. Some mangling will be done in the input field: - ${VARIABLE} will be expanded. If 'listmode' is set, the input will be split into a list (commas will be used as the separator). If 'mandatory' is set (the default), an error will occur if the variable is not found. If mandatory == 0 and the variable does not exist in the config file, it will be set to '' (or [] if listmode == 1). The 'boolean' argument will cause the interpretation of on/off/true/false/1/0. Anything else will cause the parameter to be set to false. """ try: buf = self.cfg.get("ask",option) except ConfigParser.NoSectionError, str: print "Config file error: %s" % str sys.exit(self.RET_PROCMAIL_CONTINUE) except ConfigParser.NoOptionError, str: if not default == None: return default if not mandatory: if listmode: return([]) else: return('') print "Config file error: %s" % str sys.exit(self.RET_PROCMAIL_CONTINUE) except ValueError, str: print "Config file error: %s" % str sys.exit(self.RET_PROCMAIL_CONTINUE) ## Remove leading and trailing backspaces buf = string.strip(buf) ## Expand Environment vars while 1: res = re.search("(\$\{[a-z0-9]*\})", buf, re.IGNORECASE) if (res == None): break env = res.group(1) env = env[2:-1] ## Remove ${ and } ## Expand environment variable, treating $HOME as a special case ## Non-existent environment variables yield an empty string. if env == "HOME": result = self.home else: result = os.getenv(env,"") buf = string.replace(buf, res.group(1), result) ## List? if listmode: listbuf = string.split(buf, ",") return map(lambda str: string.strip(str), listbuf) ## If boolean, interpret true/false/on/off/1/0 if boolean: if string.lower(buf) in ("true","on","1","yes"): return 1 else: return 0 ## Normal case return(buf) #------------------------------------------------------------------------------ def __cmdline(self, cmd): """ Parses the command line and set the self.rc_* variables accordingly. Also sets the return codes for procmail. """ try: (opts, args) = getopt.getopt(cmd[1:], "", ["loglevel=", "logfile=","procmail","filter","home=","rcfile="]) except getopt.error: sys.stderr.write("Use: askfilter [--loglevel=x --logfile=file] [--procmail|--filter] [--home=your_homedir]\n") sys.exit(1) for o, a in opts: if (o == "--loglevel"): try: self.loglevel = int(a) except ValueError: sys.stderr.write("Error: --loglevel takes a numeric argument\n") if (o == "--logfile"): self.logfile = a if (o == "--procmail"): self.procmail_mode = 1 self.filter_mode = 0 if (o == "--filter"): self.procmail_mode = 0 self.filter_mode = 1 if (o == "--home"): self.home = a if (o == "--rcfile"): self.rcfile = a ## Set procmail return codes accordingly. ## filter_mode always returns "continue" so procmail or another ## generic mail filter process knows when to discard the message if self.procmail_mode: self.RET_PROCMAIL_CONTINUE = 0 self.RET_PROCMAIL_STOP = 1 else: self.RET_PROCMAIL_CONTINUE = 0 self.RET_PROCMAIL_STOP = 0 #--------------------------------------------------------------------------------------