Howto: Mail Enable, Mail Disable and view Mail settings for a Public Folder with CDOEX and CDOEXM

If your living in a pre Exchange 2007 Powershell worlds and want to mail enable or disable public folders, you may come to the point where you will be needing to write some CDOEX and CDOEXM code to do what you want.  Below is a C# sample console application which will allow you to mail enable, mail disable and view mail settings on a public folder.

//======================================================================================================

// ExchangePfUtil -

// Exchange Public Folder Sample.

//

// This sample demonstrates the following:

// Check Mail setttings on a public folder

// Mail Enable a public folder

// Mail Disable setttings on a public folder

// List sub-folders

// List items in a folder

// Delete an item or a folder

// Note: This code is provided as a sample only, so you need to test and take responsibility

// of the code and any of its possible actions before usage. Being a sample, its provided

// for educational purposes only and is not supported in any way.

// Note: Because CDOEX is used, you must run this on the Exchange server being accessed.

// Note: You should not need to supply a password.

// Note: Because this code uses CDOEXM, it will not run on an Exchange 2007 server. For Exchange 2007,

// you should use PowerShell instead.

// To compile:

// Set references to CDOEXM and CDOEX:

// CDOEX can be reference as this COM component: "Microsoft CDO for Exchange 2000 Library"

// Note: Setting a reference to CDOEX will generate the "CDO" and "ADODB" interops.

// If there is a preexisting ADODB interop, its usually best to remove it and let the

// referencing of CDOEX generate the ADODB interop.

// CDOEXM can be referenced as this COM component "CDO for Exchange Management"

// Note: Setting a reference to will generate the CDOEXM iterop.

//

// Last changed 8/17/2009

//

//======================================================================================================

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using CDOEXM;

using CDO;

namespace ExchangePfUtil

