python add category to contact



  • Hi,
    I would like to synchronise contacts from a database to kopano.
    It works quite well so far, but I have problems to add categories.

    This piece of code works well with all the other extra properties (like PR_CITY, PR_EMAIL, …):

    if key in extra:
        if value:
            new_item.mapiobj.SetProps([SPropValue(extra[key], value)])
    

    The values are strings and when I set the category property it creates a list of single characters of that string.
    you can see that in my log file:

    2018-10-29 11:21:02,367 [MainThread  ] [INFO    ] - Field changed: PR_CATEGORIES, now: KUNDE/Kunde, before: ['K', 'U', 'N', 'D', 'E', '/', 'K', 'u', 'n', 'd', 'e']
    

    which is obviously not what I want to do.
    These wrong categories are also not shown in the Webapp. I also tried it with just one letter

    2018-10-29 11:08:08,694 [MainThread  ] [INFO    ] - Field changed: PR_CATEGORIES, now: A, before: ['A']
    

    Didn’t work either and is also not shown in Webapp.

    So, how to add categories?



  • I got a little bit further down the road:

    One needs to add a list object instead of a string.
    Something like this: [‘01/Baustellengemeinkosten’, ‘02/Abbrucharbeiten’, ‘STATIK/Statiker’]

    However, the Webapp still doesn’t show the categories I add.
    When I check the property of the contact I can see that they are added correctly, but the Webapp doesn’t show anything. What could be reason for this?



  • I wrote this little script to show me all categories of my contacts:

    import kopano
    from MAPI.Util import *
    from datetime import datetime
    from MAPI.Struct import MAPINAMEID
    from MAPI.Tags import (
                PS_PUBLIC_STRINGS
                )
    from MAPI import MNID_STRING, MAPI_CREATE
    
    NAMED_PROP_CATEGORY = MAPINAMEID(PS_PUBLIC_STRINGS, MNID_STRING, u'Keywords')
    
    server = kopano.Server()
    
    store = server.public_store
    contacts = store.folder("TEST-Kontakte")
    
    extra = {"PR_DISPLAY_NAME_FULL": 0x8130001f,
             "PR_EMAIL": 0x8133001f,
             "PR_CATEGORIES": 0x850d101f,
             # "PR_CATEGORIES": 0x85020000,
             "PR_PRIVATE": 0x81a6000b,
             "PR_COUNTRY": 0x80f9001f,
             }
    
    
    def getprop(item, myprop):
        try:
            if item.prop(myprop).typename == 'PT_UNICODE':
                return item.prop(myprop).value.encode('utf-8')
            elif item.prop(myprop).typename == 'PT_SYSTIME':
                epoch = datetime.utcfromtimestamp(0)
                return (item.prop(myprop).value - epoch).total_seconds()
            elif item.prop(myprop).typename == 'PT_I4':
                return int(item.prop(myprop).value)
            else:
    
                return item.prop(myprop).value
        except (MAPIErrorNotFound, kopano.errors.NotFoundError):
            return None
    
    
    def print_contact(contact, country, cats):
        print(contact.name,
              country,
              cats,
              )
        print(contact.categories)
        proptag = contact.mapiobj.GetIDsFromNames([NAMED_PROP_CATEGORY], MAPI_CREATE)[0]
        print(hex(proptag))
    
    
    for i, contact in enumerate(contacts):
        try:
            country = getprop(contact, extra['PR_COUNTRY']).decode()
        except AttributeError:
            country = None
    
        try:
            cats = getprop(contact, extra['PR_CATEGORIES'])
        except AttributeError:
            cats = None
    
        print_contact(contact, country, cats)
    

    And I found out that in extra[‘PR_CATEGORIES’] is something else than in contact.categories

    So it seems as if 0x850d101f is the wrong code and the above script shows, that it should be 0x85020000 instead.
    However, when I use that, my getprop function doesn’t work anymore. It doesn’t expect to get a list:

    Struct.py, line 266:
    <class ‘tuple’>: (<class ‘TypeError’>, TypeError(“unhashable type: ‘list’”,), None)

    But even if it would work, I can’t write the property to 0x85020000:

    Traceback (most recent call last):
      File "sync_main.py", line 226, in <module>
        main(logger)
      File "sync_main.py", line 213, in main
        kopano.insert(to_add)
      File "/tmp/pycharm_project_135/kopano_sync.py", line 197, in insert
        new_item.mapiobj.SetProps([SPropValue(0x85020000, categories)])
      File "/usr/lib/python3/dist-packages/MAPICore.py", line 407, in SetProps
        return _MAPICore.IMAPIProp_SetProps(self, cValues)
    TypeError: ulPropTag has unknown type 0
    

    Any ideas?



  • I found it by myself.
    I just used the same code as in item.py:

    proptag = new_item.mapiobj.GetIDsFromNames([NAMED_PROP_CATEGORY], MAPI_CREATE)[0]
                            proptag = CHANGE_PROP_TYPE(proptag, PT_MV_UNICODE)
                            new_item.mapiobj.SetProps([SPropValue(proptag, categories)])
    

    where categories is a list.



  • The Problem is solved now - however, I would like to know if the code 0x850d101f has anything to do with categories and if yes, what:
    “PR_CATEGORIES”: 0x850d101f

    I found it in this script:
    https://stash.kopano.io/projects/KSC/repos/core-tools/browse/contacts2csv



  • @rgsell said in python add category to contact:

    Struct.py, line 266:
    <class ‘tuple’>: (<class ‘TypeError’>, TypeError(“unhashable type: ‘list’”,), None)

    The hash() is a built-in python method, used to return a unique number . This can be applied to any user-defined object which won’t get changed once initialized. This property is used mainly in dictionary keys .

    TypeError: unhashable type: ‘list’ usually means that you are trying to use a list as an hash argument. This means that when you try to hash an unhashable object it will result an error. For ex. when you use a list as a key in the dictionary , this cannot be done because lists can’t be hashed. The standard way to solve this issue is to cast a list to a tuple .


Log in to reply