Beispiel #1
0
    def assertok(self, res, *args):
        """Check that the return code is OK.

        It also prints out what happened (which would end
        up /dev/null'ed in non-verbose mode)
        """
        if 'uid FETCH' in args[0] and not self.verbose_mails:
            res = utils.shorten(res, 140)
        if 'SEARCH' in args[0]:
            res = utils.shorten(res, 140)
        self.logger.debug("{} = {}".format(args, res))
        if res[0] not in ["OK", "BYE"]:
            self.logger.error(
                __("{} returned {} - aborting".format(args, res)))
            raise ISBGError(__exitcodes__['imap'] if self.exitcodes else -1,
                            "\n%s returned %s - aborting\n" % (repr(args), res)
                            )
Beispiel #2
0
    def assertok(self, res, *args):
        """Check that the return code is OK.

        It also prints out what happened (which would end
        up /dev/null'ed in non-verbose mode)
        """
        if 'uid FETCH' in args[0] and not self.verbose_mails:
            res = utils.shorten(res, 140)
        if 'SEARCH' in args[0]:
            res = utils.shorten(res, 140)
        self.logger.debug("{} = {}".format(args, res))
        if res[0] not in ["OK", "BYE"]:
            self.logger.error(__("{} returned {} - aborting".format(args,
                                                                    res)))
            raise ISBGError(
                __exitcodes__['imap'] if self.exitcodes else -1,
                "\n%s returned %s - aborting\n" % (repr(args), res))
Beispiel #3
0
    def learn(self, folder, learn_type, move_to, origpastuids):
        """Learn the spams (and if requested deleted or move them).

        Args:
            folder (str): The IMAP folder.
            leart_type (str): ```spam``` to learn spam, ```ham``` to learn
                nonspam.
            move_to (str): If not ```None```, the imap folder where the emails
                will be moved.
            origpastuids (list(int)): ``uids`` to not process.
        Returns:
            Sa_Learn:
                It contains the information about the result of the process.

            It will call ``spamc`` to learn the emails.

        Raises:
            isbg.ISBGError: if learn_type is unknown.


        TODO:
            Add suport to ``learn_type=forget``.

        """
        sa_learning = Sa_Learn()

        # Sanity checks:
        if learn_type not in ['spam', 'ham']:
            raise isbg.ISBGError(-1, message="Unknown learn_type")
        if self.imap is None:
            raise isbg.ISBGError(-1, message="Imap is required")

        self.logger.debug(__(
            "Teach {} to SA from: {}".format(learn_type, folder)))

        self.imap.select(folder)
        if self.learnunflagged:
            _, uids = self.imap.uid("SEARCH", None, "UNFLAGGED")
        elif self.learnflagged:
            _, uids = self.imap.uid("SEARCH", None, "(FLAGGED)")
        else:
            _, uids = self.imap.uid("SEARCH", None, "ALL")

        uids, sa_learning.newpastuids = SpamAssassin.get_formated_uids(
            uids, origpastuids, self.partialrun)

        sa_learning.tolearn = len(uids)

        for uid in uids:
            mail = imaputils.get_message(self.imap, uid, logger=self.logger)

            # Unwrap spamassassin reports
            unwrapped = sa_unwrap.unwrap(mail)
            if unwrapped is not None:
                self.logger.debug(__("{} Unwrapped: {}".format(
                    uid, utils.shorten(imaputils.mail_content(
                        unwrapped[0]), 140))))

            if unwrapped is not None and unwrapped:  # len(unwrapped)>0
                mail = unwrapped[0]

            if self.dryrun:
                self.logger.warning("Skipped learning due to dryrun!")
                continue
            else:
                code, code_orig = learn_mail(mail, learn_type)

            if code == -9999:  # error processing email, try next.
                self.logger.exception(__(
                    'spamc error for mail {}'.format(uid)))
                self.logger.debug(repr(imaputils.mail_content(mail)))
                continue

            if code in [69, 74]:
                raise isbg.ISBGError(
                    isbg.__exitcodes__['flags'],
                    "spamassassin is misconfigured (use --allow-tell)")

            if code == 5:  # learned.
                sa_learning.learned += 1
                self.logger.debug(__(
                    "Learned {} (spamc return code {})".format(uid,
                                                               code_orig)))

            elif code == 6:  # already learned.
                self.logger.debug(__(
                    "Already learned {} (spamc return code {})".format(
                        uid, code_orig)))

            elif code == 98:  # too big.
                self.logger.warning(__(
                    "{} is too big (spamc return code {})".format(
                        uid, code_orig)))

            else:
                raise isbg.ISBGError(-1, ("{}: Unknown return code {} from " +
                                          "spamc").format(uid, code_orig))

            sa_learning.uids.append(int(uid))

            if not self.dryrun:
                if self.learnthendestroy:
                    if self.gmail:
                        self.imap.uid("COPY", uid, "[Gmail]/Trash")
                    else:
                        self.imap.uid("STORE", uid, self.spamflagscmd,
                                      "(\\Deleted)")
                elif move_to is not None:
                    self.imap.uid("COPY", uid, move_to)
                elif self.learnthenflag:
                    self.imap.uid("STORE", uid, self.spamflagscmd,
                                  "(\\Flagged)")

        return sa_learning
