EWS Application: Disable OWA 2010 Conversation View


Exchange 2010 OWA Folder View Settings are stored in a MAPI property and are customizable per folder.

Conversation View is enabled by default in OWA 2010 and even if you disable it on the existing folders, new folders you create will always have Conversation View enabled.

The property that stores the View Settings information is the following:

  • Property Tag: 0x361c
  • Property Type: Binary

I have written the following code for disabling the Conversation View on existing folders:

static ExtendedPropertyDefinition PidTagOWAConversationView = new ExtendedPropertyDefinition(0x361c, MapiPropertyType.Binary);
static PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties) { PidTagOWAConversationView };

private void processMainFolder(WellKnownFolderName folderName, ExchangeService service)
{
logBox.Text += "\r\n" + "Processing folder " + folderName.ToString();
if (folderName == WellKnownFolderName.Inbox)
{
try
{
Folder objFolder = Folder.Bind(service, folderName, psPropSet);
if (objFolder != null)
{
Object objConversationView = null;
objFolder.TryGetProperty(PidTagOWAConversationView, out objConversationView);

string strConversationView;
string strNewConversationView;
strConversationView = ByteArrayToString((byte[])objConversationView);
int index = strConversationView.LastIndexOf(@"007700630073006F007200740063006F006C0075006D006E");
strNewConversationView = strConversationView.Remove(index) + "007700630073006F007200740063006F006C0075006D006E0000001A000000440065006C0069007600650072007900540069006D00650000000300C6812903020000000000C0000000000000460168007400740070003A002F002F0073006300680065006D00610073002E006D006900630072006F0073006F00660074002E0063006F006D002F00650078006300680061006E00670065002F007700630073006F00720074006F007200640065007200000001000000";
object objNewConversationView = StringToByteArray(strNewConversationView);
objFolder.SetExtendedProperty(PidTagOWAConversationView, objNewConversationView);
objFolder.Update();
}
if (objFolder.ChildFolderCount > 0)
{

processSubFolders(objFolder, service);
}
logBox.Text += "\r\n" + "Folder " + folderName.ToString() + " successfully processed.";
}
catch (Exception ex)
{
logBox.Text += "\r\n" + "EXCEPTION encountered while processing folder " + folderName.ToString() + ":" + ex;
}
}
else
{
try
{
Folder objFolder = Folder.Bind(service, folderName, psPropSet);
if (objFolder != null)
{
string strNewConversationView = "B084C5812903020000000000C0000000000000460168007400740070003A002F002F0073006300680065006D00610073002E006D006900630072006F0073006F00660074002E0063006F006D002F00650078006300680061006E00670065002F007700630073006F007200740063006F006C0075006D006E0000001A000000440065006C0069007600650072007900540069006D00650000000300C6812903020000000000C0000000000000460168007400740070003A002F002F0073006300680065006D00610073002E006D006900630072006F0073006F00660074002E0063006F006D002F00650078006300680061006E00670065002F007700630073006F00720074006F007200640065007200000001000000";
object objNewConversationView = StringToByteArray(strNewConversationView);
objFolder.SetExtendedProperty(PidTagOWAConversationView, objNewConversationView);
objFolder.Update();
logBox.Text += "\r\n" + "Folder " + folderName.ToString() + " successfully processed.";
}
}
catch (Exception ex)
{
logBox.Text += "\r\n" + "EXCEPTION encountered while processing folder " + folderName.ToString() + ":" + ex;
}
}
}

