none
Need assistance getting Named Properties on email and IPM.Note folders RRS feed

  • Question

  • The idea I'm working on is to set a custom named property for every email message and have that property show up in a user defined column in Outlook 2010-2016. The property value will be set from text parsed in the email body. The user would be able to sort and search email with this property.


    To implement this concept I think I need create a property on email items and their respective folders. I've been unable to read any properties that are PS_PUBLIC_STRING {00020329-0000-0000-C000-000000000046} in my code and I need some help to get past this.

    The MFCMapi example from codeplex is getting these properties (I have set the custom properties on email using C#), but how MFCMapi manages its property class in comparison with what I'm trying to do is too diffucult for me to understand right now.

    I'm able to read properties such as the subject, display, entryId with HrGetOneProp(). I tried using the example usage to get named properties on https://msdn.microsoft.com/en-us/library/office/cc765864.aspx. I also tried GetPropList() and then GetProps(). GetPropList succeeds, GetProps fails with the same error as GetNamesFromIDs()

    hRes = pContainer->GetPropList(MAPI_UNICODE, &lppPropTagArray);
    hRes = pContainer->GetProps(lppPropTagArray, MAPI_UNICODE, lpcValues, lppPropArray);

    The functions failing return HRESULT with a failure of E_INVLIDARG, even though cValues has a positive value (such as 84).

    Any ideas, pointers, tips that would help me get past this would be appreciated!

    Saturday, October 17, 2015 4:53 AM

Answers

  • Joel,

    When I suggested that you post your code I hoped you would post the actual code that you used in which you showed how you defined and initialized data structures and pointers and then called GetNamesFromIDs using those variables.  Showing the example code from the MSDN documentation is not helpful.  Having said that, the code that you posted -

    LPSPropTagArray FAR *    lppPropTags = NULL;

    LPGUID                   lpPropSetGuid = &PS_PUBLIC_STRINGS;

    ULONG FAR *              lpcPropNames;

    LPMAPINAMEID FAR * FAR * lpppPropNames;

    lpMAPIProp->GetNamesFromIDs (lppPropTags,

                                 lpPropSetGuid,

                                 0,

                                 lpcPropNames,

                                 lpppPropNames);

    contains several errors.  The way lpppPropNames has been used, you are giving MAPI an undefined pointer in which to return the array of Names if the call had been successful.  You should have defined a pointer variable as follows

    LPMAPINAMEID *lppPropNames = NULL;

    Then, the last variable in the call to GetNamesFromIDS should have been &lppPropNames to pass a pointer to your variable.

    Also, the call requires a pointer to a ULONG variable in which to place the count of items returned.  The above code passes an uninitialized pointer, lpcPropNames.

    I appreciate your frustration and confusion.  However, when you read the MAPI documentation it will often point out that not all implementations by MAPI providers will act in the same manner, and in some cases the documentation is simply inaccurate.

    I also tried to obtain all named properties from an Outlook 2013 PST store by passing NULL as the pointer to the property tag array and NULL as the pointer to the property set.  My results were identical to yours and E_INVALIDARG was returned.

    It is possible to retrieve all named properties by passing a property tag array containing all property values from 0x8000 to 0xFFFE but although this call succeeded on my own system it also returned a rather large array that consisted mostly of NULL pointers since the highest named property value actually in use was 0x8174.  It is for this reason that MFCMAPI uses a binary search in order to find the highest named property value in use in order to limit the number of property tags in the call to GetNamesFromIDs to retrieve the data when it tries to determine the count of named properties in use.



    • Edited by RLWA32 Sunday, October 18, 2015 12:32 PM clarification
    • Marked as answer by Joel_Z Sunday, October 18, 2015 8:52 PM
    Sunday, October 18, 2015 11:42 AM

All replies

  • Hello Joel,

    Why do you need to use Extended MAPI instead of OOM? Did you try to use the UserProperties property for accessing properties?

    When either GetProps or SetProps fails because the property is too large or too complex, call OpenPropertyOpenProperty is typically used to access properties of type PT_OBJECT. The IMAPIProp::OpenProperty method provides access to a property through a particular interface. OpenProperty is an alternative to the IMAPIProp::GetPropsand IMAPIProp::SetProps methods. 

    Saturday, October 17, 2015 6:07 AM
  • The idea I'm working on is to set a custom named property for every email message and have that property show up in a user defined column in Outlook 2010-2016. The property value will be set from text parsed in the email body. The user would be able to sort and search email with this property.


    To implement this concept I think I need create a property on email items and their respective folders. I've been unable to read any properties that are PS_PUBLIC_STRING {00020329-0000-0000-C000-000000000046} in my code and I need some help to get past this.

    The MFCMapi example from codeplex is getting these properties (I have set the custom properties on email using C#), but how MFCMapi manages its property class in comparison with what I'm trying to do is too diffucult for me to understand right now.

    I'm able to read properties such as the subject, display, entryId with HrGetOneProp(). I tried using the example usage to get named properties on https://msdn.microsoft.com/en-us/library/office/cc765864.aspx. I also tried GetPropList() and then GetProps(). GetPropList succeeds, GetProps fails with the same error as GetNamesFromIDs()

    hRes = pContainer->GetPropList(MAPI_UNICODE, &lppPropTagArray);
    hRes = pContainer->GetProps(lppPropTagArray, MAPI_UNICODE, lpcValues, lppPropArray);

    The functions failing return HRESULT with a failure of E_INVLIDARG, even though cValues has a positive value (such as 84).

    Any ideas, pointers, tips that would help me get past this would be appreciated!

    Hi Joel,

    In addition to MFCMapi another excellent tool that will provide visibility into how Outlook and MAPI work together is OutlookSpy.  It can be obtained from http://www.dimastr.com/outspy/home.htm

    First, it will be much easier to work with user defined properties if you use the Outlook Object Model and I suggest that you start with that.

    Second, I suggest that you resolve how to read a user-defined property using Extended MAPI before worrying about how to create them. In this regard I think it would be beneficial for you to create a user defined property in a folder and on several items in the folder through the Outlook user interface.  You can use OutlookSpy to examine both the Outlook Object Model properties of the folder and items as well as their Extended MAPI properties.  This will assist your understanding of how Outlook uses MAPI to store user defined properties.

    If you want assistance on using the PS_PUBLIC_STRINGS namespace to retrieve a user defined property I suggest you post the code so that we may see the details.

    Similarly, if you post the code surrounding the unsuccessful calls to GetPropList and GetProps it would make it easier to provide you with helpful comments.

    Saturday, October 17, 2015 1:40 PM
  • Hello Joel,

    Why do you need to use Extended MAPI instead of OOM? Did you try to use the UserProperties property for accessing properties?

    When either GetProps or SetProps fails because the property is too large or too complex, call OpenPropertyOpenProperty is typically used to access properties of type PT_OBJECT. The IMAPIProp::OpenProperty method provides access to a property through a particular interface. OpenProperty is an alternative to the IMAPIProp::GetPropsand IMAPIProp::SetProps methods. 


    I need to use MAPI instead of OOM because I need to override the connection to turn off cached mode so that I can read/write email that is stored remotely. It is the function (but not limited to) IMsgStore::OpenEntry with MAPI_NO_CACHE that I want.

    What is the HRESULT when GetProps or SetProps fails because the property is too large or too complex?

    Do you mean HRESULT with a failure of E_INVLIDARG (even though cValues has a positive value of 84) indicates GetProps is failing because one of the properties is too large or too complex?

    The page here https://msdn.microsoft.com/en-us/library/office/cc765847.aspx reads "Users of named properties access them by name or identifier through the IMAPIProp::GetIDsFromNames and IMAPIProp::GetNamesFromIDs methods."  When I use GetNamesFromIDs and pass NULL for the first parameter to get all names like the call below, the function call fails with E_INVLIDARG. Can you help me with this?

    ULONG FAR *lpcPropNames                  = 0;
    LPMAPINAMEID FAR *FAR *lpppPropNames     = NULL;
    LPMAPICONTAINER pSubContainer            = NULL;

    lpMDB->OpenEntry(lpsTblRows->aRow->lpProps[htPR_ENTRYID].Value.bin.cb, (LPENTRYID)lpsTblRows->aRow->lpProps[htPR_ENTRYID].Value.bin.lpb, NULL, MAPI_BEST_ACCESS | MAPI_NO_CACHE | MAPI_MODIFY, &ulObjType, (LPUNKNOWN*)&pSubContainer);

    pSubContainer->GetNamesFromIDs (NULL, NULL, 0, lpcPropNames, lpppPropNames);


    • Edited by Joel_Z Saturday, October 17, 2015 4:51 PM
    Saturday, October 17, 2015 4:49 PM
  • The idea I'm working on is to set a custom named property for every email message and have that property show up in a user defined column in Outlook 2010-2016. The property value will be set from text parsed in the email body. The user would be able to sort and search email with this property.


    To implement this concept I think I need create a property on email items and their respective folders. I've been unable to read any properties that are PS_PUBLIC_STRING {00020329-0000-0000-C000-000000000046} in my code and I need some help to get past this.

    The MFCMapi example from codeplex is getting these properties (I have set the custom properties on email using C#), but how MFCMapi manages its property class in comparison with what I'm trying to do is too diffucult for me to understand right now.

    I'm able to read properties such as the subject, display, entryId with HrGetOneProp(). I tried using the example usage to get named properties on https://msdn.microsoft.com/en-us/library/office/cc765864.aspx. I also tried GetPropList() and then GetProps(). GetPropList succeeds, GetProps fails with the same error as GetNamesFromIDs()

    hRes = pContainer->GetPropList(MAPI_UNICODE, &lppPropTagArray);
    hRes = pContainer->GetProps(lppPropTagArray, MAPI_UNICODE, lpcValues, lppPropArray);

    The functions failing return HRESULT with a failure of E_INVLIDARG, even though cValues has a positive value (such as 84).

    Any ideas, pointers, tips that would help me get past this would be appreciated!

    Hi Joel,

    In addition to MFCMapi another excellent tool that will provide visibility into how Outlook and MAPI work together is OutlookSpy.  It can be obtained from http://www.dimastr.com/outspy/home.htm

    First, it will be much easier to work with user defined properties if you use the Outlook Object Model and I suggest that you start with that.

    Second, I suggest that you resolve how to read a user-defined property using Extended MAPI before worrying about how to create them. In this regard I think it would be beneficial for you to create a user defined property in a folder and on several items in the folder through the Outlook user interface.  You can use OutlookSpy to examine both the Outlook Object Model properties of the folder and items as well as their Extended MAPI properties.  This will assist your understanding of how Outlook uses MAPI to store user defined properties.

    If you want assistance on using the PS_PUBLIC_STRINGS namespace to retrieve a user defined property I suggest you post the code so that we may see the details.

    Similarly, if you post the code surrounding the unsuccessful calls to GetPropList and GetProps it would make it easier to provide you with helpful comments.


    OutlookSpy is nice, but that isn’t going to help me here. I need to use MAPI. I agree learning how to read the user defined properties is a first step. That is where I am at and it is the context of my first post. How I was attempting to read the properties was both linked and pasted. The error I need to resolve was pasted, it is E_INVLIDARG, even though cValues has a positive value (such as 84).

    Here is the code from the link: 
    LPSPropTagArray FAR *    lppPropTags = NULL;

    LPGUID                   lpPropSetGuid = &PS_PUBLIC_STRINGS;

    ULONG FAR *              lpcPropNames;

    LPMAPINAMEID FAR * FAR * lpppPropNames;

    lpMAPIProp->GetNamesFromIDs (lppPropTags,

                                 lpPropSetGuid,

                                 0,

                                 lpcPropNames,

                                 lpppPropNames);

    I would appreciate your assistance.

    Saturday, October 17, 2015 5:03 PM
  • MFCMAPI uses the IMAPIProp::GetNamesFromIDs method to look up named properties that have previously been mapped. Take a look at the CSingleMAPIPropListCtrl::FindAllNamedProps method from the SingleMAPIPropListCtrl.cpp file in the source code. 

    Also you may find the MAPI Named Properties section in MSDN helpful. 


    Saturday, October 17, 2015 7:14 PM
  • MFCMAPI uses the IMAPIProp::GetNamesFromIDs method to look up named properties that have previously been mapped. Take a look at the CSingleMAPIPropListCtrl::FindAllNamedProps method from the SingleMAPIPropListCtrl.cpp file in the source code. 

    Also you may find the MAPI Named Properties section in MSDN helpful. 



    I've tried that (GetNamesFromIDs) and the error is E_INVLIDARG, even though cValues has a positive value (84). This is the error I need help with. Any suggestions on how to resolve this problem would be appreciated.
    Saturday, October 17, 2015 7:30 PM
  • Joel,

    When I suggested that you post your code I hoped you would post the actual code that you used in which you showed how you defined and initialized data structures and pointers and then called GetNamesFromIDs using those variables.  Showing the example code from the MSDN documentation is not helpful.  Having said that, the code that you posted -

    LPSPropTagArray FAR *    lppPropTags = NULL;

    LPGUID                   lpPropSetGuid = &PS_PUBLIC_STRINGS;

    ULONG FAR *              lpcPropNames;

    LPMAPINAMEID FAR * FAR * lpppPropNames;

    lpMAPIProp->GetNamesFromIDs (lppPropTags,

                                 lpPropSetGuid,

                                 0,

                                 lpcPropNames,

                                 lpppPropNames);

    contains several errors.  The way lpppPropNames has been used, you are giving MAPI an undefined pointer in which to return the array of Names if the call had been successful.  You should have defined a pointer variable as follows

    LPMAPINAMEID *lppPropNames = NULL;

    Then, the last variable in the call to GetNamesFromIDS should have been &lppPropNames to pass a pointer to your variable.

    Also, the call requires a pointer to a ULONG variable in which to place the count of items returned.  The above code passes an uninitialized pointer, lpcPropNames.

    I appreciate your frustration and confusion.  However, when you read the MAPI documentation it will often point out that not all implementations by MAPI providers will act in the same manner, and in some cases the documentation is simply inaccurate.

    I also tried to obtain all named properties from an Outlook 2013 PST store by passing NULL as the pointer to the property tag array and NULL as the pointer to the property set.  My results were identical to yours and E_INVALIDARG was returned.

    It is possible to retrieve all named properties by passing a property tag array containing all property values from 0x8000 to 0xFFFE but although this call succeeded on my own system it also returned a rather large array that consisted mostly of NULL pointers since the highest named property value actually in use was 0x8174.  It is for this reason that MFCMAPI uses a binary search in order to find the highest named property value in use in order to limit the number of property tags in the call to GetNamesFromIDs to retrieve the data when it tries to determine the count of named properties in use.



    • Edited by RLWA32 Sunday, October 18, 2015 12:32 PM clarification
    • Marked as answer by Joel_Z Sunday, October 18, 2015 8:52 PM
    Sunday, October 18, 2015 11:42 AM
  • I also tried to obtain all named properties from an Outlook 2013 PST store by passing NULL as the pointer to the property tag array and NULL as the pointer to the property set.  My results were identical to yours and E_INVALIDARG was returned.

    It is possible to retrieve all named properties by passing a property tag array containing all property values from 0x8000 to 0xFFFE but although this call succeeded on my own system it also returned a rather large array that consisted mostly of NULL pointers since the highest named property value actually in use was 0x8174.



    Sorry about the code examples. If I knew you were going to build a VS project I would have pasted my project to save your time (its just a win32 console proof of concept at this point).

    I wanted to find out what properties exist first before trying to create what may already be there.  I will limit the scope to the 0x8000 to 0xFFFE (the results of your investigation). I think Microsoft is proud to have you in their forum(s) tackling issues like this. Thank you so much!

    Sunday, October 18, 2015 8:52 PM
  • Joel,

    I appreciate your kind words.

    You should be aware that there is more involved than just creating a named property in order for that custom property to be displayed in an Outlook folder's view.  Adding a MAPI named property to a message item through an IMessage interface pointer is not enough.

    You would also have to create a UserProperty object that corresponds to your MAPI named property in the Outlook MailItem's UserProperties collection.  Then you would also have to perform a similar task to create a UserDefinedProperty in the Outlook Folder object's UserDefinedProperties collection.  Only then would Outlook be able to display your custom property in a folder's view.

    I think that equivalent results could be achieved using Extended MAPI, but sticking with Extended MAPI exclusively would be much more difficult and significantly more complicated to accomplish successfully for various store providers(e.g., PST, IMAP, Exchange) than using the Outlook Object Model directly.

    Sunday, October 18, 2015 10:10 PM