/// <summary>
        /// Moves the given message to the given folder.
        /// </summary>
        public void CopyMessageToFolder(ItemIdType messageId, string folderId)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            var request = new CopyItemType
            {
                ItemIds = new BaseItemIdType[] { messageId },
                ToFolderId = new TargetFolderIdType { Item = new FolderIdType { Id = folderId } }
            };

            CopyItemResponseType moveItemResponse = binding.CopyItem(request);

            if (moveItemResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                throw new Exception(moveItemResponse.ResponseMessages.Items[0].MessageText);
        }
        /// <summary>
        /// Delete the given message permanatly.
        /// </summary>
        /// <param name="messageId"></param>
        public void DeleteMessage(ItemIdType messageId)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            var deleteItemRequest = new DeleteItemType
              	{
              		ItemIds = new BaseItemIdType[] {messageId},
              		DeleteType = DisposalType.HardDelete
              	};

            DeleteItemResponseType deleteResponse = binding.DeleteItem(deleteItemRequest);

            if (deleteResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                throw new Exception(deleteResponse.ResponseMessages.Items[0].MessageText);
        }
        /// <summary>
        /// Sets the message readstate.
        /// </summary>
        public void SetMessageReadState(ItemIdType messageId, bool isRead)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            var setField = new SetItemFieldType
            {
                Item1 = new MessageType { IsRead = isRead, IsReadSpecified = true },
                Item = new PathToUnindexedFieldType { FieldURI = UnindexedFieldURIType.messageIsRead }
            };

            var updatedItems = new[]
               	{
                    new ItemChangeType
                  	{
                  		Updates = new ItemChangeDescriptionType[] { setField },
                  		Item = messageId
                  	}
                };

            var request = new UpdateItemType
            {
                ItemChanges = updatedItems,
                ConflictResolution = ConflictResolutionType.AutoResolve,
                MessageDisposition = MessageDispositionType.SaveOnly,
                MessageDispositionSpecified = true
            };

            UpdateItemResponseType updateItemResponse = binding.UpdateItem(request);

            if (updateItemResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                throw new Exception(updateItemResponse.ResponseMessages.Items[0].MessageText);
        }
        /// <summary>
        /// Asks Exchange to send a specific message.
        /// </summary>
        /// <param name="messageId"></param>
        public void SendMessage(ItemIdType messageId)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            // Send message
            var sendItem = new SendItemType { ItemIds = new BaseItemIdType[1], SavedItemFolderId = new TargetFolderIdType() };
            var siSentItemsFolder = new DistinguishedFolderIdType { Id = DistinguishedFolderIdNameType.sentitems };

            sendItem.SavedItemFolderId.Item = siSentItemsFolder;
            sendItem.SaveItemToFolder = true;
            sendItem.ItemIds[0] = messageId;

            SendItemResponseType sendItemResponse = binding.SendItem(sendItem);

            if (sendItemResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                throw new Exception(sendItemResponse.ResponseMessages.Items[0].MessageText);
        }
        /// <summary>
        /// Saves all attachments belonging to a specific message. This method can only be called after the message
        /// has been saved in exchange.
        /// </summary>
        /// <param name="messageId"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public IEnumerable<ItemIdType> SaveAttachments(ItemIdType messageId, ChannelMessage message)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            // Create add attachment request.
            var attachementRequest = new CreateAttachmentType();
            attachementRequest.ParentItemId = messageId;
            attachementRequest.Attachments = new AttachmentType[message.Attachments.Count];

            for (int i = 0; i < message.Attachments.Count; i++)
            {
                var channelAttachment = message.Attachments[i];
                var exchAttachment = new FileAttachmentType();

                exchAttachment.Name = channelAttachment.Filename;
                exchAttachment.ContentType = MimeHelper.GetMimeType(channelAttachment.Filename);
                exchAttachment.Content = channelAttachment.ContentStream.GetBytes();

                attachementRequest.Attachments[i] = exchAttachment;

                var saveAttachmentResponse = binding.CreateAttachment(attachementRequest);

                // Determine whether the request was a success.
                if (saveAttachmentResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                    throw new Exception(saveAttachmentResponse.ResponseMessages.Items[0].MessageText);

                AttachmentIdType attachmentId = ((AttachmentInfoResponseMessageType)saveAttachmentResponse.ResponseMessages.Items[0]).Attachments[0].AttachmentId;

                yield return new ItemIdType { ChangeKey = attachmentId.RootItemChangeKey, Id = attachmentId.RootItemId };
            }
        }
        /// <summary>
        /// Gets the id and changekey of a specific message by id.
        /// </summary>
        /// <param name="messageId"></param>
        /// <returns></returns>
        public MessageType GetMessageId(string messageId)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            ItemIdType itemId = new ItemIdType();
            itemId.Id = messageId;

            // Re-get item and changekey from exchange
            GetItemResponseType getItemResponse = binding.GetItem(new GetItemType
                {
                    ItemShape = new ItemResponseShapeType { BaseShape = DefaultShapeNamesType.IdOnly },
                    ItemIds = new[] { itemId }
                });

            if (getItemResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                throw new Exception(getItemResponse.ResponseMessages.Items[0].MessageText);

            return (MessageType)((ItemInfoResponseMessageType)getItemResponse.ResponseMessages.Items[0]).Items.Items[0];
        }
        /// <summary>
        /// Gets a specific message from exchange by id (attachments are only loaded shallow).
        /// </summary>
        /// <param name="messageId"></param>
        /// <returns></returns>
        public MessageType GetMessage(string messageId)
        {
            var binding = ChannelHelper.BuildChannel(hostname, username, password);

            ItemIdType itemId = new ItemIdType();
            itemId.Id = messageId;

            GetItemType getItemRequest = new GetItemType();
            getItemRequest.ItemShape = new ItemResponseShapeType { BaseShape = DefaultShapeNamesType.AllProperties };
            getItemRequest.ItemIds = new[] { itemId };

            GetItemResponseType getItemResponse = binding.GetItem(getItemRequest);

            if (getItemResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                throw new Exception(getItemResponse.ResponseMessages.Items[0].MessageText);

            var getItemResponseMessage = (ItemInfoResponseMessageType)getItemResponse.ResponseMessages.Items[0];

            if (getItemResponseMessage.Items.Items == null || getItemResponseMessage.Items.Items.Length == 0)
                throw new ApplicationException("Error in GetMessage, empty ItemInfoResponseMessageType");

            return (MessageType)getItemResponseMessage.Items.Items[0];
        }