Hobby Chef

November, 2007 - Jive into Messaging world - Site Home - MSDN Blogs

Blog - Title

November, 2007

  • Jive into Messaging world

    HOWTO: EWS: Update IsRead Flag for items using Exchange Web Services

    • 16 Comments

    First thing first, you cannot use Exchange Web Services (as of now) to update the IsRead flag for items other than MessageType. MessageType has IsRead property in place to update the MAPI property PR_MESSAGE_FLAGS. Product group is aware of this limitation and very soon we should see an fix for this. In the mean time if you like to have a solution in place for all items (what I call as workaround), you can use WebDAV to update the IsRead flag for all other items.

     

           //Check the item's message class to either use WebDAV or EWS to update the PR_MESSAGE_FLAGS (IsRead)
            public static bool SetReadFlag(ItemIdType itemId, ReadStatus status)
            {
                bool retVal = false;
                
                //Use EWS to set the IsRead flag if it's MessageType, else use WebDAV
                if (GetItem(itemId.Id).ItemClass.StartsWith("IPM.Note", StringComparison.OrdinalIgnoreCase))
                    retVal = SetReadFlagForMessage(itemId, status);
                else
                    retVal = WebDAV_SetIsRead(GetFlatspaceURI(itemId.Id), status);
    
                return retVal;
            }
           
            //WebDAV code to update the IsRead flag, it uses OWA's FlatspaceURI to update the property
            private static bool WebDAV_SetIsRead(string itemUrl, ReadStatus status)
            {
                // Variables.
                bool retVal = false;
                
                System.Net.HttpWebRequest Request;
                System.Net.WebResponse Response;
                
                string strBody = "";
                byte[] bytes = null;
                System.IO.Stream RequestStream;
    
                // Build the PROPPATCH request body.
                strBody = "<?xml version=\"1.0\"?>"
                        + "<a:propertyupdate xmlns:a=\"DAV:\" xmlns:d=\"urn:schemas-microsoft-com:exch-data:\" "
                        + "xmlns:b=\"urn:schemas:httpmail:\" xmlns:c=\"xml:\">"
                        + "<a:set><a:prop><b:read>" + Convert.ToInt32((status == ReadStatus.Read ? true : false))
                        + "</b:read></a:prop>"
                        + "</a:set></a:propertyupdate>";
    
                
                // Create the HttpWebRequest object.
                Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(itemUrl);
    
                // Add the network credentials to the request.
                Request.Credentials = ExchangeBinding.CurrentInstance.Credentials;
    
                // Specify the method.
                Request.Method = "PROPPATCH";
    
                // Encode the body using UTF-8.
                bytes = Encoding.UTF8.GetBytes((string)strBody);
    
                // Set the content header length.  This must be
                // done before writing data to the request stream.
                Request.ContentLength = bytes.Length;
    
                // Get a reference to the request stream.
                RequestStream = Request.GetRequestStream();
    
                // Write the XML body to the request stream.
                RequestStream.Write(bytes, 0, bytes.Length);
    
                // Close the Stream object to release the connection
                // for further use.
                RequestStream.Close();
    
                // Set the content type header.
                Request.ContentType = "text/xml";
    
                // Send the PROPPATCH method request and get the
                // response from the server.
                Response = (HttpWebResponse)Request.GetResponse();
    
                retVal = true;
    
                // Clean up.
                Response.Close();
    
                return retVal;
    
            }
            
            //EWS code to update the IsRead flag, *ONLY* for MessageType
            private static bool SetReadFlagForMessage(ItemIdType messageId, ReadStatus status)
            {
    
                SetItemFieldType setField = new SetItemFieldType();
                MessageType message = new MessageType();
                if (status == ReadStatus.UnRead)
                    message.IsRead = false;
                else
                    message.IsRead = true;
                message.IsReadSpecified = true;
                setField.Item1 = message;
    
                PathToUnindexedFieldType path = new PathToUnindexedFieldType();
                path.FieldURI = UnindexedFieldURIType.messageIsRead;
                setField.Item = path;
    
    
                ItemChangeType[] updatedItems = new ItemChangeType[1];
                updatedItems[0] = new ItemChangeType();
                updatedItems[0].Updates = new ItemChangeDescriptionType[1];
                updatedItems[0].Updates[0] = setField;
    
                ItemChangeDescriptionType[] updates = new ItemChangeDescriptionType[1];
                updates[0] = new ItemChangeDescriptionType();
                updates[0].Item = path;
    
                updatedItems[0].Item = new ItemIdType();
                ((ItemIdType)updatedItems[0].Item).Id = messageId.Id;
                ((ItemIdType)updatedItems[0].Item).ChangeKey = messageId.ChangeKey;
    
    
                UpdateItemType request = new UpdateItemType();
                request.ItemChanges = updatedItems;
                request.ConflictResolution = ConflictResolutionType.AutoResolve;
                request.MessageDisposition = MessageDispositionType.SaveOnly;
                request.MessageDispositionSpecified = true;
                request.SendMeetingInvitationsOrCancellations = CalendarItemUpdateOperationType.SendToChangedAndSaveCopy;
                request.SendMeetingInvitationsOrCancellationsSpecified = true;
    
    
                UpdateItemResponseType response = ExchangeBinding.CurrentInstance.UpdateItem(request);
    
                if (response.ResponseMessages.Items[0].ResponseClass != ResponseClassType.Success)
                    return false;
                else
                    return true;
            }
    
            //Get the Flatspace URI , which can be consumed by WebDav
            public static string GetFlatspaceURI(string itemId)
            {
    
                GetItemType getRequest = new GetItemType();
    
                getRequest.ItemIds = new ItemIdType[1];
    
                ItemIdType id = new ItemIdType();
                //
                id.Id = itemId;
                getRequest.ItemIds[0] = id;
                getRequest.ItemShape = new ItemResponseShapeType();
                getRequest.ItemShape.BaseShape = DefaultShapeNamesType.IdOnly;
                getRequest.ItemShape.AdditionalProperties = new PathToExtendedFieldType[1];
    
                PathToExtendedFieldType PR_FLAT_URL_NAME = new PathToExtendedFieldType();
                PR_FLAT_URL_NAME.PropertyTag = "0x670E";
                PR_FLAT_URL_NAME.PropertyType = MapiPropertyTypeType.String;
    
                getRequest.ItemShape.AdditionalProperties[0] = PR_FLAT_URL_NAME;
                GetItemResponseType response = ExchangeBinding.CurrentInstance.GetItem(getRequest);
                ResponseMessageType rmt = response.ResponseMessages.Items[0];
    
                Console.WriteLine(rmt.ResponseClass.ToString());
                if (rmt.ResponseCodeSpecified)
                {
                    Console.WriteLine(rmt.ResponseCode);
                }
    
                ItemInfoResponseMessageType iirmt = rmt as ItemInfoResponseMessageType;
                ItemType item = iirmt.Items.Items[0];
                ExtendedPropertyType ept = item.ExtendedProperty[0];
    
                return ept.Item.ToString();
            }
     
    Programming for Exchange 2007? You need Inside Microsoft Exchange 2007 Web Services
     
  • Jive into Messaging world

    My first post using Windows Live Writer, it's so damn easy with WYSIWYG

    • 0 Comments

     

    Windows Live Writer - Rocks!!! thumbs_up - See the demo  

    First time blogger???

    You REALLY need Windows Live Writer!!!

    I cannot forget those days when I stopped blogging because it used to be a pain blogging using a Web Editor. I have used many Blog Editing Software and Windows Live is what I have been looking for... worth trying. Trust me you CANNOT do without it.

    me

    This is Me... Flying!!!

     

     

  • Jive into Messaging world

    Inside Microsoft Exchange 2007 Web Services is out on stores… go grab a copy today

    • 0 Comments

    The most awaited book on programming Exchange 2007 Server using Exchange Web Services is out.

    Get it here - http://www.microsoft.com/MSPress/books/10724.aspx

    No doubts that Exchange Web Services is next big thing and there is lot more to come in this space, fasten the seatbelt and get ready for Exchange Web Services

     

    Keywords: Exchange Web Services, Exchange 2007, Samples

  • Jive into Messaging world

    HOWTO: EWS: Consume Exchange Web Service from VBScript

    • 7 Comments

    Yes you can consume Exchange Web Service using VBScript or any language / platform which support HTML.

    In this sample, I have used XMLHTTP to send/receive soap request/response. Then I have used MSXML Document to parse the XML returned by the server to get the response code.

    I have converted my recently posted sample, HOWTO: EWS: Disable Out-of-office / OOF message to VBScript code.

    Const strUrl = "http://Your-Cas-Server/ews/exchange.asmx"

    Const strUser = "Username"

    Const strPass = "Password"

    Const strDom = "Domain"

    Const strEmailAddress = "youremail@domain.com"

    Dim oXml

    Dim xmlDoc

    Dim strXmlData

    Set oXml = CreateObject("MSXML2.XMLHTTP")

    Set xmlDoc = CreateObject("MSXML2.DOMDocument")

    strXmlData = "<?xml version=""1.0"" encoding=""utf-8""?>"

    strXmlData = strXmlData & "<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">"

    strXmlData = strXmlData & " <soap:Body>"

    strXmlData = strXmlData & " <SetUserOofSettingsRequest xmlns=""http://schemas.microsoft.com/exchange/services/2006/messages"">"

    strXmlData = strXmlData & " <Mailbox xmlns=""http://schemas.microsoft.com/exchange/services/2006/types"">"

    strXmlData = strXmlData & " <Address>" & strEmailAddress & "</Address>"

    strXmlData = strXmlData & " </Mailbox>"

    strXmlData = strXmlData & " <UserOofSettings xmlns=""http://schemas.microsoft.com/exchange/services/2006/types"">"

    strXmlData = strXmlData & " <OofState>Disabled</OofState>"

    strXmlData = strXmlData & " <ExternalAudience>All</ExternalAudience>"

    strXmlData = strXmlData & " <InternalReply>"

    strXmlData = strXmlData & " <Message />"

    strXmlData = strXmlData & " </InternalReply>"

    strXmlData = strXmlData & " <ExternalReply>"

    strXmlData = strXmlData & " <Message />"

    strXmlData = strXmlData & " </ExternalReply>"

    strXmlData = strXmlData & " </UserOofSettings>"

    strXmlData = strXmlData & " </SetUserOofSettingsRequest>"

    strXmlData = strXmlData & " </soap:Body>"

    strXmlData = strXmlData & "</soap:Envelope>"

    oXml.open "POST", strUrl, False, strDom & "\" & strUser, strPass

    oXml.setRequestHeader "Content-Type", "text/xml"

    oXml.send strXmlData

    If oXml.Status = "200" Then

    If xmlDoc.loadXML(oXml.responseText) Then

    If xmlDoc.documentElement.getElementsByTagName("ResponseMessage").Item(0).Attributes.getNamedItem("ResponseClass").Text = "Success" Then

    MsgBox "Oof Disabled"

    Else

    MsgBox "Oof Cannot be disabled" & vbCrLf & xmlDoc.xml

    End If

    End If

    Else

    MsgBox "Error: " & oXml.Status & " - " & oXml.statusText

    End If

    Keywords: VBScript, MSXML, XMLHTTP, SetUserOofSettings, ExchangeImpersonation, Exchange Web Services, Exchange 2007, Out Of Office

  • Jive into Messaging world

    HOWTO: EWS: Disable Out-of-office / OOF message

    • 4 Comments

    WebDav is definitely de-emphasized and not recommended to develop applications for Exchange 2007. But WebDav was still the easiest method to disable OOF message. I was not surprised to see it NOT working against Exchange 2007 to disable the OOF message. I have a better solution for you… use my favorite technology, Exchange Web Services!!!

    using System;

    using System.Collections.Generic;

    using System.Text;

    using DisableOof.MyEWS;

    namespace DisableOof

    {

    class Program

    {

    //TODO: Add Web Reference to your Exchange 2007 WebService URI

    //default URI is http://Your-Cas-Server/EWS/Exchange.asmx

    //

    //Refrences:

    // Configuring Exchange Impersonation

    // http://msdn2.microsoft.com/en-us/library/bb204095.aspx

    const string sUrl = "http://Your-Cas-Server/EWS/Exchange.asmx";     //TODO: Exchange 2007 WebService URI

    const string sUsr = "Username";                             //TODO: Username for the user that has service account level

    const string sPwd = "Password";                         //TODO: Password

    const string sDom = "DOMAIN";                         //TODO: Your Exchange Domain Name

    const string sMyEmailAddress = "myusername@domain.com";

    //Email address for the user to impersonate

    const string sImpersonatedUserEmail = "Impersonated-User@domain.com";

              

    static void Main(string[] args)

    {

    ExchangeServiceBinding esb = new ExchangeServiceBinding();

    esb.AllowAutoRedirect = true;

    esb.Url = sUrl;

    esb.Credentials = new System.Net.NetworkCredential(sUsr, sPwd, sDom);

    esb.UnsafeAuthenticatedConnectionSharing = true;

    //////Impersonate user and Disable OOF entries for impersonated user

    //////Uncomment this to enable impersonation

    //////See references on top to configure impersonation on exchange 2007

    //////

    ////esb.ExchangeImpersonation = new ExchangeImpersonationType();

    ////esb.ExchangeImpersonation.ConnectingSID = new ConnectingSIDType();

    ////esb.ExchangeImpersonation.ConnectingSID.PrimarySmtpAddress = sImpersonatedUserEmail;

    EmailAddress email = new EmailAddress();

    if (null == esb.ExchangeImpersonation)

    email.Address = sMyEmailAddress;

    else

    email.Address = sImpersonatedUserEmail;

    if (DisableOOF(esb, email))

    Console.WriteLine("Success: OOF Disabled");

    else

    Console.WriteLine("Error: Could not disable Oof Settings");

    }

    public static bool DisableOOF(ExchangeServiceBinding esb, EmailAddress emailAddress)

    {

    SetUserOofSettingsRequest request = new SetUserOofSettingsRequest();

    request.UserOofSettings = new UserOofSettings();

    request.UserOofSettings.OofState = OofState.Disabled;

    request.UserOofSettings.ExternalAudience = ExternalAudience.All;

    request.UserOofSettings.ExternalReply = new ReplyBody();

    request.UserOofSettings.ExternalReply.Message = "";

    request.UserOofSettings.InternalReply = new ReplyBody();

    request.UserOofSettings.InternalReply.Message = "";

    request.Mailbox = emailAddress;

    SetUserOofSettingsResponse response = esb.SetUserOofSettings(request);

    if (response.ResponseMessage.ResponseClass == ResponseClassType.Success)

    return true;

    else

    return false;

    }

    }

    }

    Keywords: SetUserOofSettings, ExchangeImpersonation, Exchange Web Services, Exchange 2007, Out Of Office

  • Jive into Messaging world

    HOWTO: EWS: Find all folders inside a parent folder, helpful in generating a folder tree

    • 11 Comments

    Looks cool isn’t it? I have created this folder tree for my mailbox using Exchange Web Services. You can do the very same.

    Here is the code which I am using to get all the folders inside a folder and recursively go deep-n-deep until your reach the core.

    Here is the sample code…

           

     

     

    /// <summary>

    /// FindAllFolder: you need to pass the parent folder id to get all the child folders inside it.

    /// NOTE: It returns only one level of child folders and

    /// to get children inside a child folder you need to run it again recursively

    /// </summary>

    /// <param name="strParentFolderId">Id of the folder you want to enumerate for children</param>

    /// <returns>BaseFolderType array containing all the child folders</returns>

     

    static public BaseFolderType[] FindAllFolder(string strParentFolderId)

    {

    if (null == ExchangeBinding.CurrentInstance || null == strParentFolderId)

                return null;

    //get the root folder ID

          FolderIdType[] fit = new FolderIdType[1];

          fit[0] = new FolderIdType();

          fit[0].Id = strParentFolderId;

         

    //set the props that we want to retrieve

          FolderResponseShapeType frst = new FolderResponseShapeType();

          frst.BaseShape = DefaultShapeNamesType.AllProperties;

               

          //find the folder

          FindFolderType fft = new FindFolderType();

          fft.Traversal = FolderQueryTraversalType.Shallow;

          fft.ParentFolderIds = fit;

          fft.FolderShape = frst;

               

    FindFolderResponseType ffrt = ExchangeBinding.CurrentInstance.FindFolder(fft);

          ResponseMessageType rmt = ((ResponseMessageType)ffrt.ResponseMessages.Items[0]);

    if (rmt.ResponseClass == ResponseClassType.Success)

    return ((FindFolderResponseMessageType)ffrt.ResponseMessages.Items [0]).RootFolder.Folders;

    else

                return null;

    }

     

     Keywords: FindFolder, Folder Enumeration, Exchange Web Services, Exchange 2007

Page 1 of 1 (6 items)