#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
#
import kopano
from MAPI.Util import *
import sys
import binascii
from terminaltables import AsciiTable
from datetime import datetime
import time


def opt_args():

    parser = kopano.parser('skpc')
    parser.add_option("--user", dest="user", action="store", help="Run script for user ")
    parser.add_option("--list", dest="printrules", action="store_true", help="Print rules")
    parser.add_option("--rule", dest="rule", action="store", type="int", help="rule id")
    parser.add_option("--state", dest="state", action="store", help="enable, disable, delete, create")
    parser.add_option("--create", dest="createrule", action="store",
                      help="create rule, use  --conditions and --actions")
    parser.add_option("--conditions", dest="conditions", action="store", help="conditions")
    parser.add_option("--actions", dest="actions", action="store", help="actions")
    parser.add_option("--exceptions", dest="exceptions", action="store", help="exceptions")

    return parser.parse_args()


def checkgab(server, email):
    global temp
    check = False
    entryid = None
    name = None
    for address in server.gab_table():
        for prop in address:
            if str(prop.idname) == 'PR_ENTRYID':
                temp = prop.value
            if prop.idname == 'PR_DISPLAY_NAME':
                temp = prop.value
            try:
                if str(email) == str(prop.value.lower()):
                    check = True
                    name = temp
                    return check, name
            except AttributeError:
                continue
    return check, name

def searchusername(server, name):
    for user in server.users():
        if str(user.fullname) == name:
            return user