{

class Program

{

static void Main(string[] args)

{

string sURL = string.Empty;

string sUserId = string.Empty;

string sPassword = string.Empty;

string sContentClass = string.Empty;

string sOutlookFolderClass = string.Empty;

bool bRet = false;

string sErrorMessage = "";

string sCommand = string.Empty;

bool bOkToProcess = false;

if (args.Length >= 2)

{

sCommand = args[0];

sURL = args[1];

}

if (sURL.StartsWith("file://./backofficestorage/"))

bOkToProcess = true;

else

bOkToProcess = false;

// Check Params

if (bOkToProcess == true)

{

switch (sCommand)

{

case "MailEnabledCheck":

if (args.Length == 2 || args.Length == 4)

{

if (args.Length == 4)

{

sUserId = args[2];

sPassword = args[3];

}

bOkToProcess = true;

bRet = MailEnabledCheck(sURL, sUserId, sPassword, out sErrorMessage);

}

else

{

bOkToProcess = false;

Console.WriteLine("Incorrect number of parameters.");

}

break;

case "MailDisable":

if (args.Length == 2 || args.Length == 4)

{

if (args.Length == 4)

{

sUserId = args[2];

sPassword = args[3];

}

bOkToProcess = true;

bRet = MailDisablePublicFolder(sURL, sUserId, sPassword, out sErrorMessage);

}

else

{

Console.WriteLine("Incorrect number of parameters.");

bOkToProcess = false;

}

break;

case "MailEnable":

if (args.Length == 2 || args.Length == 4)

{

if (args.Length == 4)

{

sUserId = args[2];

sPassword = args[3];

}

bOkToProcess = true;

bRet = MailEnabledPublicFolder(sURL, sUserId, sPassword, out sErrorMessage);

}

else

{

Console.WriteLine("Incorrect number of parameters.");

bOkToProcess = false;

}

break;

case "ListFolders":

if (args.Length == 2 || args.Length == 4)

{

if (args.Length == 4)

{

sUserId = args[2];

sPassword = args[3];

}

bOkToProcess = true;

bRet = ListFolders(sURL, sUserId, sPassword, out sErrorMessage);

}

else

{

Console.WriteLine("Incorrect number of parameters.");

bOkToProcess = false;

}

break;

case "CreateFolder":

if (args.Length == 2 || args.Length == 4 || args.Length == 6)

{

if (args.Length == 2)

{

// Default

sContentClass = "urn:content-classes:folder";

sOutlookFolderClass = "IPF.Note";

}

else

{

sContentClass = args[2];

sOutlookFolderClass = args[3];

}

if (args.Length == 6)

{

sUserId = args[4];

sPassword = args[5];

}

else

bOkToProcess = true;

bRet = CreateFolder(sURL, sUserId, sPassword, sContentClass, sOutlookFolderClass, out sErrorMessage);

}

else

{

Console.WriteLine("Incorrect number of parameters.");

bOkToProcess = false;

string sText = string.Empty;

sText = "Commonly used:\r\n";

sText += " Type OutlookFolderClass ContentClass\r\n";

sText += " +--------------------+--------------------+-----------------------------------r\n";

sText += " Generic Folder IPF.Note urn:content-classes:folder \r\n";

sText += " Mail Folder IPF.Note urn:content-classes:mailfolder \r\n";

sText += " Contact Folder IPF.Contact urn:content-classes:contactfolder\r\n";

sText += " Appointment Folder IPF.Appointment urn:content-classes:calendarfolder\r\n";

sText += " Note Folder IPF.Note urn:content-classes:notesfolder\r\n";

sText += " Task Folder IPF.Task urn:content-classes:taskfolder\r\n";

sText += " Journal Folder IPF.Journal urn:content-classes:journalfolder\r\n";

Console.WriteLine(sText);

}

break;

case "ListItems":

if (args.Length == 2 || args.Length == 4)

{

if (args.Length == 4)

{

sUserId = args[2];

sPassword = args[3];

}

bOkToProcess = true;

bRet = ListItems(sURL, sUserId, sPassword, out sErrorMessage);

}

else

{

Console.WriteLine("Incorrect number of parameters.");

bOkToProcess = false;

}

break;

case "Delete":

if (args.Length == 2 || args.Length == 4)

{

if (args.Length == 4)

{

sUserId = args[2];

sPassword = args[3];

}

bOkToProcess = true;

bRet = DeleteFolderOrItem(sURL, sUserId, sPassword, out sErrorMessage);

}

else

{

Console.WriteLine("Incorrect number of parameters.");

bOkToProcess = false;

}

break;

default:

Console.WriteLine("Command Unknown: " + sCommand);

break;

}

}

if (bOkToProcess == false)

{

// Error

Console.WriteLine("Usage: ");

Console.WriteLine(" ExchangePfUtil <Command> <FolderPath>");

Console.WriteLine(" ExchangePfUtil <Command> <FolderPath> <Admin Account> <Password>");

Console.WriteLine(" ExchangePfUtil <CreateFolder> <MessageClass>");

Console.WriteLine(" ExchangePfUtil <CreateFolder> <MessageClass> <Admin Account> <Password>");

Console.WriteLine("FolderPath needs to start with file://./backofficestorage/ ");

Console.WriteLine("Commands:");

Console.WriteLine(" MailEnabledCheck - This will show Mail settings on the folder.");

Console.WriteLine(" MailDisable - This will show MailDisable the folder.");

Console.WriteLine(" MailEnable - This will show Mail Enable the folder");

Console.WriteLine(" ListFolders - This will list subfolders");

Console.WriteLine(" CreateFolder - This will create a folder");

Console.WriteLine(" ListItems - This will list items in a folder");

Console.WriteLine(" Delete - This will delete an item or folder");

Console.WriteLine("Examples: ");

Console.WriteLine(" ExchangePfUtil MailEnabledCheck \"file://./backofficestorage/myMailDom/public folders/myfolder\" ");

Console.WriteLine(" ExchangePfUtil MailDisable \"file://./backofficestorage/myMailDom/public folders/myfolder\" Administrator AA12bc");

Console.WriteLine(" ExchangePfUtil ListFolders \"file://./backofficestorage/myMailDom/public folders/myotherfolder\" ");

Console.WriteLine(" ExchangePfUtil CreateFolder \"file://./backofficestorage/myMailDom/public folders/myotherfolder\" \"IPM.NOTE\" \"urn:content-classes:folder\"");

bOkToProcess = false;

}

}

static private bool MailDisablePublicFolder(string sURL, string sUserId, string sPassword, out string sErrorMessage)

{

bool bRet = false;

string sError = "";

CDO.Folder oPublicFolder = new CDO.Folder();

CDOEXM.IMailRecipient oRecip;

try

{

if (sUserId.Length != 0)

{

oPublicFolder.DataSource.Open(

sURL,

null,

ADODB.ConnectModeEnum.adModeReadWrite,

ADODB.RecordCreateOptionsEnum.adFailIfNotExists,

ADODB.RecordOpenOptionsEnum.adOpenExecuteCommand,

sUserId,

sPassword);

}

else

{

oPublicFolder.DataSource.Open(

sURL,

null,

ADODB.ConnectModeEnum.adModeReadWrite,

ADODB.RecordCreateOptionsEnum.adFailIfNotExists,

ADODB.RecordOpenOptionsEnum.adOpenExecuteCommand,

string.Empty,

string.Empty);

}

oRecip = (CDOEXM.IMailRecipient)oPublicFolder;

oRecip.MailDisable();

oPublicFolder.DataSource.Save();

Console.WriteLine("Mail Disabled Folder: " + sURL);

Console.WriteLine("Note: It may take anywhere from a few seconds to minutes to take effect.");

bRet = true;

System.Runtime.InteropServices.Marshal.ReleaseComObject(oPublicFolder);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oRecip);

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Failed to Mail Disable folder.");

Console.WriteLine(sError);

}

sErrorMessage = sError;

return bRet;

}

public static bool MailEnabledPublicFolder(string sURL, string sUserId, string sPassword, out string sErrorMessage)

{

CDO.Folder oPublicFolder = new CDO.Folder();

CDOEXM.IMailRecipient oRecip;

ADODB.Connection oConn = new ADODB.Connection();

string sError = "";

bool bRet = false;

try

{

oConn.Provider = "exoledb.datasource";

if (sUserId.Length != 0)

{

oConn.Open(sURL, sUserId, sPassword, 0);

}

else

{

oConn.Open(sURL, string.Empty, string.Empty, 0);

}

oPublicFolder.DataSource.Open(sURL, oConn,

ADODB.ConnectModeEnum.adModeReadWrite,

ADODB.RecordCreateOptionsEnum.adFailIfNotExists,

ADODB.RecordOpenOptionsEnum.adOpenSource,

sUserId, sPassword);

oRecip = (CDOEXM.IMailRecipient)oPublicFolder;

oRecip.MailEnable(string.Empty);

oPublicFolder.DataSource.Save();

Console.WriteLine("Mail Enabled Folder: " + sURL);

Console.WriteLine("Note: It may take anywhere from a few seconds to minutes to take effect.");

bRet = true;

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Failed to Mail Enable folder.");

Console.WriteLine(sError);

}

oRecip = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject(oPublicFolder);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oConn);

sErrorMessage = sError;

return bRet;

}

