Recently, I was tasked with querying our Exchange Server. After a day or two research, I realized
there there is no real .net wrapper to do this. After looking into several different ways and
technologies I decided to go with C# using WebDAV.
static void Main(string[] args)
{
WATGDataContext dc = new WATGDataContext();
String sExchangeBaseUrl = "http://{0}/Exchange/{1}/";
String sExchangeFolderUrl = "http://{0}/Exchange/{1}/{2}";
List<String> ExchangeServers = new List<string> { "exch01", "exch02", "exch03" };
String sQueryUrl = String.Empty;
int iContact = 0;
List<LocalEmplyeeContacts> Contacts = new List<LocalEmplyeeContacts>();
List<Employee> OfficeEmployees = null;
EmployeeContact employeeContact = null;
String sBaseQuery = String.Empty;
String sFolderPath = String.Empty;
//query
var baseEmployeesQuery = from q in dc.Employees
where q.LogonName != String.Empty
orderby q.LastName
select q;
foreach (var server in ExchangeServers)
{
#region "Servers"
//office queries
if (server.Equals("newexch01"))
{
var subquery = from q in baseEmployeesQuery
where
q.Office.Equals("Irvine")
|| q.Office.Equals("Seattle")
|| q.Office.Equals("Orlando")
|| q.Office.Equals("Singapore")
|| q.Office.Equals("Newport")
orderby q.LastName
select q;
OfficeEmployees = subquery.ToList();
}
else if (server.Equals("lonexch01"))
{
var subquery = from q in baseEmployeesQuery
where
q.Office.Equals("London")
|| q.Office.Equals("Henley")
orderby q.LastName
select q;
OfficeEmployees = subquery.ToList();
}
else if (server.Equals("honexch01"))
{
var subquery = from q in baseEmployeesQuery
where
q.Office.Equals("Honolulu")
orderby q.LastName
select q;
OfficeEmployees = subquery.ToList();
}
#endregion
//foreach employee
foreach (var employee in OfficeEmployees)
{
sBaseQuery = String.Empty;
sFolderPath = String.Empty;
try
{
Console.WriteLine("Getting Contacts for " + employee.LogonName + " in " + server);
//First get all Folders
sBaseQuery = String.Format(sExchangeBaseUrl, server, employee.LogonName.Trim());
//set root
sFolderPath = "Contacts";
//foreach folder
#region "For each Folder"
List<String> Folders = null;
//get recursive list of foldres in "Contacts" root
Folders = GetCascadingFolders(sBaseQuery, sFolderPath);
//add root ("Contacts") to list.
Folders.Add("Contacts");
foreach (var folder in Folders)
{
try
{
sQueryUrl = String.Format(sExchangeFolderUrl, server, employee.LogonName, folder);
Contacts = GetContactsInFolderPath(sQueryUrl);
//add contacts for each folder to capture folder path
if (Contacts.Count() > 0)
{
foreach (var item in Contacts)
{
employeeContact = new EmployeeContact();
employeeContact.EmplyeeContactSeq = Guid.NewGuid();
employeeContact.EmployeeLogon = employee.LogonName;
employeeContact.FolderPath = folder;
employeeContact.FullName = item.FullName;
employeeContact.Server = server;
employeeContact.Email = item.Email;
employeeContact.Phone = item.Phone;
employeeContact.Mobile = item.Mobile;
employeeContact.City = item.City;
employeeContact.State = item.State;
employeeContact.Country = item.Country;
employeeContact.Company = item.Company;
employeeContact.Title = item.Title;
dc.EmployeeContacts.InsertOnSubmit(employeeContact);
dc.SubmitChanges();
iContact++;
Console.WriteLine(iContact.ToString());
}
}
Contacts.Clear();
}
catch { }
}
Folders.Clear();
#endregion
}
catch { }
}
}
}
#region "Util"
private static List<String> GetCascadingFolders(String _queryUrl, String _folderPath)
{
List<String> folders = new List<String>();
String folder = String.Empty;
String sWebDavQuery = String.Empty;
String sResultText = String.Empty;
XmlDocument xmlDoc = null;
String sNewFolderPath = String.Empty;
int iCounter = 0;
try
{
MSXML2.XMLHTTP30 oXMLHttp = new MSXML2.XMLHTTP30();
if (_queryUrl != String.Empty)
{
oXMLHttp.open("SEARCH", _queryUrl + "/" + _folderPath, false, @"username", "password");
sWebDavQuery = "<?xml version=\"1.0\"?>"
+ "<g:searchrequest xmlns:g=\"DAV:\">"
+ "<g:sql>SELECT \"urn:schemas:contacts:cn\" "
+ "FROM SCOPE('SHALLOW TRAVERSAL OF \"" + _queryUrl + "/" + _folderPath + "\"')"
+ " WHERE \"DAV:isfolder\" = true"
+ "</g:sql></g:searchrequest>";
oXMLHttp.setRequestHeader("Content-Type", "text/xml");
oXMLHttp.setRequestHeader("Translate", "f");
oXMLHttp.setRequestHeader("Content-Length", "" + sWebDavQuery.Length);
oXMLHttp.send(sWebDavQuery);
sResultText = oXMLHttp.responseText;
if (!sResultText.Contains("Bad request"))
{
xmlDoc = new XmlDocument();
xmlDoc.LoadXml(sResultText);
var query = from q in xmlDoc.DocumentElement.ChildNodes.Cast<XmlNode>()
select q;
foreach (var item in query)
{
folder = String.Empty;
try
{
XmlNode node = item;
iCounter = 0;
foreach (XmlNode childNode in node.ChildNodes[1].ChildNodes[1].ChildNodes)
{
try
{
if (childNode.Name.Equals("d:cn"))
folder = childNode.ChildNodes[0].Value.ToString();
if (folder != String.Empty)
{
sNewFolderPath = _folderPath + "/" + folder;
folders.AddRange(GetCascadingFolders(_queryUrl, sNewFolderPath));
}
iCounter++;
}
catch { }
}
folders.Add(sNewFolderPath);
}
catch { }
}
}
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return folders;
}
private static List<LocalEmplyeeContacts> GetContactsInFolderPath(String _queryUrl)
{
List<LocalEmplyeeContacts> contacts = new List<LocalEmplyeeContacts>();
LocalEmplyeeContacts contact = null;
String company = String.Empty;
String fullname = String.Empty;
String title = String.Empty;
String mail = String.Empty;
String telephoneNumber = String.Empty;
String mobile = String.Empty;
String city = String.Empty;
String state = String.Empty;
String country = String.Empty;
int iCounter = 0;
try
{
MSXML2.XMLHTTP30 oXMLHttp = new MSXML2.XMLHTTP30();
if (_queryUrl != String.Empty)
{
oXMLHttp.open("SEARCH", _queryUrl, false, @"username", "password");
string sQuery = "<?xml version=\"1.0\"?>"
+ "<g:searchrequest xmlns:g=\"DAV:\">"
+ "<g:sql>SELECT "
+ "\"urn:schemas:contacts:o\", "
+ "\"urn:schemas:contacts:cn\", "
+ "\"urn:schemas:contacts:title\", "
+ "\"urn:schemas:contacts:email1\", "
+ "\"urn:schemas:contacts:telephoneNumber\", "
+ "\"urn:schemas:contacts:o\", "
+ "\"urn:schemas:contacts:l\", "
+ "\"urn:schemas:contacts:st\", "
+ "\"urn:schemas:contacts:mobile\", "
+ "\"urn:schemas:contacts:cn\" "
+ " FROM SCOPE('SHALLOW TRAVERSAL OF \"" + _queryUrl + "\"')"
+ "</g:sql></g:searchrequest>";
oXMLHttp.setRequestHeader("Content-Type", "text/xml");
oXMLHttp.setRequestHeader("Translate", "f");
oXMLHttp.setRequestHeader("Content-Length", "" + sQuery.Length);
try
{
oXMLHttp.send(sQuery);
}
catch { }
String sResultText = oXMLHttp.responseText;
String sResultXML = oXMLHttp.responseXML.ToString();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(sResultText);
var query = from q in xmlDoc.DocumentElement.ChildNodes.Cast<XmlNode>()
select q;
foreach (var item in query)
{
company = String.Empty;
fullname = String.Empty;
title = String.Empty;
mail = String.Empty;
telephoneNumber = String.Empty;
mobile = String.Empty;
city = String.Empty;
country = String.Empty;
state = String.Empty;
try
{
contact = new LocalEmplyeeContacts();
XmlNode node = item;
iCounter = 0;
foreach (XmlNode childNode in node.ChildNodes[1].ChildNodes[1].ChildNodes)
{
try
{
if (childNode.Name.Equals("d:o"))
company = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:mobile"))
mobile = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:cn"))
fullname = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:title"))
title = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:telephoneNumber"))
telephoneNumber = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:email1"))
mail = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:l"))
city = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:st"))
state = childNode.ChildNodes[0].Value.ToString();
else if (childNode.Name.Equals("d:co"))
country = childNode.ChildNodes[0].Value.ToString();
iCounter++;
}
catch { }
}
contact.Company = company;
//fix watg emp email
if (mail.IndexOf("\"") >= 0)
{
String sRegEx = "\".*\"";
String sString = mail;
String sClean = String.Empty;
Regex regex = new Regex(sRegEx, RegexOptions.Singleline);
sClean = regex.Match(sString).Value;
mail = sClean.Replace("\"", "").ToLower();
//mail = sClean.Replace("'", "").ToLower();
}
contact.Email = mail;
contact.Phone = telephoneNumber;
contact.Title = title;
contact.FullName = fullname;
contact.Mobile = mobile;
contact.City = city;
contact.Country = country;
contact.State = state;
contacts.Add(contact);
}
catch { }
}
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return contacts;
}
#endregion
Hope it’s helpful.