Hobby Chef

February, 2009 - Jive into Messaging world - Site Home - MSDN Blogs

Blog - Title

February, 2009

  • Jive into Messaging world

    MAPI asks: Can you please take it offline???


    MAPI developers have another reason to cheers. Now you can take the MAPI documentation with you for a walk.

    Outlook 2007 MAPI Reference is now also available as offline download in a CHM format, download it here 


    All you need now is find a CHM viewer for your Windows Mobile and take the documentation with you all the time… sweet!!!

  • Jive into Messaging world

    HOWTO: EWS: Send UTF-16 request to Exchange Web Service from VBScript


    I had explained earlier how you can consume Exchange Web Services like WebDAV from VBScript in the below sample


    Today I had a requirement to send Unicode request to the server but VBScript does not support Unicode. I workaround this situation, with the help of Notepad and VBScript.

    In the notepad, write the XML that you need to pass on to the server. We will be using it as raw packet. We can use the following simplest FindItem call to list all the items from Inbox

    <?xml version="1.0" encoding="UTF-16"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
        <FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" Traversal="Shallow">
            <t:DistinguishedFolderId Id="inbox" />
    Copy paste the XML into the notepad and save it as UNICODE, make sure you select the UNICODE format while saving the notepad
    Once done, now use the following script to send the packet to Exchange Web Service using MSXML’s ServerXMLHttp class.
    Const strCasServer = "CAS_SERVER_NAME"
    Const strUsername = "USERNAME"
    Const strPassword = "********"
    Dim objXmlRequestor
    Dim strBuffer
    Dim strOutput
    'Ignoring SSL Errors
    Set objXmlRequestor = CreateObject("MSXML2.SERVERXMLHTTP")
    'Reading the RAW UNICODE packet we just saved
    strBuffer = ReadBinaryFile("packet.txt")
    'Sending the request to server
    objXmlRequestor.open "POST", "https://" & strCasServer & "/ews/exchange.asmx",false
    objXmlRequestor.setRequestHeader "Content-Type", "text/xml; charset=utf-16"
    'Generating Base64 authorization string for BASIC authentication
    objXmlRequestor.setRequestHeader "Authorization", "BASIC " & Base64Encode(strUsername & ":" & strPassword)
    'Specify the User-Agent string
    objXmlRequestor.setRequestHeader "User-Agent", "Visual Basic Scripting Client"
    objXmlRequestor.setRequestHeader "Host", strCasServer
    'Make sure you use LenB to get the corrent length from unicode string
    objXmlRequestor.setRequestHeader "Content-Length", LenB(strBuffer)
    objXmlRequestor.send strBuffer
    strOutput = objXmlRequestor.getAllResponseHeaders & vbCrLf & objXmlRequestor.responseText
    'Dump the response along with headers on to the screen
    Wscript.echo strOutput
    ' Used for reading binary/unicode file
    Function ReadBinaryFile(FileName)
      Const adTypeBinary = 1
      'Create Stream object
      Dim BinaryStream
      Set BinaryStream = CreateObject("ADODB.Stream")
      'Specify stream type - we want To get binary data.
      BinaryStream.Type = adTypeBinary
      'Open the stream
      'Load the file data from disk To stream object
      BinaryStream.LoadFromFile FileName
      'Open the stream And get binary data from the object
      ReadBinaryFile = BinaryStream.Read
    End Function
    Function Base64Encode(inputData)
      Const strBase64String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
      Dim cOut, sOut, I
      For I = 1 To Len(inputData) Step 3
        Dim nGroup, pOut, sGroup
        nGroup = &H10000 * Asc(Mid(inputData, I, 1)) + &H100 * RealASC(Mid(inputData, I + 1, 1)) + RealASC(Mid(inputData, I + 2, 1))
        nGroup = Oct(nGroup)
        nGroup = String(8 - Len(nGroup), "0") & nGroup
        'Convert To base64 string
        pOut = Mid(strBase64String , CLng("&o" & Mid(nGroup, 1, 2)) + 1, 1) + _
          Mid(strBase64String , CLng("&o" & Mid(nGroup, 3, 2)) + 1, 1) + _
          Mid(strBase64String , CLng("&o" & Mid(nGroup, 5, 2)) + 1, 1) + _
          Mid(strBase64String , CLng("&o" & Mid(nGroup, 7, 2)) + 1, 1)
        sOut = sOut + pOut
      Select Case Len(inputData) Mod 3
        Case 1: 
          sOut = Left(sOut, Len(sOut) - 2) + "=="
        Case 2: 
          sOut = Left(sOut, Len(sOut) - 1) + "="
      End Select
      Base64Encode = sOut
    End Function
    Function RealASC(SingleChar)
      If SingleChar = "" Then RealASC = 0 Else RealASCASC = Asc(SingleChar)
    End Function
  • Jive into Messaging world

    HOWTO: Create Search Folder using Exchange Impersonation for multiple users via Exchange Web Services


    What are we doing here? What is Search Folder? Why do I care?

    Search folders are a quick way to bookmark your frequently searched items. It allows you to save a search query with predefined parameters for quick access. For instance I am always looking for emails with attachments and from a particular sender where the subject has some specific words. Yeah a rule could do that but I want to search in multiple folders and keep the individual mails in their individual folders. Complex? not really!

    Search folders can help you in creating all those complex queries and mapping them to a single folder to bring all the items under one umbrella, whether its raining or not.

    So far everything sounds good now I want to implement this solution enterprise wide, I want to role out a specific query for everyone in my organization is it possible from GUI, server side script or any way to do this. Don’t even think about sending Outlook Macro Project to everyone in your organization. You have a better solution with Exchange 2007 SP1 – Exchange Web Services

    I feel blessed with the existence of Exchange Web Services. You can use Exchange Impersonation to act on behalf of every individual in your Organization, go to every individual’s mailbox and create a search folder for them.

    Ok now… stop talking and show me the code.. here you go!

    using System;
    using System.Collections.Generic;
    using System.Text;
    using SearchFolderCreator.MyEWS;
    using System.Net;
    using System.IO;
    namespace SearchFolderCreator
        class Program
            static ExchangeServiceBinding esb = null;
            const string strSearchText = "IPM.Note";
            const string strEWSURL = "https://server/ews/exchange.asmx";
            const string strUsername = "Username";
            const string strPassword = "********";
            const string strDomain = "Domain.com";
            const string strSearchFolderName = "EWS Created Search Folder";
            static void Main(string[] args)
                esb = new ExchangeServiceBinding();
                esb.Credentials = new NetworkCredential(strUsername, strPassword, strDomain);
                esb.AllowAutoRedirect = true;
                esb.Url = strEWSURL;
                catch (Exception e)
                    Console.WriteLine("Exception Caught: " + e.ToString());
            static BaseFolderType CreateSearchFolder()
                FolderIdType folderID = new FolderIdType();
                //create the request that will create a new searchfolder under the finder directory
                CreateFolderType folderType = new CreateFolderType();
                SearchFolderType[] folderArray = new SearchFolderType[1];
                folderArray[0] = new SearchFolderType();
                folderArray[0].SearchParameters = new SearchParametersType();
                folderArray[0].SearchParameters.Traversal = SearchFolderTraversalType.Deep;        // deep traversal
                folderArray[0].SearchParameters.TraversalSpecified = true;                        // must set it to true otherwise traversal will have no effect
                folderArray[0].SearchParameters.BaseFolderIds = new DistinguishedFolderIdType[1];
                DistinguishedFolderIdType dType = new DistinguishedFolderIdType();
                dType.Id = new DistinguishedFolderIdNameType();
                dType.Id = DistinguishedFolderIdNameType.inbox;                                    //  we are looking at Inbox only
                folderArray[0].SearchParameters.BaseFolderIds[0] = dType;
                PathToUnindexedFieldType path = new PathToUnindexedFieldType();
                path.FieldURI = UnindexedFieldURIType.itemItemClass;                            // Evaluating a string with Item Class
                folderArray[0].SearchParameters.Restriction = new RestrictionType();
                ContainsExpressionType expressionType = new ContainsExpressionType();
                expressionType.Item = path;
                expressionType.ContainmentModeSpecified = true;
                expressionType.ContainmentMode = ContainmentModeType.FullString;                // Matching full string
                expressionType.ContainmentComparison = ContainmentComparisonType.Exact;            // With Exact match
                expressionType.ContainmentComparisonSpecified = true;
                expressionType.Constant = new ConstantValueType();
                expressionType.Constant.Value = strSearchText;                                    // Subject to look for
                folderArray[0].SearchParameters.Restriction.Item = expressionType;
                folderArray[0].DisplayName = strSearchFolderName;                        // Give your search folder a unique name
                folderType.Folders = folderArray;
                TargetFolderIdType targetFolder = new TargetFolderIdType();
                //Create the searchfolder under the Finder Folder
                DistinguishedFolderIdType searchFolder = new DistinguishedFolderIdType();
                searchFolder.Id = DistinguishedFolderIdNameType.searchfolders;                    // Saving it under searchfolders root
                targetFolder.Item = searchFolder;
                folderType.ParentFolderId = targetFolder;
                // Uncomment the following lines of code to make it a hidden search folder, can be consumed by other programs and not visible to users
                // See the explanintion below
                // folderArray[0].ExtendedProperty = new ExtendedPropertyType[1];
                // folderArray[0].ExtendedProperty[0] = new ExtendedPropertyType();
                // folderArray[0].ExtendedProperty[0].ExtendedFieldURI = new PathToExtendedFieldType();
                // folderArray[0].ExtendedProperty[0].ExtendedFieldURI.PropertyTag="0x10F4";   //PR_ATTR_HIDDEN
                // folderArray[0].ExtendedProperty[0].ExtendedFieldURI.PropertyType = MapiPropertyTypeType.Boolean;
                // folderArray[0].ExtendedProperty[0].Item = "true";
                //Create the search folder
                CreateFolderResponseType createFolderResponse = esb.CreateFolder(folderType);
                //Return the newly created search folder
                FolderInfoResponseMessageType folderInfo = (FolderInfoResponseMessageType)createFolderResponse.ResponseMessages.Items[0];
                return folderInfo.Folders.Length == 0 ? null : folderInfo.Folders[0];
            static bool DeleteSearchFolder()
                string strSearchFolderID = null;
                //get the search folder's ID
                strSearchFolderID = SearchFolderExists();
                if (strSearchFolderID==string.Empty || strSearchFolderID ==null)
                    return false;
                FolderIdType folderID = new FolderIdType();
                folderID.Id = strSearchFolderID;
                //Now create the request that will delete the searchfolder using FolderID we have already
                DeleteFolderType folderType = new DeleteFolderType();
                folderType.DeleteType = DisposalType.HardDelete;
                folderType.FolderIds = new BaseFolderIdType[1];
                folderType.FolderIds[0] = folderID;
                //Delete the search folder
                DeleteFolderResponseType deleteFolderResponse = esb.DeleteFolder(folderType);
                return deleteFolderResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Success ? true : false;
            // Search for folder if it already exists
            static string SearchFolderExists()
                if (null == esb)
                    return false;
                //get the root folder ID
                DistinguishedFolderIdType[] fit = new DistinguishedFolderIdType[1];
                fit[0] = new DistinguishedFolderIdType();
                fit[0].Id = DistinguishedFolderIdNameType.searchfolders;
                //set the props that we want to retrieve
                FolderResponseShapeType frst = new FolderResponseShapeType();
                frst.BaseShape = DefaultShapeNamesType.IdOnly;
                //restrict the search on the folder name
                PathToUnindexedFieldType ftFolderName = new PathToUnindexedFieldType();
                ftFolderName.FieldURI = UnindexedFieldURIType.folderDisplayName;
                ConstantValueType cvt = new ConstantValueType();
                cvt.Value = strSearchFolderName;
                FieldURIOrConstantType ctFolderName = new FieldURIOrConstantType();
                ctFolderName.Item = cvt;
                ContainsExpressionType cet = new ContainsExpressionType();
                cet.Constant = cvt;
                cet.Item = ftFolderName;
                cet.ContainmentComparisonSpecified = true;
                cet.ContainmentMode = ContainmentModeType.FullString;
                cet.ContainmentModeSpecified = true;
                RestrictionType rt = new RestrictionType();
                rt.Item = cet;
                //find the folder
                FindFolderType fft = new FindFolderType();
                fft.Traversal =FolderQueryTraversalType.Shallow;
                fft.ParentFolderIds = fit;
                fft.FolderShape = frst;
                fft.Restriction = rt;
                FindFolderResponseType ffrt = esb.FindFolder(fft);
                ResponseMessageType rmt =
                if (rmt.ResponseClass == ResponseClassType.Success)
                    FindFolderResponseMessageType folderInfo = (FindFolderResponseMessageType)ffrt.ResponseMessages.Items[0];
                    if (folderInfo.RootFolder.Folders.Length == 0)
                        return string.Empty;
                        return folderInfo.RootFolder.Folders[0].FolderId.Id;
                    return  string.Empty;
            static void InstallForUser(string primarySMTPaddress)
                string SubscriptionID = null;
                esb.ExchangeImpersonation = new ExchangeImpersonationType();
                esb.ExchangeImpersonation.ConnectingSID = new ConnectingSIDType();
                esb.ExchangeImpersonation.ConnectingSID.PrimarySmtpAddress = primarySMTPaddress;
                Console.WriteLine("Processing \"" + primarySMTPaddress + "\"...");
                Console.WriteLine("Checking if search folder already exists...");
                if (!SearchFolderExists())
                    Console.WriteLine("Search folder does not exist, creating one...");
                    strSearchFolderID = CreateHiddenSearchFolder().FolderId.Id;
                    Console.WriteLine("Search folder created.");
                    Console.WriteLine("Search folder already exist... deleting existing one...");
                    Console.WriteLine("Search folder deleted, creating new one...");
                    strSearchFolderID = CreateHiddenSearchFolder().FolderId.Id;
                    Console.WriteLine("Search folder created.");
                Console.WriteLine("Search Folder ID: " + strSearchFolderID);

    I talked about inside code, about Hidden Search Folder. You can make your search folders hidden but what could be the use of search folders if they are hidden? Users cannot see them so who will use them? Well that’s for later :)

  • Jive into Messaging world

    Soooooo tweet..


    Follow me at http://twitter.com/findvikas for all the updates from my life, technology, gizmos and what not? I am eating breakfast or its dinner time. Playing fussball or 8 ball.. is it a complex problem or a piece of cake. Be part of my life and be a part of every celebration… life is a party so join it now.

Page 1 of 1 (4 items)