def convertcondition(conditions):
    condition_message = ''
    conlist = []
    totalnum = 0
    messagelist = []
    try:
        conditions = conditions.lpRes
        totalconditions = len(conditions.lpRes)
    except AttributeError:
        conditions = conditions
        try:
            totalconditions = len(conditions)
        except AttributeError:
            conditions = [conditions]
            totalconditions = len(conditions)


    for condition in conditions:
        connum = 0
        # SOrRestriction
        if isinstance(condition, SOrRestriction):
            totaladdresses = len(condition.lpRes)
            numaddress = 0
            for addresses in condition.lpRes:
                if isinstance(addresses, SCommentRestriction):
                    proptag = hex(addresses.lpRes.ulPropTag)
                    if proptag not in conlist:
                        conlist.append(proptag)
                        if proptag == "0xc1d0102":
                            condition_message += "Is received from "

                    condition_message += addresses.lpRes.lpProp.Value.replace('kopano:', '').lower()

                if isinstance(addresses, SContentRestriction):
                    proptag = hex(addresses.ulPropTag)
                    if proptag not in conlist:
                        conlist.append(proptag)
                        if proptag == '0xc1d0102':
                            condition_message += "Includes these words in the sender's address: "
                        if proptag == '0x37001f':
                            condition_message += "Includes these words in the subject: "
                        if proptag == '0x1000001f':
                            condition_message += "Includes these words in the body: "
                    condition_message += addresses.lpProp.Value

                numaddress += 1
                if numaddress != totaladdresses and totaladdresses != 1:
                    condition_message += ", "
                if numaddress == totaladdresses and totaladdresses != 1:
                    condition_message += "\n"

        # single.
        if isinstance(condition, SContentRestriction):
            if not SContentRestriction in conlist:
                conlist.append(SContentRestriction)
                proptag = hex(condition.ulPropTag).lower()
                if proptag == '0xc1d0102':
                    condition_message += "Includes these words in the sender's address: "
                if proptag == '0x37001f':
                    condition_message += "Includes these words in the subject: "
                if proptag == '0x1000001f':
                    condition_message += "Includes these words in the body: "
            condition_message += "%s \n" % condition.lpProp.Value


        if isinstance(condition, SPropertyRestriction):
            proptag = hex(condition.ulPropTag)
            if proptag not in conlist:
                conlist.append(proptag)
                if proptag == '0x57000b' and condition.lpProp.Value :
                    condition_message += "Is sent only to me \n"
                if proptag == '0x57000b' and not condition.lpProp.Value and '0x58000b' not in conlist:
                    condition_message += "When my name is in the To box\n"
                if proptag == '0x58000b':
                    condition_message += "When my name is in the Cc box\n"
                if proptag == '0x59000b' and '0x58000b' not in conlist:
                    condition_message += "When my name is in the To or Cc box\n"

            if proptag == '0x360003':
                sens = {0: 'normal',
                        1: 'personal',
                        2: 'private',
                        3: 'confidential',
                        }
                condition_message += "If it is marked as %s sensitivity\n" % sens[condition.lpProp.Value]

            if proptag == '0x170003':
                importancevalue = {0: "low",
                                   1: "normal",
                                   2: "high"}
                condition_message += "Has importance %s \n" % importancevalue[int(condition.lpProp.Value)]

            if proptag == '0xe080003':
                if proptag not in conlist:
                    conlist.append(proptag)
                    condition_message += "if received "
                if condition.relop == 2:
                    condition_message += "at least %s kb " % (int(condition.lpProp.Value) / 10)
                if condition.relop == 0:
                    condition_message += "and at most %s kb " % (int(condition.lpProp.Value) / 10)

            if proptag == '0xe060040':
                if proptag not in conlist:
                    conlist.append(proptag)
                    condition_message += "if received "
                if condition.relop == 2:
                    condition_message += "after %s " % condition.lpProp.Value
                if condition.relop == 0:
                    condition_message += "and before %s " % condition.lpProp.Value

        if isinstance(condition, SBitMaskRestriction):
            condition_message += "Which has an attachment \n"

        # multiple values
        if isinstance(condition, SAndRestriction):
            for andcon in condition.lpRes:
                if isinstance(andcon, SPropertyRestriction):
                    proptag = hex(andcon.ulPropTag)
                    if proptag == '0x57000b' and andcon.lpProp.Value:
                        condition_message += "Is sent only to me \n"
                    if proptag == '0x57000b' and not andcon.lpProp.Value:
                       condition_message += "When my name is in the Cc box\n"
                    if proptag == '0x58000b':
                        condition_message += "When my name is in the To box\n"
                    if proptag == '0x59000b':
                        condition_message += "When my name is in the To or Cc box\n"
                    if proptag == '0x360003':
                        sens = {0: 'normal',
                                1: 'personal',
                                2: 'private',
                                3: 'confidential',
                                }
                        condition_message += "If it is marked as %s sensitivity\n" % sens[andcon.lpProp.Value]
                    if proptag == '0x170003':
                        importancevalue = {0: "low",
                                           1: "normal",
                                           2: "high"}
                        condition_message += "Has importance %s \n" % importancevalue[int(andcon.lpProp.Value)]
                    if proptag == '0xe080003':
                        if proptag not in conlist:
                            conlist.append(proptag)
                            condition_message += "if received "
                        if andcon.relop == 2:
                            condition_message += "at least %s kb " % (int(andcon.lpProp.Value) / 10)
                        if andcon.relop == 0:
                            condition_message += "and at most %s kb \n" % (int(andcon.lpProp.Value) / 10)
                    if proptag == '0xe060040':
                        if proptag not in conlist:
                            conlist.append(proptag)
                            condition_message += "if received "
                        if andcon.relop == 2:
                            condition_message += "after %s " % andcon.lpProp.Value
                        if andcon.relop == 0:
                            condition_message += "and before %s \n" % andcon.lpProp.Value

                if isinstance(condition, SBitMaskRestriction):
                    condition_message += "Which has an attachment\n"

        #exceptions at the end
        if isinstance(condition, SNotRestriction):
            # create list, so we don't need to run this part twice
            if isinstance(condition.lpRes, SOrRestriction):
                listconditions = condition.lpRes.lpRes
                countconditions = len(condition.lpRes.lpRes)
            else:
                listconditions =  [condition.lpRes]
                countconditions = len(listconditions)
            for cond in listconditions:
                if isinstance(cond, SCommentRestriction):
                    content = cond.rt
                    email = cond.lpRes.lpProp.Value.replace('kopano:', '').replace('SMTP:', '').lower()
                    if content == 10:
                        if connum == 0:
                            condition_message += 'NOT received from: '
                        condition_message += email

                if isinstance(cond, SContentRestriction):


                    proptag = hex(cond.ulPropTag)
                    if proptag not in conlist:
                        conlist.append(proptag)
                        if 'Except' in condition_message:
                            condition_message += "\n"
                        if proptag == '0xc1d0102':
                            condition_message += "Except if the sender's address contains: "
                        if proptag == '0x37001f':
                            condition_message += "Except if the subject contains: "
                        if proptag == '0x1000001f':
                            condition_message += "Except if the body contains: "

                    condition_message += cond.lpProp.Value

                if isinstance(cond, SAndRestriction):
                    andnum = 0
                    for andcon in cond.lpRes:
                        if isinstance(andcon, SPropertyRestriction):
                            proptag = hex(andcon.ulPropTag)
                            if proptag == '0x57000b':
                                condition_message += "Except if sent only to me \n"
                            if proptag == '0x57000b' and not andcon.lpProp.Value:
                                condition_message += "Except when my name is in the Cc box\n"
                            if proptag == '0xe080003':
                                if andnum ==0:
                                    condition_message += "Except with a size "
                                if andcon.relop == 2:
                                    condition_message += "at least %s kb " % (int(andcon.lpProp.Value) /10)
                                if andcon.relop == 0:
                                    condition_message += "and at most %s kb \n" % (int(andcon.lpProp.Value) /10)
                            if proptag == '0xe060040':
                                if andnum == 0:
                                    condition_message += "Except if received "
                                if andcon.relop == 2:
                                    condition_message += "after %s " % andcon.lpProp.Value
                                if andcon.relop == 0:
                                    condition_message += "and before %s \n" % andcon.lpProp.Value
                        andnum += 1



                if isinstance(cond, SPropertyRestriction):
                    proptag = hex(cond.ulPropTag)
                    if proptag == '0x57000b':
                        condition_message += "Except when my name is in the To box\n"
                    if proptag == '0x59000b':
                        condition_message += "Except when my name is in the To or Cc box\n"
                    if proptag == '0x360003':
                        sens = {0: 'normal',
                                1: 'personal',
                                2: 'private',
                                3: 'confidential',
                        }
                        condition_message += "Except if it is marked as %s sensitivity\n" % sens[cond.lpProp.Value]
                    if proptag == '0x170003':
                        sens = {0: 'low',
                                1: 'normal',
                                2: 'high',
                                }
                        condition_message += "Except if it is marked as %s importance\n" % sens[cond.lpProp.Value]

                connum += 1
                if connum != countconditions and countconditions != 1:
                    condition_message += ", "
                if connum == countconditions and countconditions != 1:
                    condition_message += "\n"

    return condition_message