Beispiel #4
0
def test_shorten():
    """Test the shorten function."""
    # We try with dicts:
    dic = {1: 'Option 1', 2: u'Option 2', 3: b'Option 3'}
    assert dic == utils.shorten(dic, 8), "The dicts should be the same."
    dic2 = utils.shorten(dic, 7)
    assert dic != dic2, "The dicts should be diferents."
    # Note: py2 and py3:
    assert dic2[1] in ['u\'Opti…', '\'Optio…'], "Unexpected shortened string."
    assert dic2[2] in ['u\'Opti…', '\'Optio…'], "Unexpected shortened string."
    assert dic2[3] in ['\'Optio…', 'b\'Opti…'], "Unexpected shortened string."

    # We try with lists:
    ls = ['Option 1', 'Option 2', 'Option 3']
    assert ls == utils.shorten(ls, 8)
    ls2 = utils.shorten(ls, 7)
    for k in ls2:
        assert k in ['u\'Opti…', '\'Optio…'], "Unexpected shortened string."

    # We try with strings:
    assert "Option 1" == utils.shorten("Option 1", 8), \
        "Strings should be the same."
    assert utils.shorten("Option 1", 7) in ['u\'Opti…', "\'Optio…"], \
        "Strings should be diferents."

    # Others:
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(None, 8)
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(None, 7)
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(False, 8)
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(True, 7)
    with pytest.raises(TypeError, message="int should raise a TypeError."):
        utils.shorten(1, 7)
    with pytest.raises(TypeError, message="float should raise a TypeError."):
        utils.shorten(1.0, 7)
    with pytest.raises(ValueError, message="length should be at least 1."):
        utils.shorten("123", 0)
    with pytest.raises(TypeError, message="int should be not supported."):
        assert utils.shorten([1, 2, 3], 2)
    assert utils.shorten(["111", "2", "3"], 3) == ["111", "2", "3"]
    assert utils.shorten(("111", "2", "3"), 3) == ("111", "2", "3")
Beispiel #5
0
def test_shorten():
    """Test the shorten function."""
    # We try with dicts:
    dic = {1: 'Option 1', 2: u'Option 2', 3: b'Option 3'}
    assert dic == utils.shorten(dic, 8), "The dicts should be the same."
    dic2 = utils.shorten(dic, 7)
    assert dic != dic2, "The dicts should be diferents."
    # Note: py2 and py3:
    assert dic2[1] in ['u\'Opti…', '\'Optio…'], "Unexpected shortened string."
    assert dic2[2] in ['u\'Opti…', '\'Optio…'], "Unexpected shortened string."
    assert dic2[3] in ['\'Optio…', 'b\'Opti…'], "Unexpected shortened string."

    # We try with lists:
    ls = ['Option 1', 'Option 2', 'Option 3']
    assert ls == utils.shorten(ls, 8)
    ls2 = utils.shorten(ls, 7)
    for k in ls2:
        assert k in ['u\'Opti…', '\'Optio…'], "Unexpected shortened string."

    # We try with strings:
    assert "Option 1" == utils.shorten("Option 1", 8), \
        "Strings should be the same."
    assert utils.shorten("Option 1", 7) in ['u\'Opti…', "\'Optio…"], \
        "Strings should be diferents."

    # Others:
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(None, 8)
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(None, 7)
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(False, 8)
    with pytest.raises(TypeError, message="None should raise a TypeError."):
        utils.shorten(True, 7)
    with pytest.raises(TypeError, message="int should raise a TypeError."):
        utils.shorten(1, 7)
    with pytest.raises(TypeError, message="float should raise a TypeError."):
        utils.shorten(1.0, 7)
    with pytest.raises(ValueError, message="length should be at least 1."):
        utils.shorten("123", 0)
    with pytest.raises(TypeError, message="int should be not supported."):
        assert utils.shorten([1, 2, 3], 2)
    assert utils.shorten(["111", "2", "3"], 3) == ["111", "2", "3"]
    assert utils.shorten(("111", "2", "3"), 3) == ("111", "2", "3")