private static bool MailEnabledCheck(string sURL, string sUserId, string sPassword, out string sErrorMessage)

{

CDO.Folder oPublicFolder = new CDO.Folder();

CDOEXM.IMailRecipient oRecip ;

ADODB.Connection oConn = new ADODB.Connection();

string sError = "";

bool bRet = false;

try

{

oConn.Provider = "exoledb.datasource";

if (sUserId.Length != 0)

{

oConn.Open(sURL, sUserId, sPassword, 0);

}

else

{

oConn.Open(sURL, string.Empty, string.Empty, 0);

}

oPublicFolder.DataSource.Open(sURL, oConn,

ADODB.ConnectModeEnum.adModeReadWrite,

ADODB.RecordCreateOptionsEnum.adFailIfNotExists,

ADODB.RecordOpenOptionsEnum.adOpenSource,

sUserId, sPassword);

// Set MailEnabled property

oRecip = (CDOEXM.IMailRecipient)oPublicFolder;

Console.WriteLine ("Mail Settings:");

Console.WriteLine(" PF: " + oPublicFolder.DisplayName);

Console.WriteLine(" EmailAddress: " + oPublicFolder.EmailAddress);

Console.WriteLine(" SMTPEmail: " + oRecip.SMTPEmail);

Console.WriteLine(" TargetAddress: " + oRecip.TargetAddress);

Console.WriteLine(" X400Email: " + oRecip.X400Email);

bRet = true;

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Could not check folder.");

Console.WriteLine(sError);

}

// Explicitly release objects

oRecip = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject(oPublicFolder);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oConn);

sErrorMessage = sError;

return bRet;

}

private static bool ListFolders(string sURL, string sUserId, string sPassword, out string sErrorMessage)