def convertaction(action, user,server):

    action_message = ''
    movetype = {1: 'Move',
                2: 'Copy',}
    countact = len(action.Value.lpAction)
    num = 0

    for act in action.Value.lpAction:
        if isinstance(act.actobj, actMoveCopy):
            folderid = binascii.hexlify(act.actobj.FldEntryId)
            storeid = act.actobj.StoreEntryId
            try:
                try:
                    foldername = user.store.folder(entryid=folderid).name
                except TypeError:
                    foldername = user.store.folder(folderid).name
            except kopano.NotFoundError:
                mapistore = server.mapisession.OpenMsgStore(0, storeid, IID_IMsgStore, MDB_WRITE)
                newstore = kopano.Store(mapiobj=mapistore, server=server)
                try:
                    foldername = '%s (%s)' % (newstore.folder(entryid=folderid).name, newstore.user.name)
                except TypeError:
                    foldername = '%s (%s)' % (newstore.folder(folderid).name, newstore.user.name)


            if act.acttype == 1:
                if folderid == binascii.hexlify(user.store.prop(PR_IPM_WASTEBASKET_ENTRYID).value):
                    action_message += 'Delete message'
                else:
                    action_message += "%s message to folder '%s'" % (movetype[act.acttype], foldername)
            else:
                action_message += "%s message to folder '%s'" % (movetype[act.acttype], foldername)

        if isinstance(act.actobj, actFwdDelegate):
            sendstype = {0: 'Forward message to ',
                         3: 'Redirect message to ',
                         4: 'Forward the message as attachment to '}

            countaddress = len(act.actobj.lpadrlist)
            addnum = 0
            action_message += sendstype[act.ulActionFlavor]
            for addresses in act.actobj.lpadrlist:
                action_message += addresses[5].Value

                addnum += 1
                if addnum != countaddress and countaddress != 1:
                    action_message += ","

        num += 1
        if num != countact and countact != 1:
            action_message += "\n"

    return action_message