Beispiel #6
0
    def learn(self, folder, learn_type, move_to, origpastuids):
        """Learn the spams (and if requested deleted or move them).

        Args:
            folder (str): The IMAP folder.
            leart_type (str): ```spam``` to learn spam, ```ham``` to learn
                nonspam.
            move_to (str): If not ```None```, the imap folder where the emails
                will be moved.
            origpastuids (list(int)): ``uids`` to not process.
        Returns:
            Sa_Learn:
                It contains the information about the result of the process.

            It will call ``spamc`` to learn the emails.

        Raises:
            isbg.ISBGError: if learn_type is unknown.


        TODO:
            Add suport to ``learn_type=forget``.

        """
        sa_learning = Sa_Learn()

        # Sanity checks:
        if learn_type not in ['spam', 'ham']:
            raise isbg.ISBGError(-1, message="Unknown learn_type")
        if self.imap is None:
            raise isbg.ISBGError(-1, message="Imap is required")

        self.logger.debug(
            __("Teach {} to SA from: {}".format(learn_type, folder)))

        self.imap.select(folder)
        if self.learnunflagged:
            _, uids = self.imap.uid("SEARCH", None, "UNFLAGGED")
        elif self.learnflagged:
            _, uids = self.imap.uid("SEARCH", None, "(FLAGGED)")
        else:
            _, uids = self.imap.uid("SEARCH", None, "ALL")

        uids, sa_learning.newpastuids = SpamAssassin.get_formated_uids(
            uids, origpastuids, self.partialrun)

        sa_learning.tolearn = len(uids)

        for uid in uids:
            mail = imaputils.get_message(self.imap, uid, logger=self.logger)

            # Unwrap spamassassin reports
            unwrapped = sa_unwrap.unwrap(mail)
            if unwrapped is not None:
                self.logger.debug(
                    __("{} Unwrapped: {}".format(
                        uid,
                        utils.shorten(imaputils.mail_content(unwrapped[0]),
                                      140))))

            if unwrapped is not None and unwrapped:  # len(unwrapped)>0
                mail = unwrapped[0]

            if self.dryrun:
                self.logger.warning("Skipped learning due to dryrun!")
                continue
            else:
                code, code_orig = learn_mail(mail, learn_type)

            if code == -9999:  # error processing email, try next.
                self.logger.exception(__(
                    'spamc error for mail {}'.format(uid)))
                self.logger.debug(repr(imaputils.mail_content(mail)))
                continue

            if code in [69, 74]:
                raise isbg.ISBGError(
                    isbg.__exitcodes__['flags'],
                    "spamassassin is misconfigured (use --allow-tell)")

            if code == 5:  # learned.
                sa_learning.learned += 1
                self.logger.debug(
                    __("Learned {} (spamc return code {})".format(
                        uid, code_orig)))

            elif code == 6:  # already learned.
                self.logger.debug(
                    __("Already learned {} (spamc return code {})".format(
                        uid, code_orig)))

            elif code == 98:  # too big.
                self.logger.warning(
                    __("{} is too big (spamc return code {})".format(
                        uid, code_orig)))

            else:
                raise isbg.ISBGError(-1, ("{}: Unknown return code {} from " +
                                          "spamc").format(uid, code_orig))

            sa_learning.uids.append(int(uid))

            if not self.dryrun:
                if self.learnthendestroy:
                    if self.gmail:
                        self.imap.uid("COPY", uid, "[Gmail]/Trash")
                    else:
                        self.imap.uid("STORE", uid, self.spamflagscmd,
                                      "(\\Deleted)")
                elif move_to is not None:
                    self.imap.uid("COPY", uid, move_to)
                elif self.learnthenflag:
                    self.imap.uid("STORE", uid, self.spamflagscmd,
                                  "(\\Flagged)")

        return sa_learning