{

CDO.Folder oPublicFolder = new CDO.Folder();

ADODB.Connection oConn = new ADODB.Connection();

string sError = "";

bool bRet = false;

try

{

oConn.Provider = "exoledb.datasource";

if (sUserId.Length != 0)

{

oConn.Open(sURL, sUserId, sPassword, 0);

}

else

{

oConn.Open(sURL, string.Empty, string.Empty, 0);

}

if (oConn.State == 1 )

{

string sLine = string.Empty;

string sSQL = "";

sSQL = "SELECT " +

"\"DAV:href\", " +

"\"DAV:contentclass\", " +

"\"DAV:displayname\", " +

"\"DAV:hassubs\" " +

"FROM SCOPE ('SHALLOW TRAVERSAL OF \"" + sURL +

"\"') WHERE \"DAV:isfolder\" = true";

ADODB.Recordset oRecs = new ADODB.Recordset();

try

{

oRecs.CursorLocation = ADODB.CursorLocationEnum.adUseServer;

oRecs.Open (sSQL, oConn.ConnectionString,ADODB.CursorTypeEnum.adOpenUnspecified,

ADODB.LockTypeEnum.adLockOptimistic, -1);

oRecs.MoveFirst();

if (oRecs.RecordCount > 0)

{

while(oRecs.EOF != true)

{

sLine = "";

//sLine = "[subfolders:" + oRecs.Fields["DAV:hassubs"].Value.ToString() + "] ";

//sLine = "[contentclass: " + oRecs.Fields["DAV:href"].Value.ToString() + "] ";

//sLine = "\"" + oRecs.Fields["DAV:displayname"].Value.ToString() + "\" ";

sLine += "" + oRecs.Fields["DAV:href"].Value.ToString() + "";

Console.WriteLine(sLine);

oRecs.MoveNext();

}

}

else

{

}

bRet = true;

}

catch (Exception ex2)

{

sError = "Could not list folders.\r\n" + ex2.Message;

Console.WriteLine(sError);

bRet = false;

}

oRecs.Close();

System.Runtime.InteropServices.Marshal.ReleaseComObject(oRecs);

}

else

{

sError = "Could not list folders.";

Console.WriteLine(sError);

bRet = false;

}

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Could not list folders:");

Console.WriteLine(sError);

}

// Explicitly release objects

System.Runtime.InteropServices.Marshal.ReleaseComObject(oPublicFolder);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oConn);

sErrorMessage = sError;

return bRet;

}

private static bool ListItems(string sURL, string sUserId, string sPassword, out string sErrorMessage)

{

CDO.Folder oPublicFolder = new CDO.Folder();

ADODB.Connection oConn = new ADODB.Connection();

string sError = "";

bool bRet = false;

try

{

oConn.Provider = "exoledb.datasource";

if (sUserId.Length != 0)

{

oConn.Open(sURL, sUserId, sPassword, 0);

}

else

{

oConn.Open(sURL, string.Empty, string.Empty, 0);

}

if (oConn.State == 1)

{

string sSQL = "";

sSQL = "SELECT " +

"\"DAV:href\", " +

"\"DAV:displayname\", " +

"\"DAV:ContentClass\" " +

"FROM SCOPE ('SHALLOW TRAVERSAL OF \"" + sURL +

"\"') WHERE \"DAV:isfolder\" = false";

ADODB.Recordset oRecs = new ADODB.Recordset();

try

{

string sLine = string.Empty;

oRecs.CursorLocation = ADODB.CursorLocationEnum.adUseServer;

oRecs.Open(sSQL, oConn.ConnectionString, ADODB.CursorTypeEnum.adOpenUnspecified,

ADODB.LockTypeEnum.adLockOptimistic, -1);

oRecs.MoveFirst();

if (oRecs.RecordCount > 0)

{

while (oRecs.EOF != true)

{

sLine = "";

//sLine = "[contentclass: " + oRecs.Fields["DAV:href"].Value.ToString() + "] ";

//sLine = "\"" + oRecs.Fields["DAV:displayname"].Value.ToString() + "\" ";

sLine += "" + oRecs.Fields["DAV:href"].Value.ToString() + "";

Console.WriteLine(sLine);

oRecs.MoveNext();

}

}

bRet = true;

oRecs.Close();

}

catch (Exception ex2)

{

sError = "Could not list items - check path.\r\n" + ex2.Message;

Console.WriteLine(sError);

bRet = false;

}

System.Runtime.InteropServices.Marshal.ReleaseComObject(oRecs);

}

else

{

sError = "Could not list items.";

Console.WriteLine(sError);

bRet = false;

}

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Could not list items:");

Console.WriteLine(sError);

}

// Explicitly release objects

System.Runtime.InteropServices.Marshal.ReleaseComObject(oPublicFolder);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oConn);

sErrorMessage = sError;

return bRet;

}

private static bool CreateFolder(string sURL, string sUserId, string sPassword,

string sContentClass,

string sOutlookFolderClass,

out string sErrorMessage)