private void processSubFolders(Folder parentFolder, ExchangeService service)
{
if (parentFolder != null)
{
logBox.Text += "\r\n" + "Processing subfolders in " + parentFolder.DisplayName.ToString();
try
{
FolderView folderView = new FolderView(50, 0);
folderView.OffsetBasePoint = OffsetBasePoint.Beginning;
folderView.PropertySet = psPropSet;
FindFoldersResults folderResults;
folderResults = service.FindFolders(parentFolder.Id, folderView);
foreach (Folder folder in folderResults.Folders)
{
try
{
logBox.Text += "\r\n" + "Processing subfolder " + folder.DisplayName.ToString();
Folder objFolder = Folder.Bind(service, folder.Id, psPropSet);
if (objFolder != null)
{
string strNewConversationView = "B084C5812903020000000000C0000000000000460168007400740070003A002F002F0073006300680065006D00610073002E006D006900630072006F0073006F00660074002E0063006F006D002F00650078006300680061006E00670065002F007700630073006F007200740063006F006C0075006D006E0000001A000000440065006C0069007600650072007900540069006D00650000000300C6812903020000000000C0000000000000460168007400740070003A002F002F0073006300680065006D00610073002E006D006900630072006F0073006F00660074002E0063006F006D002F00650078006300680061006E00670065002F007700630073006F00720074006F007200640065007200000001000000";
object objNewConversationView = StringToByteArray(strNewConversationView);
objFolder.SetExtendedProperty(PidTagOWAConversationView, objNewConversationView);
objFolder.Update();
}
if (objFolder.ChildFolderCount > 0)
{
processSubFolders(objFolder, service);
}
logBox.Text += "\r\n" + "Subolder " + folder.DisplayName.ToString() + " successfully processed.";
}
catch (Exception ex)
{
logBox.Text += "\r\n" + "EXCEPTION encountered while processing subfolder" + folder.DisplayName.ToString() + ":" + ex;
}
}
}
catch (Exception ex)
{
logBox.Text += "\r\n" + "EXCEPTION encountered while processing subfolders in " + parentFolder.DisplayName.ToString() + ":" + ex;
}
}
}

I am also attaching the Visual Studio solution.

The application uses Exchange impersonation so you will need to grant impersonation permissions for the account you will be using by running the following command:

New-ManagementRoleAssignment –Name:IMPERSONATION_ASSIGNMENT_NAME –Role:ApplicationImpersonation –User:SERVICE_ACCOUNT

Where IMPERSONATION_ASSIGNMENT_NAME is a name you need to choose for the role assignment and SERVICE_ACCOUNT is the alias of the account you will be using. For example: New-ManagementRoleAssignment –Name:AdministratorImpersonation –Role:ApplicationImpersonation –User:administrator.

Next, you will need to create a text file containing the e-mail addresses of the mailboxes you wish to disable conversation view for. For example:


administrator@zone.lab
userc1@zone.lab
userc2@zone.lab


You need to import the text file by clicking on the Import File button, fill in the EWS URL, Username, Password and Domain fields and click the Process Items button to start processing.

clip_image001

The EWS URL is the EWS URL of one of your CAS servers.

OWAConversationView.zip

Comments (9)

  1. AndreaT says:

    Hello,

    Thank you for sharing your code, it is very helpful.

    Can you kindly explain me why do we need to truncate strConversationView at 1012 for the inbox?

    What's the difference from this strConversationView and strConversationView of other folders?

    I'm getting an error when processing the inbox after a mailbox move from Ex2003 to Ex2010

    "The folder save operation failed due to invalid property values."

    Other folders are processed correctly.

    thanks in advance

    Andrea

  2. Andrei Ghita says:

    Hi Andrea,

    I have done a few changes to the initial code and it should work now. Please check the source code above.

    Andrei

  3. Paul Veerman says:

    I get the following error on certain mailboxes, not sure why it works for some and not for others…

    EXCEPTION encountered while processing folder Inbox:System.ArgumentOutOfRangeException: StartIndex cannot be less than zero.

    Parameter name: startIndex

      at System.String.Remove(Int32 startIndex)

      at OWAConversationView.Form1.processMainFolder(WellKnownFolderName folderName, ExchangeService service) in C:ProjectsOWAConversationViewOWAConversationViewForm1.cs:line 123

    Also, this only appears to work on custom folders created under the inbox, if they are created at the root of the mailbox the script ignores them.  It's not a big deal but I thought I would point it out.  Thanks.

  4. Andrei Ghita says:

    Hi Paul,

    I have uploaded the latest version of the solution. I actually fixed this a while back but didn't have the time to update the post.

    As for the folders in the mailbox root, my application only disables conversation view on the following folders:

    WellKnownFolderName.Inbox

    WellKnownFolderName.Drafts

    WellKnownFolderName.SentItems

    WellKnownFolderName.JunkEmail

    WellKnownFolderName.Outbox

    WellKnownFolderName.DeletedItems

    If you wish to update other folders you need to make the necessary changes in the source code.

    Andrei

  5. Mike Barnes says:

    Do you have a version that would disabled it for all folders under a user's mailbox?

  6. Tooco says:

    can I use this for Exchange 2013 ?

  7. Andrei Ghita says:

    I will publish a .Net sample for Exchange 2013 at some point this week.

  8. Bruce Gagliolo says:

    Any update on this for Exchange 2013 or Exchange online?