def printrules(filters, user, server):

    rulestate = {0: "Disabled",
                 1: "Enabled",
                 2: "Error",
                 3: "Enabled but error reported",
                 4: "Only active when OOF is active",
                 16: "Disabled",
                 17: "Enabled (stop further rules)"}

    table_data = [["Number", "Name", "Condition", "Action", "State"]]
    for rule in filters:

        condition_message = convertcondition(rule[4].Value)

        actions = convertaction(rule[5], user,server)
        name = rule[7].Value
        if not isinstance(condition_message, unicode):
            condition = unicode(condition_message, encoding='ISO-8859-1')
        else:
            condition = condition_message
        table_data.append(
            [rule[0].Value, name, condition, unicode(actions),
             unicode(rulestate[rule[2].Value])])

    table = AsciiTable(table_data)
    print(table.table)


def changerule(filters, number, state):
    rowlist = ''
    convertstate = {'enable': ST_ENABLED,
                    'disable': ST_DISABLED
                    }

    rule = filters[number - 1]
    for prop in rule:
        if prop.ulPropTag == PR_RULE_ACTIONS:
            actions = prop.Value
        if prop.ulPropTag == PR_RULE_CONDITION:
            conditions = prop.Value
        if prop.ulPropTag == PR_RULE_NAME:
            name = prop.Value
        if prop.ulPropTag == PR_RULE_SEQUENCE:
            sequence = prop.Value
        if prop.ulPropTag == PR_RULE_PROVIDER_DATA:
            provider_data = binascii.hexlify(prop.Value)

    if state == 'enable' or state == 'disable':
        rowlist = [ROWENTRY(
            ROW_MODIFY,
            [SPropValue(PR_RULE_ID, number),
             SPropValue(PR_RULE_PROVIDER_DATA, binascii.unhexlify(provider_data)),
             SPropValue(PR_RULE_STATE, convertstate[state]),
             SPropValue(PR_RULE_ACTIONS, actions),
             SPropValue(PR_RULE_CONDITION, conditions),
             SPropValue(PR_RULE_SEQUENCE, sequence),
             SPropValue(1719730206, 'RuleOrganizer'),
             SPropValue(PR_RULE_NAME, name)
             ])]

    if state == 'delete':
        rowlist = [ROWENTRY(
            ROW_REMOVE,
            [SPropValue(PR_RULE_ID, number)]
        )]

    return rowlist, name