{

CDO.Folder oPublicFolder = new CDO.Folder();

ADODB.Connection oConn = new ADODB.Connection();

string sError = "";

bool bRet = false;

try

{

oConn.Provider = "exoledb.datasource";

if (sUserId.Length != 0)

{

oConn.Open(sURL, sUserId, sPassword, 0);

}

else

{

oConn.Open(sURL, string.Empty, string.Empty, 0);

}

if (oConn.State == 1 )

{

oPublicFolder.ContentClass = sContentClass;

oPublicFolder.Fields["https://schemas.microsoft.com/exchange/outlookfolderclass"].Value = sOutlookFolderClass;

//oPublicFolder.Description = sDescription;

oPublicFolder.DataSource.SaveTo(sURL, oConn, ADODB.ConnectModeEnum.adModeReadWrite,

ADODB.RecordCreateOptionsEnum.adCreateCollection | ADODB.RecordCreateOptionsEnum.adCreateOverwrite,

ADODB.RecordOpenOptionsEnum.adOpenSource,

sUserId, sPassword);

bRet = true;

}

else

{

sError = "Could not create folder.";

Console.WriteLine(sError);

bRet = false;

}

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Could not create folder.");

Console.WriteLine(sError);

}

// Explicitly release objects

System.Runtime.InteropServices.Marshal.ReleaseComObject(oPublicFolder);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oConn);

sErrorMessage = sError;

return bRet;

}

private static bool DeleteFolderOrItem(string sURL, string sUserId, string sPassword,out string sErrorMessage)

{

ADODB.Record oRec = new ADODB.Record();

ADODB.Connection oConn = new ADODB.Connection();

string sError = "";

bool bRet = false;

try

{

oConn.Provider = "exoledb.datasource";

if (sUserId.Length != 0)

{

oConn.Open(sURL, sUserId, sPassword, 0);

}

else

{

oConn.Open(sURL, string.Empty, string.Empty, 0);

}

if (oConn.State == 1)

{

try

{

oRec.Open(sURL, oConn, ADODB.ConnectModeEnum.adModeReadWrite,

ADODB.RecordCreateOptionsEnum.adFailIfNotExists,

ADODB.RecordOpenOptionsEnum.adOpenSource,

sUserId, sPassword);

try

{

//if (oRec.State == ADODB.ObjectStateEnum.adStateOpen)

oRec.DeleteRecord(sURL, false);

bRet = true;

}

catch (Exception ex3)

{

bRet = false;

sError = ex3.Message;

Console.WriteLine("Could not Delete - Call to delete the item failed.");

Console.WriteLine(sError);

}

}

catch (Exception ex2)

{

bRet = false;

sError = ex2.Message;

Console.WriteLine("Could not open item for deletion - check path.");

Console.WriteLine(sError);

}

}

else

{

sError = "Could not Delete.";

Console.WriteLine(sError);

bRet = false;

}

}

catch (Exception ex)

{

bRet = false;

sError = ex.Message;

Console.WriteLine("Could not Delete.");

Console.WriteLine(sError);

}

// Explicitly release objects

System.Runtime.InteropServices.Marshal.ReleaseComObject(oRec);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oConn);

sErrorMessage = sError;

return bRet;

}

}

}

If you run into an issue with the code not mail enabling a folder, you should try to perform the same operation with Exchange System Manager (ESM). If ESM cannot mail-enable or mail-disable a folder, then custom code will not likely either. When this happens, you should concentrate on getting ESM to enable/disable the folder first rather than trying to resolve the issue in custom code first.

If the public folder was migrated from Exchange 5.5 and will not mail enable or disable, then the pf_proxy_required may not be set.

You may receive a c1038a21 error message when you try to use Exchange System Manager to look at the properties of a public folder

https://support.microsoft.com/?id=328740

Microsoft Exchange Server Public Folder DAV-based Administration Tool

https://www.microsoft.com/downloads/details.aspx?FamilyId=635BE792-D8AD-49E3-ADA4-E2422C0AB424&displaylang=en

PFDAVADMIN->connect to Server->Select Root public Folders->Click Tools->Custom

Bulk Operations

2- Type (DS:proxyaddresses=*) in the filter box

3- Click on ADD->Select other folder properties->ok

4- under the property box select PR_PF_PROXY_REQUIRED-> under value type 1 and

click on add-> click ok and again click ok

In Exchange 2007, you would use PowerShell to mail-enable a public folder:

How to Mail-Enable Public Folders: Exchange 2007 Help

https://technet.microsoft.com/en-us/library/aa997560.aspx