⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb_imapfilter.py

📁 用python实现的邮件过滤器
💻 PY
📖 第 1 页 / 共 4 页
字号:
#!/usr/bin/env python"""An IMAP filter.  An IMAP message box is scanned and all non-scoredmessages are scored and (where necessary) filtered.Usage:    sb_imapfilter [options]        note: option values with spaces in them must be enclosed              in double quotes        options:            -p  dbname  : pickled training database filename            -d  dbname  : dbm training database filename            -t          : train contents of spam folder and ham folder            -c          : classify inbox            -h          : display this message            -v          : verbose mode            -P          : security option to prompt for imap password,                          rather than look in options["imap", "password"]            -e y/n      : expunge/purge messages on exit (y) or not (n)            -i debuglvl : a somewhat mysterious imaplib debugging level                          (4 is a good level, and suitable for bug reports)            -l minutes  : period of time between filtering operations            -b          : Launch a web browser showing the user interface.            -o section:option:value :                          set [section, option] in the options database                          to valueExamples:    Classify inbox, with dbm database        sb_imapfilter -c -d bayes.db    Train Spam and Ham, then classify inbox, with dbm database        sb_imapfilter -t -c -d bayes.db    Train Spam and Ham only, with pickled database        sb_imapfilter -t -p bayes.dbWarnings:    o We never delete mail, unless you use the -e/purge option, but we do      mark a lot as deleted, and your mail client might remove that for      you.  We try to only mark as deleted once the moved/altered message      is correctly saved, but things might go wrong.  We *strongly*      recommend that you try this script out on mail that you can recover      from somewhere else, at least at first."""from __future__ import generatorstodo = """    o IMAP supports authentication via other methods than the plain-text      password method that we are using at the moment.  Neither of the      servers I have access to offer any alternative method, however.  If      someone's does, then it would be nice to offer this.      Thanks to #1169939 we now support CRAM_MD5 if available.  It'd still      be good to support others, though.    o Usernames should be able to be literals as well as quoted strings.      This might help if the username/password has special characters like      accented characters.    o Suggestions?"""# This module is part of the SpamBayes project, which is Copyright 2002-5# The Python Software Foundation and is covered by the Python Software# Foundation license.__author__ = "Tony Meyer <ta-meyer@ihug.co.nz>, Tim Stone"__credits__ = "All the SpamBayes folk. The original filter design owed " \              "much to isbg by Roger Binns (http://www.rogerbinns.com/isbg)."try:    True, Falseexcept NameError:    # Maintain compatibility with Python 2.2    True, False = 1, 0# If we are running as a frozen application, then chances are that# output is just lost.  We'd rather log this, like sb_server and Oulook# log, so that the user can pull up the output if possible.  We could just# rely on the user piping the output appropriately, but would rather have# more control.  The sb_server tray application only does this if not# running in a console window, but we do it whenever we are frozen.import osimport sysif hasattr(sys, "frozen"):    # We want to move to logging module later, so for now, we    # hack together a simple logging strategy.    try:        import win32api    except ImportError:        if sys.platform == "win32":            # Fall back to CWD, but warn user.            status = "Warning: your log is stored in the current " \                     "working directory.  We recommend installing " \                     "the pywin32 extensions, so that the log is " \                     "stored in the Windows temp directory."            temp_dir = os.getcwd()        else:            # Try for a /tmp directory.            if os.path.isdir("/tmp"):                temp_dir = "/tmp"                status = "Log file opened in /tmp"            else:                status = "Warning: your log is stored in the current " \                         "working directory.  If this does not suit you " \                         "please let the spambayes@python.org crowd know " \                         "so that an alternative can be arranged."    else:        temp_dir = win32api.GetTempPath()        status = "Log file opened in " + temp_dir    for i in range(3,0,-1):        try:            os.unlink(os.path.join(temp_dir, "SpamBayesIMAP%d.log" % (i+1)))        except os.error:            pass        try:            os.rename(                os.path.join(temp_dir, "SpamBayesIMAP%d.log" % i),                os.path.join(temp_dir, "SpamBayesIMAP%d.log" % (i+1))                )        except os.error:            pass    # Open this log, as unbuffered, so crashes still get written.    sys.stdout = open(os.path.join(temp_dir,"SpamBayesIMAP1.log"), "wt", 0)    sys.stderr = sys.stdoutimport socketimport reimport timeimport getoptimport typesimport threadimport tracebackimport emailimport email.Parserfrom getpass import getpassfrom email.Utils import parsedatetry:    import cStringIO as StringIOexcept ImportError:    import StringIOfrom spambayes import Statsfrom spambayes import messagefrom spambayes.Options import options, get_pathname_option, optionsPathnamefrom spambayes import tokenizer, storage, Dibblerfrom spambayes.UserInterface import UserInterfaceServerfrom spambayes.ImapUI import IMAPUserInterface, LoginFailurefrom spambayes.Version import get_current_versionfrom imaplib import IMAP4from imaplib import Time2Internaldatetry:    if options["imap", "use_ssl"]:        from imaplib import IMAP4_SSL as BaseIMAP    else:        from imaplib import IMAP4 as BaseIMAPexcept ImportError:    from imaplib import IMAP4 as BaseIMAPclass BadIMAPResponseError(Exception):    """An IMAP command returned a non-"OK" response."""    def __init__(self, command, response):        self.command = command        self.response = response    def __str__(self):        return "The command '%s' failed to give an OK response.\n%s" % \               (self.command, self.response)class IMAPSession(BaseIMAP):    '''A class extending the IMAP4 class, with a few optimizations'''    timeout = 60 # seconds    def __init__(self, server, port, debug=0, do_expunge=False):        # There's a tricky situation where if use_ssl is False, but we        # try to connect to a IMAP over SSL server, we will just hang        # forever, waiting for a response that will never come.  To        # get past this, just for the welcome message, we install a        # timeout on the connection.  Normal service is then returned.        # This only applies when we are not using SSL.        if not hasattr(self, "ssl"):            readline = self.readline            self.readline = self.readline_timeout        try:            BaseIMAP.__init__(self, server, port)        except (BaseIMAP.error, socket.gaierror, socket.error):            print "Cannot connect to server %s on port %s" % (server, port)            if not hasattr(self, "ssl"):                print "If you are connecting to an SSL server, please " \                      "ensure that you have the 'Use SSL' option enabled."            self.connected = False        else:            self.connected = True        if not hasattr(self, "ssl"):            self.readline = readline        self.debug = debug        self.do_expunge = do_expunge        self.server = server        self.port = port        self.logged_in = False        # For efficiency, we remember which folder we are currently        # in, and only send a select command to the IMAP server if        # we want to *change* folders.  This functionality is used by        # both IMAPMessage and IMAPFolder.        self.current_folder = None        # We override the base read so that we only read a certain amount        # of data at a time.  OS X and Python has problems with getting         # large amounts of memory at a time, so maybe this will be a way we        # can work around that (I don't know, and don't have a mac to test,        # but we need to try something).        self._read = self.read        self.read = self.safe_read    def readline_timeout(self):        """Read line from remote, possibly timing out."""        st_time = time.time()        self.sock.setblocking(False)        buffer = []        while True:            if (time.time() - st_time) > self.timeout:                if options["globals", "verbose"]:                    print >> sys.stderr, "IMAP Timing out"                break            try:                data = self.sock.recv(1)            except socket.error, e:                if e[0] == 10035:                    # Nothing to receive, keep going.                    continue                raise            if not data:                break            if data == '\n':                break            buffer.append(data)        self.sock.setblocking(True)        return "".join(buffer)    def login(self, username, pwd):        """Log in to the IMAP server, catching invalid username/password."""        assert self.connected, "Must be connected before logging in."        if 'AUTH=CRAM-MD5' in self.capabilities:            login_func = self.login_cram_md5            args = (username, pwd)            description = "MD5"        else:            login_func = BaseIMAP.login # superclass login            args = (self, username, pwd)            description = "plain-text"        try:            login_func(*args)        except BaseIMAP.error, e:            msg = "The username (%s) and/or password (sent in %s) may " \                  "be incorrect." % (username, description)            raise LoginFailure(msg)        self.logged_in = True    def logout(self):        """Log off from the IMAP server, possibly expunging.        Note that most, if not all, of the expunging is probably done in        SelectFolder, rather than here, for purposes of speed."""        # We may never have logged in, in which case we do nothing.        if self.connected and self.logged_in and self.do_expunge:            # Expunge messages from the ham, spam and unsure folders.            for fol in ["spam_folder",                        "unsure_folder",                        "ham_folder"]:                folder_name = options["imap", fol]                if folder_name:                    self.select(folder_name)                    self.expunge()            # Expunge messages from the ham and spam training folders.            for fol_list in ["ham_train_folders",                             "spam_train_folders",]:                for fol in options["imap", fol_list]:                    self.select(fol)                    self.expunge()        BaseIMAP.logout(self)  # superclass logout    def check_response(self, command, IMAP_response):        """A utility function to check the response from IMAP commands.        Raises BadIMAPResponseError if the response is not OK.  Returns        the data segment of the response otherwise."""        response, data = IMAP_response        if response != "OK":            raise BadIMAPResponseError(command, IMAP_response)        return data    def SelectFolder(self, folder):        """A method to point ensuing IMAP operations at a target folder.        This is essentially a wrapper around the IMAP select command, which        ignores the command if the folder is already selected."""        if self.current_folder != folder:            if self.current_folder != None and self.do_expunge:                # It is faster to do close() than a single                # expunge when we log out (because expunge returns                # a list of all the deleted messages which we don't do                # anything with).                self.close()                self.current_folder = None            if folder == "":                # This is Python bug #845560 - if the empty string is                # passed, we get a traceback, not just an 'invalid folder'                # error, so raise our own error.                raise BadIMAPResponseError("select",                                           "Cannot have empty string as "                                           "folder name in select")            # We *always* use SELECT and not EXAMINE, because this            # speeds things up considerably.            response = self.select(folder, None)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -