locked
Detect system and user defined folders in outlook RRS feed

  • Question

  • Hi

    I am trying to add a custom context menu item (using "FolderContextMenuDisplay" event) for user defined outlook folders. there is a function in Application.Session called "GetDefaultFolder" which get folder type and return its folder. by using this method I create following function:

     

    Public Shared Function IsSystemFolder(ByVal Folder As MAPIFolder) As Boolean
          For Each type As OlDefaultFolders In [Enum].GetValues(GetType(OlDefaultFolders))
             Try
                If (Folder.EntryID = Globals.ThisAddIn.Application.Session.GetDefaultFolder(type).EntryID) Then
                   Return True
                End If
             Catch
                'skip error folder and check next one
             End Try
          Next
    
          Return False
       End Function
    

     


    it can detect system folders for default active account only and not for other accounts in outlook. also there are some hidden folders in each account and this method can not detect them as well.

    I couldn't find any other way to distinguish between user and system folders in outlook and it supports multiple account profile. is there any other way to find such information?

     


    • Edited by Mahyar Sh Wednesday, December 21, 2011 6:25 AM
    Thursday, September 29, 2011 9:25 AM

Answers

  • The options are what's been presented to you: Store properties using PropertyAccessor, Inbox folder properties using PropertyAccessor, using the OlDefaultFolders enum to get folders from NameSpace and/or in Outlook 2010 from the Store objects.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Mahyar sh" <=?utf-8?B?TWFoeWFyIHNo?=> wrote in message news:7d921849-940d-4b24-a70a-1d308545bd44...

    Hi

    I manage to create something which is working! first because retrieving IDs is a time consuming process I create a class with some shared properties to cache such information, and using that information try to find system folders.

    my class is like this:

     

    Public Class SystemFolder
       Private Shared StoreValues() As String = {"http://schemas.microsoft.com/mapi/proptag/0x35E60102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E70102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x66300102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E20102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E40102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E00102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E30102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E50102"}
       Private Shared _Profiles_Count As Integer
       Private Shared _Cache_Ids As New ArrayList
    
          Private Shared Sub PrepareCache()
          If (Not IsNothing(_Cache_Ids) AndAlso _Profiles_Count = Globals.ExactAddIn.Application.Session.Accounts.Count) Then
             Exit Sub
          End If
    
          _Cache_Ids.Clear()
    
          For Each st As Store In Globals.ExactAddIn.Application.Session.Stores
             For Each param As String In StoreValues
                Try
                   Dim id As String = st.PropertyAccessor.BinaryToString(st.PropertyAccessor.GetProperty(param))
                   If (Not String.IsNullOrEmpty(id)) Then
                      _Cache_Ids.Add(id)
                   End If
                Catch ex As System.Exception
                   'skip error ID and check next one
                End Try
             Next
          Next
          _Profiles_Count = Globals.ExactAddIn.Application.Session.Accounts.Count
       End Sub
    
    
       Public Shared Function IsSystemFolder(ByVal Folder As MAPIFolder) As Boolean
    
          PrepareCache()
    
          Try If (Folder.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x10F4000B")) Then
                Return True
             End If
          Catch
             'skip if property does not exists
          End Try
    
             If (_Cache_Ids.Contains(Folder.EntryID)) Then Return True
    
          Return False
       End Function
    End Class
    

     


    but still some of folder like "Junk E-mail", "RSS Feeds", "Draft" and even Inbox itself still cannot be detected. yes you may say go and use second sets of properties, which related to inbox, but in first place you must be able to detect inbox folder for all profiles which is not possible! because Inbox ID in not stored in store properties.

    Any idea or solution? or maybe I am on a wrong path.

    Thank You
    Mahyar

     

     



    Ken Slovak MVP - Outlook
    • Marked as answer by Mahyar Sh Wednesday, October 5, 2011 12:57 AM
    Tuesday, October 4, 2011 1:32 PM

All replies

  • There are binary properties stored in the Inbox folder and the Store object that have the EntryID's of some of the default folders but not much that you can't get from the object model or GetDefaultFolder().
     
    Inbox has information about Calendar, Contacts, Drafts, Journal, Notes, Tasks. All of those are stored as binary arrays, so you'd need to convert them into strings for use with GetFolderFromID(). Inbox also has entries for the online and offline Reminders folder.
     
    Store has Common Views, Views, Deleted Items, Sent Items, Outbox, IPM_SUBTREE, Finder, Favorites.
     
    You can see those MAPI properties using a MAPI viewer such as OutlookSpy(www.dimastr.com/outspy) or MFCMAPI (a download from MS). The following are the MAPI properties and their corresponding DASL property tags for use with PropertyAccessor.
     
    Store:
    PR_FINDER_ENTRYID                    http://schemas.microsoft.com/mapi/proptag/0x35E70102
    PR_IPM_FAVORITES_ENTRYID        http://schemas.microsoft.com/mapi/proptag/0x66300102
    PR_IPM_OUTBOX_ENTRYID            http://schemas.microsoft.com/mapi/proptag/0x35E20102
    PR_IPM_SENTMAIL_ENTRYID        http://schemas.microsoft.com/mapi/proptag/0x35E40102
    PR_IPM_SUBTREE_ENTRYID        http://schemas.microsoft.com/mapi/proptag/0x35E00102
    PR_VIEWS_ENTRYID                        http://schemas.microsoft.com/mapi/proptag/0x35E50102
     
    Inbox:
    PR_IPM_APPOINTMENT_ENTRYID        http://schemas.microsoft.com/mapi/proptag/0x36D00102
    PR_IPM_CONTACT_ENTRYID                http://schemas.microsoft.com/mapi/proptag/0x36D10102
    PR_IPM_DRAFTS_ENTRYID                http://schemas.microsoft.com/mapi/proptag/0x36D70102
    PR_IPM_JOURNAL_ENTRYID            http://schemas.microsoft.com/mapi/proptag/0x36D20102
    PR_IPM_NOTE_ENTRYID                http://schemas.microsoft.com/mapi/proptag/0x36D30102
    PR_IPM_TASK_ENTRYID                http://schemas.microsoft.com/mapi/proptag/0x36D40102
    PR_REM_OFFLINE_ENTRYID        http://schemas.microsoft.com/mapi/proptag/0x36D60102
    PR_REM_ONLINE_ENTRYID            http://schemas.microsoft.com/mapi/proptag/0x36D50102
     
    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Mahyar sh" <=?utf-8?B?TWFoeWFyIHNo?=> wrote in message news:b6695d9f-991b-4f98-b5b2-fa28e1aef239...

    Hi

    I am trying to add a custom context menu item (using "FolderContextMenuDisplay" event) for user defined outlook folders. there is a function in Application.Session called "GetDefaultFolder" which get folder type and return its folder. by using this method I create following function:

    Public Shared Function IsSystemFolder(ByVal Folder As MAPIFolder) As Boolean
          For Each type As OlDefaultFolders In [Enum].GetValues(GetType(OlDefaultFolders))
             Try
                If (Folder.EntryID = Globals.ExactAddIn.Application.Session.GetDefaultFolder(type).EntryID) Then
                   Return True
                End If
             Catch
                'skip error folder and check next one
             End Try
          Next
    
          Return False
       End Function
    


    it can detect system folders for default active account only and not for other accounts in outlook. also there are some hidden folders in each account and this method can not detect them as well.

    I couldn't find any other way to distinguish between user and system folders in outlook and it supports multiple account profile. is there any other way to find such information?

     


    Ken Slovak MVP - Outlook
    Thursday, September 29, 2011 2:08 PM
  • In Outook 2010 you can use Store.GetDefaultFolder to detect special folders on the per-store basis.

    You can do the same (RDOStore.GetDefaultFolder) using Redemption in any version of Outlook.

     


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/
    OutlookSpy - Outlook, CDO
    and MAPI Developer Tool
    Thursday, September 29, 2011 2:36 PM
  • Hi Ken

    as you mentioned your self, those are some of folders and not all, however I can't make it work at all. I think maybe there is a work around for this problem. somehow if it is possible to find folder can be renamed or deleted (for example from permissions or properties) that is good enough for me, because system folders cannot and if user cannot rename a folder, also he\she can not access my extra operation for that folder.

    I did check some of folders properties using MFCMapi, but I couldn't find any useful thing, unfortunately.

     

    Thank you
    Mahyar

     

     

    Friday, September 30, 2011 4:16 AM
  • Hi Dmitry

    We are using VSTO for Office 2007 with .net 3.5 and Visual Studio 2008 and also not using Redemptio.

    Thank you
    Mahyar

    Friday, September 30, 2011 4:18 AM
  • Then you only option is to use the approach outlined by Ken: read the properties from the store and/or Inbox folder.

     


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/
    OutlookSpy - Outlook, CDO
    and MAPI Developer Tool
    Friday, September 30, 2011 4:24 AM
  • Any folder can be renamed on the MAPI level, Outlook won't care. The default folders have different names based on the user locale anyway.

    What exactly did not work for you?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/
    OutlookSpy - Outlook, CDO
    and MAPI Developer Tool
    Friday, September 30, 2011 4:26 AM
  • Could not convert binary data of EntryID to string and use them in Session.GetFolderFromID(). are they Base64 binary data?

    also not all of those folders exists in outlook, but no problem, it is possible to skip them.

    so main question is how to convert binary EntryID to string?

    Friday, September 30, 2011 4:30 AM
  • For the binary properties you get back a variant array of bytes.

    Each byte must be converted to a 2 digit hex representation. E.g. (0x56, 0xFA, ...) becomes "56FA...".


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/
    OutlookSpy - Outlook, CDO
    and MAPI Developer Tool
    Friday, September 30, 2011 5:04 AM
  • If default folder names have been changed, which can be done using MAPI, you can still find them using the default folders enum and GetDefaultFolder() or by using the entry id's in those store and folder properties I provided for you.
     
    Any other folders you'd need to find by location or name.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Mahyar sh" <=?utf-8?B?TWFoeWFyIHNo?=> wrote in message news:7e28b354-cde6-4302-90d3-aaf249ec882f...

    Hi Ken

    as you mentioned your self, those are some of folders and not all, however I can't make it work at all. I think maybe there is a work around for this problem. somehow if it is possible to find folder can be renamed or deleted (for example from permissions or properties) that is good enough for me, because system folders cannot and if user cannot rename a folder, also he\she can not access my extra operation for that folder.

    I did check some of folders properties using MFCMapi, but I couldn't find any useful thing, unfortunately.

     

    Thank you
    Mahyar

     

     


    Ken Slovak MVP - Outlook
    Friday, September 30, 2011 2:08 PM
  • If you are reading the folder properties using the PropertyAccessor() object in Outlook 2007 or 2010 you can convert the binary array to a string value using the PropertyAccessor.BinaryToString() method. That takes a binary array such as those properties return and converts the array into a hex string value. It was provided primarily to do this sort of conversion.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Mahyar sh" <=?utf-8?B?TWFoeWFyIHNo?=> wrote in message news:1609eef1-0046-4883-88f2-6d9051a75c99...

    Could not convert binary data of EntryID to string and use them in Session.GetFolderFromID(). are they Base64 binary data?

    also not all of those folders exists in outlook, but no problem, it is possible to skip them.

    so main question is how to convert binary EntryID to string?


    Ken Slovak MVP - Outlook
    Friday, September 30, 2011 2:08 PM
  • Hi

    I manage to create something which is working! first because retrieving IDs is a time consuming process I create a class with some shared properties to cache such information, and using that information try to find system folders.

    my class is like this:

     

    Public Class SystemFolder
       Private Shared StoreValues() As String = {"http://schemas.microsoft.com/mapi/proptag/0x35E60102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E70102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x66300102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E20102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E40102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E00102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E30102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E50102"}
       Private Shared _Profiles_Count As Integer
       Private Shared _Cache_Ids As New ArrayList
    
          Private Shared Sub PrepareCache()
          If (Not IsNothing(_Cache_Ids) AndAlso _Profiles_Count = Globals.ExactAddIn.Application.Session.Accounts.Count) Then
             Exit Sub
          End If
    
          _Cache_Ids.Clear()
    
          For Each st As Store In Globals.ExactAddIn.Application.Session.Stores
             For Each param As String In StoreValues
                Try
                   Dim id As String = st.PropertyAccessor.BinaryToString(st.PropertyAccessor.GetProperty(param))
                   If (Not String.IsNullOrEmpty(id)) Then
                      _Cache_Ids.Add(id)
                   End If
                Catch ex As System.Exception
                   'skip error ID and check next one
                End Try
             Next
          Next
          _Profiles_Count = Globals.ExactAddIn.Application.Session.Accounts.Count
       End Sub
    
    
       Public Shared Function IsSystemFolder(ByVal Folder As MAPIFolder) As Boolean
    
          PrepareCache()
    
          Try If (Folder.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x10F4000B")) Then
                Return True
             End If
          Catch
             'skip if property does not exists
          End Try
    
             If (_Cache_Ids.Contains(Folder.EntryID)) Then Return True
    
          Return False
       End Function
    End Class
    

     


    but still some of folder like "Junk E-mail", "RSS Feeds", "Draft" and even Inbox itself still cannot be detected. yes you may say go and use second sets of properties, which related to inbox, but in first place you must be able to detect inbox folder for all profiles which is not possible! because Inbox ID in not stored in store properties.

    Any idea or solution? or maybe I am on a wrong path.

    Thank You
    Mahyar

     

     


    • Edited by Mahyar Sh Tuesday, October 4, 2011 9:29 AM
    Tuesday, October 4, 2011 9:29 AM
  • The options are what's been presented to you: Store properties using PropertyAccessor, Inbox folder properties using PropertyAccessor, using the OlDefaultFolders enum to get folders from NameSpace and/or in Outlook 2010 from the Store objects.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Mahyar sh" <=?utf-8?B?TWFoeWFyIHNo?=> wrote in message news:7d921849-940d-4b24-a70a-1d308545bd44...

    Hi

    I manage to create something which is working! first because retrieving IDs is a time consuming process I create a class with some shared properties to cache such information, and using that information try to find system folders.

    my class is like this:

     

    Public Class SystemFolder
       Private Shared StoreValues() As String = {"http://schemas.microsoft.com/mapi/proptag/0x35E60102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E70102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x66300102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E20102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E40102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E00102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E30102", _
                                    "http://schemas.microsoft.com/mapi/proptag/0x35E50102"}
       Private Shared _Profiles_Count As Integer
       Private Shared _Cache_Ids As New ArrayList
    
          Private Shared Sub PrepareCache()
          If (Not IsNothing(_Cache_Ids) AndAlso _Profiles_Count = Globals.ExactAddIn.Application.Session.Accounts.Count) Then
             Exit Sub
          End If
    
          _Cache_Ids.Clear()
    
          For Each st As Store In Globals.ExactAddIn.Application.Session.Stores
             For Each param As String In StoreValues
                Try
                   Dim id As String = st.PropertyAccessor.BinaryToString(st.PropertyAccessor.GetProperty(param))
                   If (Not String.IsNullOrEmpty(id)) Then
                      _Cache_Ids.Add(id)
                   End If
                Catch ex As System.Exception
                   'skip error ID and check next one
                End Try
             Next
          Next
          _Profiles_Count = Globals.ExactAddIn.Application.Session.Accounts.Count
       End Sub
    
    
       Public Shared Function IsSystemFolder(ByVal Folder As MAPIFolder) As Boolean
    
          PrepareCache()
    
          Try If (Folder.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x10F4000B")) Then
                Return True
             End If
          Catch
             'skip if property does not exists
          End Try
    
             If (_Cache_Ids.Contains(Folder.EntryID)) Then Return True
    
          Return False
       End Function
    End Class
    

     


    but still some of folder like "Junk E-mail", "RSS Feeds", "Draft" and even Inbox itself still cannot be detected. yes you may say go and use second sets of properties, which related to inbox, but in first place you must be able to detect inbox folder for all profiles which is not possible! because Inbox ID in not stored in store properties.

    Any idea or solution? or maybe I am on a wrong path.

    Thank You
    Mahyar

     

     



    Ken Slovak MVP - Outlook
    • Marked as answer by Mahyar Sh Wednesday, October 5, 2011 12:57 AM
    Tuesday, October 4, 2011 1:32 PM
  • Ken,

    I think the issue is that there's no way to get the Inbox from the Store.

    For example, suppose in Outlook 2007 addin (in Outlook 2010 and up this is N/A and provided by the object model without needing the property accessors) you need the Contacts of a delegate mailbox.  You get the Store that represents that delegate mailbox, but there's no fool-proof way to get the Inbox for that delegated mailbox and according to you, you need the Inbox to get the Contacts.

    Thursday, May 29, 2014 8:09 PM
  • If you cannot use Store.GetDefaultFolder, your only other options are either Extended MAPI (C++ or Delphi, call IMsgStore::GetReceiveFolder("IPM", ...)) or Redemption (any language) - it exposes RDOStore.GetDefaultFolder in all versions of Outlook.

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Thursday, May 29, 2014 8:15 PM