def createrule(options, lastid):
    try:
        conditions = options.conditions.split(';')
    except AttributeError:
        conditions = []
    actions = options.actions.split(';')
    try:
        exceptions = options.exceptions.split(';')
    except AttributeError:
        exceptions = []
    server = kopano.Server(options)
    storeconditions = []
    storeactions = []
    storeexceptions = []

    for condition in conditions:
        conditionslist = []
        splitcondition = condition.split(':')
        condition_rule = splitcondition[0]
        try:
            condition_var = splitcondition[1].split(',')
        except IndexError:
            condition_var = ''

        if condition_rule == 'received-from' or condition_rule == 'sent-to':
            for user in condition_var:
                check, tmpname = checkgab(server, user)
                if check:
                    frommail = 'kopano:%s' % user.upper()
                    fromname = u'%s <%s>' % (tmpname, user)
                else:
                    frommail = 'SMTP:%s' % user.upper()
                    fromname = u'%s <%s>' % (user, user)
                if condition_rule == 'received-from':
                    conditionslist.append(SCommentRestriction(
                        SPropertyRestriction(4, 0xc1d0102, SPropValue(0x00010102, '%s\x00' % frommail)),
                        [SPropValue(0x60000003, 1L), SPropValue(0x00010102, '%s\x00' % frommail),
                         SPropValue(0x0001001F, fromname), SPropValue(0x39000003, 0L)]))

                if condition_rule == 'sent-to':
                    conditionslist.append(SSubRestriction(0xe12000d, SCommentRestriction(
                        SPropertyRestriction(4, 0x300b0102, SPropValue(0x00010102, '%s\x00' % frommail)),
                        [SPropValue(0x60000003, 1L), SPropValue(0x00010102, '%s\x00' % frommail),
                         SPropValue(0x0001001F, fromname), SPropValue(0x39000003, 0L)])))

            if len(conditionslist) > 1:
                storeconditions.append(SOrRestriction(conditionslist))
            else:
                storeconditions.append(conditionslist[0])


        if condition_rule == 'importance':
            importancevalue = {"low": 0,
                               "normal": 1,
                               "high": 2}
            getlevel = importancevalue[condition_var[0].lower()]
            storeconditions.append(SPropertyRestriction(4, 0x170003, SPropValue(0x00170003, getlevel)))


        if condition_rule == 'sent-only-to-me':
            storeconditions.append(SAndRestriction([SPropertyRestriction(4, 0x57000b, SPropValue(0x0057000B, True)),
                                                    SNotRestriction(SContentRestriction(1, 0xe04001f,
                                                                                        SPropValue(0x0E04001F, u';'))),
                                                    SPropertyRestriction(4, 0xe03001f, SPropValue(0x0E03001F, u''))])
                                   )

        if condition_rule == 'contain-word-sender-address' or condition_rule == 'contain-word-in-subject' or condition_rule == 'contain-word-in-body':
            for word in condition_var:
                if condition_rule == 'contain-word-sender-address':
                    conditionslist.append(SContentRestriction(1, 0xc1d0102, SPropValue(0x0C1D0102, word.decode('utf8').encode('ISO-8859-1'))))
                if condition_rule == 'contain-word-in-subject':
                    conditionslist.append(SContentRestriction(65537, 0x37001f, SPropValue(0x0037001F, word.decode('utf8'))))
                if condition_rule == 'contain-word-in-body':
                    conditionslist.append(SContentRestriction(65537, 0x1000001f, SPropValue(0x1000001F, word.decode('utf8'))))
            if len(conditionslist) > 1:
                storeconditions.append(SOrRestriction(conditionslist))
            else:
                storeconditions.append(conditionslist[0])

        if condition_rule == 'message-size':
            if condition_var[0] <= condition_var[1]:
                lowvalue = condition_var[0]
                highvalue= condition_var[1]
            else:
                lowvalue = condition_var[1]
                highvalue= condition_var[0]

            storeconditions.append(SAndRestriction([SPropertyRestriction(2,0xe080003,SPropValue(0x0E080003, int(lowvalue) *10)),
                                                                    SPropertyRestriction(0,0xe080003,SPropValue(0x0E080003, int(highvalue) *10))]))
        if condition_rule == 'received-date':
            date1 = MAPI.Time.unixtime(time.mktime(datetime.strptime(condition_var[0], '%d-%m-%Y').timetuple()))
            date2 = MAPI.Time.unixtime(time.mktime(datetime.strptime(condition_var[1], '%d-%m-%Y').timetuple()))
            if date1 <= date2:
                datelow = date1
                datehigh = date2
            else:
                datelow = date2
                datehigh = date1
            storeconditions.append(SAndRestriction([SPropertyRestriction(2,0xe060040,SPropValue(0x0E060040, datelow)),
                                                                    SPropertyRestriction(0,0xe060040,SPropValue(0x0E060040, datehigh))]))
        if condition_rule == 'name-in-to-or-cc':
            storeconditions.append(SPropertyRestriction(4,0x59000b,SPropValue(0x0059000B, True)))
        if condition_rule == 'name-in-to':
            storeconditions.append(SPropertyRestriction(4,0x57000b,SPropValue(0x0057000B, False)))
        if condition_rule == 'name-in-cc':
            storeconditions.append(
                SAndRestriction([SPropertyRestriction(4,0x58000b,SPropValue(0x0058000B, True)),
                                                 SPropertyRestriction(4,0x59000b,SPropValue(0x0059000B, True)),
                                                 SPropertyRestriction(4,0x57000b,SPropValue(0x0057000B, False))]))
        if condition_rule == 'only-sent-to-me':
            storeconditions.append(SAndRestriction([SPropertyRestriction(4,0x57000b,SPropValue(0x0057000B, True)),
                                                   SNotRestriction(SContentRestriction(1,0xe04001f,SPropValue(0x0E04001F, u';'))),
                                                   SPropertyRestriction(4,0xe03001f,SPropValue(0x0E03001F, u''))]))
        if condition_rule == 'has-attachment':
            storeconditions.append(SBitMaskRestriction(1,0xe070003,16))
        if condition_rule == 'sensitivity':
            sens = {'normal': 0,
                    'personal': 1,
                    'private': 2,
                    'confidential': 3}
            storeconditions.append(SPropertyRestriction(4,0x360003,SPropValue(0x00360003, sens[condition_var[0].lower()])))

    # action part
    for action in actions:
        splitactions = action.split(':')
        action_rule = splitactions[0]
        if not action_rule == 'delete':
            action_var = splitactions[1].split(',')
        actionslist = []

        if action_rule == 'forward-to' or action_rule == 'redirect-to' or action_rule == 'forward-as-attachment':
            for user in action_var:
                check, tmpname = checkgab(server, user)

                if check:
                    tomail = 'kopano:%s' % user.upper()
                    fullname = tmpname
                    username = searchusername(server, tmpname)
                    name = username.name
                    entryid = username.userid
                    protocol = u'kopano'
                else:
                    tomail = 'SMTP:%s' % user.upper()
                    fullname = user
                    name = user
                    entryid = binascii.hexlify(tomail)  # XXXX can be broken.
                    protocol = u'SMTP'

                actionslist.append([SPropValue(0x0FFF0102,
                                               binascii.unhexlify(entryid)),
                                    SPropValue(0x0FFE0003, 6L), SPropValue(0x3001001F, u'%s' % fullname),
                                    SPropValue(0x39000003, 0L), SPropValue(0x3003001F, u'%s' % name),
                                    SPropValue(0x39FE001F, u'%s' % user), SPropValue(0x3002001F, protocol),
                                    SPropValue(0x0C150003, 1L), SPropValue(0x300B0102, '%s\x00' % tomail)])


                if action_rule == 'forward-to':
                    if len(actionslist) > 0:
                        storeactions.append(ACTION(7, 0, None, None, 0x0, actFwdDelegate(actionslist)))

                if action_rule == 'redirect-to':
                    if len(actionslist) > 0:
                        storeactions.append(ACTION(7, 3, None, None, 0x0, actFwdDelegate(actionslist)))

                if action_rule == 'forward-as-attachment':
                    if len(actionslist) > 0:
                        storeactions.append(ACTION(7, 4, None, None, 0x0, actFwdDelegate(actionslist)))


        if action_rule == 'move-to' or action_rule == 'copy-to' or action_rule == 'delete':
            if not action_rule == 'delete':
                try:
                    user = server.user(action_var[1])
                except kopano.NotFoundError:
                    print("user '%s' not found" % action_var[1])
                    sys.exit()
                except IndexError:
                    user = server.user(options.user)

                folders = action_var[0].split('/')
                num = 0
                for searchfolder in folders:
                    try:
                        if num == 0:
                            getfolder = user.store.folder(searchfolder)
                        else:
                            getfolder = getfolder.folder(searchfolder)
                        num += 1
                    except kopano.NotFoundError:
                        print("Folder '%s' does not exist" % searchfolder)
                        sys.exit()
            else:
                user = server.user(options.user)
            if action_rule == 'move-to':
                storeactions.append(ACTION(1, 0, None, None, 0x0, actMoveCopy(binascii.unhexlify(user.store.entryid),
                                                                              binascii.unhexlify(getfolder.entryid))))
            if action_rule == 'copy-to':
                storeactions.append(ACTION(2, 0, None, None, 0x0, actMoveCopy(binascii.unhexlify(user.store.entryid),
                                                                              binascii.unhexlify(getfolder.entryid))))
            if action_rule == 'delete':
                storeactions.append(ACTION(1, 0, None, None, 0x0, actMoveCopy(binascii.unhexlify(user.store.entryid),
                                                                              binascii.unhexlify(
                                                                                  user.store.wastebasket.entryid))))

    #exception part
    for exception in exceptions:
        splitexception = exception.split(':')
        exception_rule = splitexception[0]
        try:
            exception_var = splitexception[1].split(',')
        except IndexError:
            exception_var = ''
        exceptionslist = []

        if exception_rule == 'name-in-to-or-cc':
            storeexceptions.append(SNotRestriction(SPropertyRestriction(4,0x59000b,SPropValue(0x0059000B, True))))
        if exception_rule == 'name-in-to':
            storeexceptions.append(SNotRestriction(SPropertyRestriction(4,0x57000b,SPropValue(0x0057000B, False))))
        if exception_rule == 'name-in-cc':
            storeexceptions.append(
                SNotRestriction(SAndRestriction([SPropertyRestriction(4,0x58000b,SPropValue(0x0058000B, True)),
                                                 SPropertyRestriction(4,0x59000b,SPropValue(0x0059000B, True)),
                                                 SPropertyRestriction(4,0x57000b,SPropValue(0x0057000B, False))])))
        if exception_rule == 'only-sent-to-me':
            storeexceptions.append(SNotRestriction(SAndRestriction([SPropertyRestriction(4,0x57000b,SPropValue(0x0057000B, True)),
                                                   SNotRestriction(SContentRestriction(1,0xe04001f,SPropValue(0x0E04001F, u';'))),
                                                   SPropertyRestriction(4,0xe03001f,SPropValue(0x0E03001F, u''))])))
        if exception_rule == 'has-attachment':
            storeexceptions.append(SNotRestriction(SBitMaskRestriction(1,0xe070003,16)))
        if exception_rule == 'sensitivity':
            sens = {'normal': 0,
                    'personal': 1,
                    'private': 2,
                    'confidential': 3}
            storeexceptions.append(SNotRestriction(SPropertyRestriction(4,0x360003,SPropValue(0x00360003, sens[exception_var[0].lower()]))))
        if exception_rule == 'importance':
            imp = {'low': 0,
                    'normal': 1,
                    'high': 2}
            storeexceptions.append(SNotRestriction(SPropertyRestriction(4,0x170003,SPropValue(0x00170003, imp[exception_var[0].lower()]))))
        if exception_rule == 'message-size':
            if exception_var[0] <= exception_var[1]:
                lowvalue = exception_var[0]
                highvalue= exception_var[1]
            else:
                lowvalue = exception_var[1]
                highvalue= exception_var[0]
            storeexceptions.append(SNotRestriction(SAndRestriction([SPropertyRestriction(2,0xe080003,SPropValue(0x0E080003, int(lowvalue) *10)),
                                                                    SPropertyRestriction(0,0xe080003,SPropValue(0x0E080003, int(highvalue) *10))])))
        if exception_rule == 'received-date':
            date1 = MAPI.Time.unixtime(time.mktime(datetime.strptime(exception_var[0], '%d-%m-%Y').timetuple()))
            date2 = MAPI.Time.unixtime(time.mktime(datetime.strptime(exception_var[1], '%d-%m-%Y').timetuple()))
            if date1 <= date2:
                datelow = date1
                datehigh = date2
            else:
                datelow = date2
                datehigh = date1
            storeexceptions.append(SNotRestriction(SAndRestriction([SPropertyRestriction(2,0xe060040,SPropValue(0x0E060040, datelow)),
                                                                    SPropertyRestriction(0,0xe060040,SPropValue(0x0E060040, datehigh))])))

        if exception_rule == 'received-from' or exception_rule == 'sent-to':
            for user in exception_var:
                check, tmpname = checkgab(server, user)
                if check:
                    frommail = 'kopano:%s' % user.upper()
                    fromname = u'%s <%s>' % (tmpname, user)
                else:
                    frommail = 'SMTP:%s' % user.upper()
                    fromname = u'%s <%s>' % (user, user)
                if condition_rule == 'received-from':
                    exceptionslist.append(SCommentRestriction(
                        SPropertyRestriction(4, 0xc1d0102, SPropValue(0x00010102, '%s\x00' % frommail)),
                        [SPropValue(0x60000003, 1L), SPropValue(0x00010102, '%s\x00' % frommail),
                         SPropValue(0x0001001F, fromname), SPropValue(0x39000003, 0L)]))

                if condition_rule == 'sent-to':
                    exceptionslist.append(SSubRestriction(0xe12000d, SCommentRestriction(
                        SPropertyRestriction(4, 0x300b0102, SPropValue(0x00010102, '%s\x00' % frommail)),
                        [SPropValue(0x60000003, 1L), SPropValue(0x00010102, '%s\x00' % frommail),
                         SPropValue(0x0001001F, fromname), SPropValue(0x39000003, 0L)])))

            if len(exceptionslist) > 1:
                storeexceptions.append(SNotRestriction(SOrRestriction(conditionslist)))
            else:
                storeexceptions.append(SNotRestriction(exceptionslist[0]))

        if exception_rule == 'contain-word-sender-address' or exception_rule == 'contain-word-in-subject' or exception_rule == 'contain-word-in-body':
            for word in exception_var:
                if condition_rule == 'contain-word-sender-address':
                    exceptionslist.append(SContentRestriction(1, 0xc1d0102, SPropValue(0x0C1D0102, word.decode('utf8').encode('ISO-8859-1'))))
                if condition_rule == 'contain-word-in-subject':
                    exceptionslist.append(SContentRestriction(65537, 0x37001f, SPropValue(0x0037001F, word.decode('utf8'))))
                if condition_rule == 'contain-word-in-body':
                    exceptionslist.append(SContentRestriction(65537, 0x1000001f, SPropValue(0x1000001F, word.decode('utf8'))))
            if len(exceptionslist) > 1:
                storeexceptions.append(SNotRestriction(SOrRestriction(exceptionslist)))
            else:
                storeexceptions.append(SNotRestriction(exceptionslist[0]))

    #combine conditions and exceptions
    if len(storeexceptions) > 0:
        storeconditions = storeconditions + storeexceptions

    # combine all conditions
    if len(storeconditions) > 1:
        #returncon = SOrRestriction(storeconditions)
        returncon = SAndRestriction(storeconditions)
    else:
        returncon = storeconditions[0]


    rowlist = [ROWENTRY(
        ROW_ADD,
        [SPropValue(PR_RULE_STATE, ST_ENABLED),
         SPropValue(PR_RULE_ACTIONS, ACTIONS(1, storeactions)),
         SPropValue(PR_RULE_PROVIDER_DATA, binascii.unhexlify('010000000000000074da402772c2e440')),
         SPropValue(PR_RULE_CONDITION, returncon),
         SPropValue(PR_RULE_SEQUENCE, lastid + 1),
         SPropValue(1719730206, 'RuleOrganizer'),
         SPropValue(PR_RULE_NAME, options.createrule)
         ])]

    return rowlist


def main():
    options, args = opt_args()

    if not options.user:
        print('Usage:\n %s --user <username>  ' % (sys.argv[0]))
        sys.exit(1)
    server = kopano.Server(options)
    user = server.user(options.user)
    rule_table = user.store.inbox.mapiobj.OpenProperty(PR_RULES_TABLE, IID_IExchangeModifyTable, 0, 0)
    table = rule_table.GetTable(0)
    cols = table.QueryColumns(TBL_ALL_COLUMNS)
    table.SetColumns(cols, 0)
    filters = table.QueryRows(-1, 0)

    if options.printrules:
        print(user.name)
        printrules(filters, user, server)

    if options.state:
        rowlist, name = changerule(filters, options.rule, options.state)
        if options.state == 'enable' or options.state == 'disable' or options.state == 'delete':
            rule_table.ModifyTable(0, rowlist)
            print("Rule '%s' is %sd for user '%s'" % (name, options.state, user.name))

    if options.createrule:
        try:
            lastid = filters[-1][1].Value
        except:
            lastid = 0
        rowlist = createrule(options, lastid)
        rule_table.ModifyTable(0, rowlist)
        print("Rule '%s' created " % options.createrule)


if __name__ == "__main__":
    main()
