Action Data buffer format for ActionType: OP_FORWARD, OP_DELEGATE
Inheritance: IActionData
        public void MSOXORULE_S01_TC05_ModifyOrDeleteRule()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForward);
            #endregion

            #region TestUser1 prepares the recipient block for Forward rules.
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            #region TestUser1 adds rule forward.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };

            RuleData ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, forwardActionData, ruleProperties, null);
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information for the newly added rule.
            PropertyTag[] propertyTags = new PropertyTag[2];
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagRuleName;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTags[1].PropertyId = (ushort)PropertyId.PidTagRuleId;
            propertyTags[1].PropertyType = (ushort)PropertyType.PtypInteger64;

            // Retrieve rows from the rule table.
            RopQueryRowsResponse queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");
            
            // Add one rules to the Inbox folder. If the rule table is got successfully and the rule count is 1,
            // it means that the server is returning a table with the rule added by the test suite.
            Site.Assert.IsTrue(queryRowResponse.RowCount == 1, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            ulong ruleId = BitConverter.ToUInt64(queryRowResponse.RowData.PropertyRows[0].PropertyValues[1].Value, 0);
            this.VerifyRuleTable();

            #region   Capture R127
            bool isVerifiedR127 = Encoding.Unicode.GetString(queryRowResponse.RowData.PropertyRows[0].PropertyValues[0].Value).Equals(ruleProperties.Name + "\0");
  
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R127");

            // Verify MS-OXORULE requirement: MS-OXORULE_R127
            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR127,
                127,
                @"[In RopGetRulesTable ROP Request Buffer] [TableFlags] U: (Bitmask 0x40): This bit is set if the client is requesting that string values in the table be returned as Unicode strings.");

            #endregion
            #endregion

            #region TestUser1 prepares the recipient block for Forward rules.
            recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User1Name, this.User1ESSDN);
            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            #region TestUser1 modifies the created rule.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForward);
            forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };

            ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForModify, 0, RuleState.ST_ENABLED, forwardActionData, ruleProperties, ruleId);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information for the modified rule.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Only one rule added in the Inbox folder. If the rule table is got successfully and the rule count is 1,
            // it means that the server is returning a table with the rule added by the test suite.
            Site.Assert.AreEqual<uint>(1, queryRowResponse.RowCount, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            this.VerifyRuleTable();
            
            ulong ruleIdModified = BitConverter.ToUInt64(queryRowResponse.RowData.PropertyRows[0].PropertyValues[1].Value, 0);
            bool isSameRuleId = ruleId == ruleIdModified;
            Site.Assert.IsTrue(isSameRuleId, "The original rule Id is {0} and the modified rule Id is {1}", ruleId, ruleIdModified);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R671");

            bool isVerifiedR671 = isSameRuleId && queryRowResponse.RowCount == 1;

            // Verify MS-OXORULE requirement: MS-OXORULE_R671.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR671,
                671,
                @"[In RopModifyRules ROP Request Buffer] [ModifyRulesFlag] R (Bitmask 0x01): If this bit is not set, the rules (2) specified in this request represent changes (delete, modify, and add) to the set of rules (2) already existing in this folder.");

            #endregion

            #region TestUser1 adds rule DELEGATE.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelegate, 1);
            ForwardDelegateActionData delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };

            #region Prepare the Delegate rule Recipient block
            RecipientBlock delegateRecipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };
            TaggedPropertyValue[] delegateRecipientProperties = new TaggedPropertyValue[5];

            TaggedPropertyValue[] tempArray = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(tempArray, 0, delegateRecipientProperties, 0, tempArray.Length);

            // Add PidTagSmtpEmailAdderss.
            delegateRecipientProperties[4] = new TaggedPropertyValue();
            PropertyTag delegateRecipientPropertiesPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            delegateRecipientProperties[4].PropertyTag = delegateRecipientPropertiesPropertyTag;
            delegateRecipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            delegateRecipientBlock.PropertiesData = delegateRecipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { delegateRecipientBlock };
            RuleData ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Delegate rule should succeed.");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information to check if two rules exist.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Two rules have been added to the Inbox folder, so the row count in the rule table should be 2.
            Site.Assert.AreEqual<uint>(2, queryRowResponse.RowCount, "The rule number in the rule table  should be 2.");
            bool twoRulesExistBeforeReplaceAll = queryRowResponse.RowCount == 2;
            this.VerifyRuleTable();

            #endregion

            #region TestUser1 adds another rule to replace all the existing rules.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelegate, 2);
            delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };

            #region Prepare the Delegate rule Recipient block
            delegateRecipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };
            delegateRecipientProperties = new TaggedPropertyValue[5];

            tempArray = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(tempArray, 0, delegateRecipientProperties, 0, tempArray.Length);

            // Add PidTagSmtpEmailAdderss
            delegateRecipientProperties[4] = new TaggedPropertyValue();
            delegateRecipientPropertiesPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            delegateRecipientProperties[4].PropertyTag = delegateRecipientPropertiesPropertyTag;
            delegateRecipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            delegateRecipientBlock.PropertiesData = delegateRecipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { delegateRecipientBlock };
            ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Delegate rule should succeed.");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information to check if the existing rules are replaced.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Only one rule exist on Inbox folder, so the row count in the rule table should be 1.
            Site.Assert.AreEqual<uint>((uint)1, queryRowResponse.RowCount, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            this.VerifyRuleTable();

            // Only one rule exist on Inbox folder, means other rules have been replaced.
            bool oneRuleExistsAfterReplaceAll = queryRowResponse.RowCount == 1;
            ruleId = BitConverter.ToUInt64(queryRowResponse.RowData.PropertyRows[0].PropertyValues[1].Value, 0);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R669: the row count of rule table before replace is {0}, and after replace is {1}", twoRulesExistBeforeReplaceAll, oneRuleExistsAfterReplaceAll);

            // Verify MS-OXORULE requirement: MS-OXORULE_R669
            bool isVerifiedR669 = twoRulesExistBeforeReplaceAll && oneRuleExistsAfterReplaceAll;

            Site.CaptureRequirementIfIsTrue(
                isVerifiedR669,
                669,
                @"[In RopModifyRules ROP Request Buffer] [ModifyRulesFlag] R (Bitmask 0x01): If this bit is set, the rules (2) in this request are to replace the existing set of rules (2) in the folder.");
            #endregion

            #region TestUser1 deletes the last created rule.
            ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForRemove, 0, RuleState.ST_ENABLED, delegateActionData, ruleProperties, ruleId);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Deleting the created rule should be success");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information to check if the last created rule is deleted.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Get rule table succeed and the rule count is 0, means the server is returning a table with no rule.
            Site.Assert.IsTrue(queryRowResponse.RowCount == 0, "The rule number in the rule table is {0}", queryRowResponse.RowCount);

            // Add the debug information.
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R14");

            // Verify MS-OXORULE requirement: MS-OXORULE_R14.
            // According to above steps, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                14,
                @"[In RopModifyRules ROP] The RopModifyRules ROP ([MS-OXCROPS] section 2.2.11.1) creates, modifies, or deletes rules (2) in a folder.");
            #endregion
        }
        public void MSOXORULE_S02_TC05_ServerExecuteRule_Action_OP_DELETE()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameCopy);
            #endregion

            #region TestUser1 creates a new folder in server store.
            RopCreateFolderResponse createFolderResponse;
            uint newFolderHandle = this.OxoruleAdapter.RopCreateFolder(this.InboxFolderHandle, Common.GenerateResourceName(this.Site, "User1Folder"), "TestForOP_COPY", out createFolderResponse);
            ulong newFolderId = createFolderResponse.FolderId;
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating folder operation should succeed.");
            #endregion

            #region Prepare rules' data.
            MoveCopyActionData moveCopyActionData = new MoveCopyActionData();

            // Get the created folder entry ID.
            ServerEID serverEID = new ServerEID(BitConverter.GetBytes(newFolderId));
            byte[] folderEId = serverEID.Serialize();

            // Get the store object's entry ID.
            byte[] storeEId = this.GetStoreObjectEntryID(StoreObjectType.Mailbox, this.Server, this.User1ESSDN);
            moveCopyActionData.FolderInThisStore = 1;
            moveCopyActionData.FolderEID = folderEId;
            moveCopyActionData.StoreEID = storeEId;
            moveCopyActionData.FolderEIDSize = (ushort)folderEId.Length;
            moveCopyActionData.StoreEIDSize = (ushort)storeEId.Length;
            RuleData ruleForCopy = AdapterHelper.GenerateValidRuleData(ActionType.OP_COPY, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, moveCopyActionData, ruleProperties, null);
            #endregion

            #region TestUser1 adds OP_COPY rule to the Inbox folder.
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForCopy });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Copy rule should succeed.");
            #endregion

            #region TestUser1 adds OP_DELETE rule for Inbox folder with rule Sequence set to 2.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelete);
            RuleData ruleForDelete = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELETE, TestRuleDataType.ForAdd, 2, RuleState.ST_ENABLED, new DeleteMarkReadActionData(), ruleProperties, null);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForDelete });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding the delete rule should succeed.");
            #endregion

            #region TestUser1 adds OP_FORWARD rule with rule sequence set to 3.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForward);
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block.
            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);

            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForAdd, 3, RuleState.ST_ENABLED, forwardActionData, ruleProperties, null);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed");
            #endregion

            #region Get the rule properties in the Inbox of TestUser1.
            RopGetRulesTableResponse ropGetRulesTableResponse = new RopGetRulesTableResponse();
            uint ruleTableHandler = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table operation should succeed.");

            PropertyTag[] propertyTags = new PropertyTag[2];

            // PidTagRuleFolderEntryId
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagRuleFolderEntryId;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypBinary;

            // PidTagRuleLevel
            propertyTags[1].PropertyId = (ushort)PropertyId.PidTagRuleLevel;
            propertyTags[1].PropertyType = (ushort)PropertyType.PtypInteger32;

            RopQueryRowsResponse ropQueryRowsResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandler, propertyTags);
            Site.Assert.AreEqual<uint>(0, ropQueryRowsResponse.ReturnValue, "Query rows operation should succeed.");

            // Three rules have been added to the Inbox folder, so the row count in the rule table should be 3.
            Site.Assert.AreEqual<uint>(3, ropQueryRowsResponse.RowCount, "The rule number in the rule table is {0}", ropQueryRowsResponse.RowCount);
            this.VerifyRuleTable();
            #endregion

            #region TestUser2 deliver a message to TestUser1 to trigger these rules
            // Wait for the mail to be received and the rule to take effect.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject);

            // Wait for the mail to be received and the rule to take effect.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser1 checks whether the origin message is deleted.
            // Set PidTagSubject and PidTagMessageFlags visible.
            PropertyTag[] propertyTag = new PropertyTag[2];
            propertyTag[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTag[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTag[1].PropertyId = (ushort)PropertyId.PidTagMessageFlags;
            propertyTag[1].PropertyType = (ushort)PropertyType.PtypInteger32;

            // Get mail message content.
            uint contentsTableHandle = 0;
            bool doesUnexpectedMessageExist = this.CheckUnexpectedMessageExist(this.InboxFolderHandle, ref contentsTableHandle, propertyTag, mailSubject);

            #region Capture Code
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R931");

            // Verify MS-OXORULE requirement: MS-OXORULE_R931.
            // In this test case, the server-side rule is OP_DELETE, and the actions specified in the PidTagRuleActions property associated with this rule is to delete the incoming message. 
            // TestUser2 has sent a message to TestUser1. If the message doesn't appear in TestUser1's mailbox, it means the server has deleted the incoming message. This requirement can be verified.
            Site.CaptureRequirementIfIsFalse(
                doesUnexpectedMessageExist,
                931,
                @"[In Processing Incoming Messages to a Folder] When executing a rule (2) whose condition evaluates to ""TRUE"" as per the restriction (2) in the PidTagRuleCondition property (section 2.2.1.3.1.9), then the server MUST perform the actions (2) specified in the PidTagRuleActions property (section 2.2.1.3.1.10) associated with that rule (2) in the case of a server-side rule.");

            if (Common.IsRequirementEnabled(898, this.Site))
            {
                // Add the debug information.
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R898");

                Site.CaptureRequirementIfIsFalse(
                    doesUnexpectedMessageExist,
                    898,
                    @"[In OP_DELETE or OP_MARK_AS_READ Data Buffer Format] For the OP_DELETE action type, the implementation does delete the incoming messages according to the ActionType itself. (Windows Exchange 2003 and above follow this behavior)");
            }

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R549");

            // Verify MS-OXORULE requirement: MS-OXORULE_R549.
            // TestUser2 has sent a message to TestUser1. If the message doesn't appear in TestUser1's mailbox, it means the server has deleted the incoming message. This requirement can be verified.
            Site.CaptureRequirementIfIsFalse(
                doesUnexpectedMessageExist,
                549,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELETE"": The server MUST delete the message.");

            #endregion
            #endregion

            #region TestUser2 checks whether a forward message is received.
            this.LogonMailbox(TestUser.TestUser2);
            bool doesUnexpectedMessageExist2 = this.CheckUnexpectedMessageExist(this.InboxFolderHandle, ref contentsTableHandle, propertyTag, mailSubject);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R550");

            // Verify MS-OXORULE requirement: MS-OXORULE_R550.
            // In this test case, if the forward message doesn't appear in TestUser2's mailbox, it means the subsequent OP_FORWARD rule, which is not an Out of Office rule, is not executed.
            Site.CaptureRequirementIfIsFalse(
                doesUnexpectedMessageExist2,
                550,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELETE"": The server MUST stop evaluating subsequent rules (2) on the message except for Out of Office rules.");
            #endregion

            #region Delete the newly created folder.
            this.LogonMailbox(TestUser.TestUser1);
            RopDeleteFolderResponse deleteFolder = this.OxoruleAdapter.RopDeleteFolder(this.InboxFolderHandle, newFolderId);
            Site.Assert.AreEqual<uint>(0, deleteFolder.ReturnValue, "Deleting folder should succeed.");
            #endregion
        }
        public void MSOXORULE_S01_TC07_AddForwardAndDelegateRules()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 prepares value for rule properties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForward);
            #endregion

            #region TestUser1 prepares the recipient block for Forward rules.
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            #region TestUser1 adds rule forward with ActionFlavor set to PR and NC.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };
            uint actionForwardFlavorNC_PR = (uint)ActionFlavorsForward.NC | (uint)ActionFlavorsForward.PR;

            RuleData ruleForward = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 100, RuleState.ST_ENABLED, forwardActionData, actionForwardFlavorNC_PR, ruleProperties);
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R276.");

            // Verify MS-OXORULE requirement: MS-OXORULE_R276.
            // If the ReturnValue of modifyRulesResponse response is 0x00000000, it means PR can be combined with the NC ActionFlavor flag.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000000,
                modifyRulesResponse.ReturnValue,
                276,
                @"[In Action Flavors] PR (Bitmask 0x00000001): Can be combined with the NC ActionFlavor flag.");
            #endregion

            #region TestUser1 adds rule forward with ActionFlavor set to AT.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForwardAT);
            ForwardDelegateActionData forwardActionDataAT = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };
            RuleData ruleForwardAT = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 100, RuleState.ST_ENABLED, forwardActionDataAT, (uint)ActionFlavorsForward.AT, ruleProperties);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForwardAT });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 adds rule forward with ActionFlavor set to TM.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForwardTM);
            ForwardDelegateActionData forwardActionDataTM = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };
            RuleData ruleForwardTM = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 100, RuleState.ST_ENABLED, forwardActionDataTM, (uint)ActionFlavorsForward.TM, ruleProperties);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForwardTM });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 adds rule DELEGATE.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelegate);
            ForwardDelegateActionData delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };

            #region Prepare the Delegate rule Recipient block.
            RecipientBlock delegateRecipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };
            TaggedPropertyValue[] delegateRecipientProperties = new TaggedPropertyValue[5];

            TaggedPropertyValue[] tempArray = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(tempArray, 0, delegateRecipientProperties, 0, tempArray.Length);

            // Add PidTagSmtpEmailAdderss
            delegateRecipientProperties[4] = new TaggedPropertyValue();
            PropertyTag delegateRecipientPropertiesPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            delegateRecipientProperties[4].PropertyTag = delegateRecipientPropertiesPropertyTag;
            delegateRecipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            delegateRecipientBlock.PropertiesData = delegateRecipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { delegateRecipientBlock };
            RuleData ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Delegate rule should succeed.");
            #endregion

            #region TestUser1 gets ruleActions of the four rules.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");

            PropertyTag actionsTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagRuleActions,
                PropertyType = (ushort)PropertyType.PtypRuleAction
            };

            // Set the query target to standardardRules.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForStandardRules;

            RopQueryRowsResponse getAllActionsResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, new PropertyTag[1] { actionsTag });
            Site.Assert.AreEqual<uint>(0, getAllActionsResponse.ReturnValue, "Getting the rule actions should succeed.");

            // Four rules have been added to the Inbox folder, so the row count in the rule table should be 4.
            Site.Assert.AreEqual<uint>(4, getAllActionsResponse.RowCount, "The rule number in the rule table is {0}", getAllActionsResponse.RowCount);
            this.VerifyRuleTable();

            // Clear the status of the adapter.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.OtherTarget;
            #endregion
        }
        public void MSOXORULE_S02_TC17_ServerExecuteRule_ForwardAsAttachment()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForwardAT);
            #endregion

            #region TestUser1 adds a rule for ActionType with OP_Forward ActionFlavor set to AT.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block of the rule to forward the message to TestUser2.
            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;

            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForwardAT = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 0, RuleState.ST_ENABLED, forwardActionData, (uint)ActionFlavorsForward.AT, ruleProperties);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForwardAT });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed.");
            #endregion

            #region TestUser1 delivers a message to itself to trigger the rule.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser1 delivers a message to itself to trigger the rule.
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.SUTAdapter.SendMailToRecipient(this.User1Name, this.User1Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser2 gets the forwarded message to verify the rule evaluation.

            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);
            PropertyTag[] propertyTagList = new PropertyTag[3];

            // pidTagSubject and pidTagMessageClass
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagMessageClass;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[2].PropertyId = (ushort)PropertyId.pidTagHasAttachment;
            propertyTagList[2].PropertyType = (ushort)PropertyType.PtypBoolean;
            uint contentsTableHandle = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse testUser2getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref expectedMessageIndex, mailSubject);
            Site.Assert.AreEqual<uint>(0, testUser2getNormalMailMessageContent.ReturnValue, "Getting message property operation should succeed.");

            mailSubject = AdapterHelper.PropertyValueConvertToString(testUser2getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value);
            byte[] hasAttachment = testUser2getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value;

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R279");

            // Verify MS-OXORULE requirement: MS-OXORULE_R279
            bool isVerifiedR279 = hasAttachment.Length == 1 && hasAttachment[0] == 1;

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR279,
                279,
                @"[In Action Flavors] AT (Bitmask 0x00000004): Forwards the message as an attachment.");
            #endregion
        }
        public void MSOXORULE_S02_TC12_ServerExecuteRules_InOrder()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForward);
            #endregion

            #region TestUser1 adds a rule for ActionType OP_Forward with rule sequence set to 1.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block.
            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);

            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, forwardActionData, ruleProperties, null);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed.");
            #endregion

            #region TestUser1 adds a delete rule for Inbox folder with rule Sequence set to 100.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelete);
            RuleData ruleForDelete = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELETE, TestRuleDataType.ForAdd, 100, RuleState.ST_ENABLED, new DeleteMarkReadActionData(), ruleProperties, null);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForDelete });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Delete rule should succeed.");
            #endregion

            #region TestUser1 gets rule table.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table Should succeed");
            #endregion

            #region TestUser1 retrieves rule information for the newly added rule.
            PropertyTag[] propertyTags = new PropertyTag[]
            {
                new PropertyTag
                {
                    PropertyId = (ushort)PropertyId.PidTagRuleName,
                    PropertyType = (ushort)PropertyType.PtypString
                }
            };

            // Retrieve rows from the rule table.
            RopQueryRowsResponse queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Two rules have been added to the Inbox folder, so the row count in the rule table should be 2.
            Site.Assert.AreEqual<uint>(2, queryRowResponse.RowCount, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            this.VerifyRuleTable();

            #region Capture Code
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R778");

            // Add two rules to the Inbox folder. If the rule table is got successfully and the rule count is 2,
            // it means that the server had stored all previously created rules.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                queryRowResponse.RowCount,
                778,
                @"[In Returning and Maintaining the Rules Table] When a user creates or modifies a rule using the RopModifyRules ROP request ([MS-OXCROPS] section 2.2.11.1), the server MUST store this and all previously created rules.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R779: the row count of the rule table is {0}", queryRowResponse.RowCount);

            // Add two rules to the Inbox folder. If the rule table is got successfully and the rule count is 2. This requirement can be verified.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                queryRowResponse.RowCount,
                779,
                @"[In Returning and Maintaining the Rules Table] [When a user creates or modifies a rule using the RopModifyRules ROP request ([MS-OXCROPS] section 2.2.11.1)] The server MUST also respond to a RopGetRulesTable ROP request ([MS-OXCROPS] section 2.2.11.2) by returning these rules to the client in the form of a rules table.");
            #endregion
            #endregion

            #region TestUser1 delivers a message to itself to trigger these rules.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser1 delivers a message to itself to trigger these rules.
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.SUTAdapter.SendMailToRecipient(this.User1Name, this.User1Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser1 gets the messages in the Inbox to verify the rule evaluation.
            PropertyTag[] propertyTagList = new PropertyTag[2];

            // pidTagSubject and pidTagMessageClass
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagMessageClass;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;
            uint contentsTableHandle = 0;
            bool doesUnexpectedMessageExist = this.CheckUnexpectedMessageExist(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, mailSubject);
            #endregion

            #region TestUser2 gets the forwarded message to verify the rule evaluation.
            // Let Testuser2 to logon to the server
            this.LogonMailbox(TestUser.TestUser2);
            uint contentTableHandler = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse testUser2getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandler, propertyTagList, ref expectedMessageIndex, mailSubject);
            Site.Assert.AreEqual<uint>(0, testUser2getNormalMailMessageContent.ReturnValue, "Getting message property operation should succeed.");

            string testUser2mailSubject = AdapterHelper.PropertyValueConvertToString(testUser2getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R514, the value of mailSubject is {0}", testUser2mailSubject);

            // Verify MS-OXORULE requirement: MS-OXORULE_R514.
            // This test case has added 2 rules (OP_FORWARD and OP_DELETE) in increasing order of the value of the PidTagRuleSequence property.
            // According to this order, OP_FORWARD should be performed before OP_DELETE.
            // If there is a message existing under the forwarded recipient's Inbox folder, whose subject name contains the original received message's subject name,
            // it means the server has forwarded the message to the corresponding recipient before executing the OP_DELETE rule.
            // If the RowCount of getMailMessageContent equals 0, it means the original received message under the administrator's Inbox folder
            // has been deleted. So it proves the server evaluates each rule in the increasing order.
            bool isVerifyR514 = testUser2mailSubject.ToUpperInvariant().Contains(mailSubject.ToUpperInvariant()) && !doesUnexpectedMessageExist;
            Site.CaptureRequirementIfIsTrue(
                isVerifyR514,
                514,
                @"[In Processing Incoming Messages to a Folder] For each message delivered to a folder, the server evaluates each rule (2) in that folder in increasing order of the value of the PidTagRuleSequence property (section 2.2.1.3.1.2) in each rule (2).");
            #endregion
        }
        public void MSOXORULE_S02_TC08_ServerExecuteRule_Action_OP_DELEGATE()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameDelegate);
            #endregion

            #region TestUser1 adds an OP_DELEGATE rule.
            ForwardDelegateActionData delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };

            #region Prepare recipient Block.
            TaggedPropertyValue[] recipientProperties = new TaggedPropertyValue[5];

            TaggedPropertyValue[] temp = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(temp, 0, recipientProperties, 0, temp.Length);

            // Add PidTagSmtpEmailAdderss.
            recipientProperties[4] = new TaggedPropertyValue();
            PropertyTag pidTagSmtpEmailAdderssPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            recipientProperties[4].PropertyTag = pidTagSmtpEmailAdderssPropertyTag;
            recipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding delegate rule should succeed.");
            #endregion

            #region TestUser1 delivers a message to itself to trigger the rule.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser1 delivers a message to itself to trigger the rule.
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.SUTAdapter.SendMailToRecipient(this.User1Name, this.User1Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser2 gets the delegate message to verify the rule evaluation.
            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);

            PropertyTag[] propertyTagList = new PropertyTag[7];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagReceivedRepresentingEntryId;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypBinary;
            propertyTagList[2].PropertyId = (ushort)PropertyId.PidTagReceivedRepresentingAddressType;
            propertyTagList[2].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[3].PropertyId = (ushort)PropertyId.PidTagReceivedRepresentingEmailAddress;
            propertyTagList[3].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[4].PropertyId = (ushort)PropertyId.PidTagReceivedRepresentingName;
            propertyTagList[4].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[5].PropertyId = (ushort)PropertyId.PidTagReceivedRepresentingSearchKey;
            propertyTagList[5].PropertyType = (ushort)PropertyType.PtypBinary;
            propertyTagList[6].PropertyId = (ushort)PropertyId.PidTagDelegatedByRule;
            propertyTagList[6].PropertyType = (ushort)PropertyType.PtypBoolean;

            uint contentTableHandler = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandler, propertyTagList, ref expectedMessageIndex, mailSubject);
            #endregion

            #region Get TestUser1's information from address book

            // Let TestUser1 log on to the server.
            this.LogonMailbox(TestUser.TestUser1);

            PropertyTagArray_r ptags = new PropertyTagArray_r
            {
                Values = 5,
                AulPropTag = AdapterHelper.SerializeRecipientProperties()
            };

            // The Windows NSPI will be invoked when the first parameter is domain name instead of server address.
            PropertyRowSet_r? propertyRows = this.OxoruleAdapter.GetRecipientInfo(this.Domain, this.User1Name, this.Domain, this.User1Password, ptags);
            Site.Assert.IsNotNull(propertyRows, "The recipient information returned by the NSPI service should not be null");
            int user1Index = 0;
            for (int i = 0; i < propertyRows.Value.Rows; i++)
            {
                if (Encoding.Unicode.GetString(propertyRows.Value.PropertyRowSet[i].Props[3].Value.LpszW).ToLower(System.Globalization.CultureInfo.CurrentCulture) == this.User1Name.ToLower(System.Globalization.CultureInfo.CurrentCulture))
                {
                    user1Index = i;
                    break;
                }
            }

            // The two EntryId should be the same.
            AddressBookEntryID addressbookEntryId = new AddressBookEntryID();
            addressbookEntryId.Deserialize(propertyRows.Value.PropertyRowSet[user1Index].Props[0].Value.Bin.Lpb);
            byte[] pidTagReceivedRepresentingEntryIdbytesTemp = getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[1].Value;
            byte[] pidTagReceivedRepresentingEntryIdbytes = new byte[pidTagReceivedRepresentingEntryIdbytesTemp.Length - 2];
            Array.Copy(pidTagReceivedRepresentingEntryIdbytesTemp, 2, pidTagReceivedRepresentingEntryIdbytes, 0, pidTagReceivedRepresentingEntryIdbytes.Length);
            AddressBookEntryID mailEntryID = new AddressBookEntryID();
            mailEntryID.Deserialize(pidTagReceivedRepresentingEntryIdbytes);
            string subject = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value);

            #region Capture Code
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R539");

            // Verify MS-OXORULE requirement: MS-OXORULE_R539.
            Site.CaptureRequirementIfAreEqual<string>(
                mailSubject,
                subject,
                539,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": the server MUST resend the message to the recipients (2) specified in the action buffer structure.");

            string pidTagEntryIdOfMailboxUser = addressbookEntryId.ValueOfX500DN.ToLower(System.Globalization.CultureInfo.CurrentCulture);
            string pidTagReceivedRepresentingEntryId = mailEntryID.ValueOfX500DN.ToLower(System.Globalization.CultureInfo.CurrentCulture);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R540");

            // Verify MS-OXORULE requirement: MS-OXORULE_R540.
            Site.CaptureRequirementIfAreEqual<string>(
                pidTagReceivedRepresentingEntryId,
                pidTagEntryIdOfMailboxUser,
                540,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": The server also MUST set the values of the following properties to match the current user's properties in the address book: The PidTagReceivedRepresentingEntryId property ([MS-OXOMSG] section 2.2.1.25) MUST be set to the same value as the mailbox user's PidTagEntryId property ([MS-OXOABK] section 2.2.3.3).");

            string pidTagReceivedRepresentingAddressType = Encoding.Unicode.GetString(getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value);

            // The actual value of pidTagReceivedRepresentingAddressType should not contain the last '\0' character.
            pidTagReceivedRepresentingAddressType = pidTagReceivedRepresentingAddressType.Substring(0, pidTagReceivedRepresentingAddressType.Length - 1);

            // In this test case, the mailbox user's PidTagAddressType is "EX".
            string pidTagAddressTypeOfMailboxUser = System.Text.UTF8Encoding.Unicode.GetString(propertyRows.Value.PropertyRowSet[user1Index].Props[1].Value.LpszW);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R541");

            // Verify MS-OXORULE requirement: MS-OXORULE_R541.
            Site.CaptureRequirementIfAreEqual<string>(
                pidTagReceivedRepresentingAddressType,
                pidTagAddressTypeOfMailboxUser,
                541,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": The PidTagReceivedRepresentingAddressType property ([MS-OXOMSG] section 2.2.1.23) MUST be set to the same value as the mailbox user's PidTagAddressType property ([MS-OXOABK] section 2.2.3.13).");

            string pidTagReceivedRepresentingEmailAddress = Encoding.Unicode.GetString(getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[3].Value);

            // The actual value of PidTagReceivedRepresentingEmailAddress should not contain the last '\0' character.
            pidTagReceivedRepresentingEmailAddress = pidTagReceivedRepresentingEmailAddress.Substring(0, pidTagReceivedRepresentingEmailAddress.Length - 1).ToUpperInvariant();

            // In this test case, the mailbox user's PidTagEmailAddress is the adminUserDN.
            string pidTagEmailAddressOfMailboxUser = Encoding.Unicode.GetString(propertyRows.Value.PropertyRowSet[user1Index].Props[2].Value.LpszW).ToUpperInvariant();

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R542");

            // Verify MS-OXORULE requirement: MS-OXORULE_R542.
            Site.CaptureRequirementIfAreEqual<string>(
                pidTagReceivedRepresentingEmailAddress,
                pidTagEmailAddressOfMailboxUser,
                542,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": The PidTagReceivedRepresentingEmailAddress property ([MS-OXOMSG] section 2.2.1.24) MUST be set to the same value as the mailbox user's PidTagEmailAddress property ([MS-OXOABK] section 2.2.3.14).");

            string pidTagReceivedRepresentingName = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[4].Value).ToLower(System.Globalization.CultureInfo.CurrentCulture);

            // In this test case, the mailbox user's PidTagDisplayName is "administrator".
            string pidTagDisplayNameOfMailboxUser = Encoding.Unicode.GetString(propertyRows.Value.PropertyRowSet[user1Index].Props[3].Value.LpszW).ToLower(System.Globalization.CultureInfo.CurrentCulture);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R543");

            // Verify MS-OXORULE requirement: MS-OXORULE_R543.
            Site.CaptureRequirementIfAreEqual<string>(
                pidTagReceivedRepresentingName,
                pidTagDisplayNameOfMailboxUser,
                543,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": The PidTagReceivedRepresentingName property ([MS-OXOMSG] section 2.2.1.26) MUST be set to the same value as the mailbox user's PidTagDisplayName property ([MS-OXCFOLD] section 2.2.2.2.2.5).");

            byte[] pidTagReceivedRepresentingSearchKeyOfbytes = getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[5].Value;
            byte[] pidTagReceivedRepresentingSearchKey = AdapterHelper.PropertyValueConvertToBinary(pidTagReceivedRepresentingSearchKeyOfbytes);
            byte[] pidTagSearchKeyOfMailboxUser = propertyRows.Value.PropertyRowSet[user1Index].Props[4].Value.Bin.Lpb;

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R544: the value of PidTagReceivedRepresentingSearchKey is {0}", pidTagSearchKeyOfMailboxUser);

            // Verify MS-OXORULE requirement: MS-OXORULE_R544.
            bool isVerifyR544 = Common.CompareByteArray(pidTagSearchKeyOfMailboxUser, pidTagReceivedRepresentingSearchKey);

            Site.CaptureRequirementIfIsTrue(
                isVerifyR544,
                544,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": The PidTagReceivedRepresentingSearchKey property ([MS-OXOMSG] section 2.2.1.27) MUST be set to the same value as the mailbox user's PidTagSearchKey property ([MS-OXCPRPT] section 2.2.1.9).");

            // BitConverter.ToBoolean() is used to convert a byte array to a bool value from the byte array index of 0.
            bool pidTagDelegatedByRule = BitConverter.ToBoolean(getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[6].Value, 0);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R545");

            // Verify MS-OXORULE requirement: MS-OXORULE_R545.
            Site.CaptureRequirementIfIsTrue(
                pidTagDelegatedByRule,
                545,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_DELEGATE"": The PidTagDelegatedByRule property ([MS-OXOMSG] section 2.2.1.84) MUST be set to ""TRUE"".");

            #endregion
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.

            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 calls RopQueryRows to retrieve rows from the rule table

            PropertyTag[] propertyTags = new PropertyTag[2];
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagRuleName;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTags[1].PropertyId = (ushort)PropertyId.PidTagRuleActions;
            propertyTags[1].PropertyType = (ushort)PropertyType.PtypRuleAction;

            // Retrieves rows from the rule table.
            RopQueryRowsResponse queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");
            ForwardDelegateActionData forwardDelegateActionDataOfQueryRowResponse = new ForwardDelegateActionData();
            RuleAction ruleAction = new RuleAction();
            for (int i = 0; i < queryRowResponse.RowCount; i++)
            {
                System.Text.UnicodeEncoding converter = new UnicodeEncoding();
                string ruleName = converter.GetString(queryRowResponse.RowData.PropertyRows.ToArray()[i].PropertyValues[0].Value);
                if (ruleName == ruleProperties.Name + "\0")
                {
                    // Verify structure RuleAction 
                    ruleAction.Deserialize(queryRowResponse.RowData.PropertyRows[i].PropertyValues[1].Value);
                    forwardDelegateActionDataOfQueryRowResponse.Deserialize(ruleAction.Actions[0].ActionDataValue.Serialize());
                    break;
                }
            }

            #region Capture Code

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1003");

            // Verify MS-OXORULE requirement: MS-OXORULE_R1003
            this.Site.CaptureRequirementIfIsInstanceOfType(
                forwardDelegateActionDataOfQueryRowResponse.RecipientsData,
                typeof(RecipientBlock[]),
                1003,
                @"[In OP_FORWARD and OP_DELEGATE ActionData Structure] RecipientBlocks (variable): An array of RecipientBlockData structures, each of which specifies information about one recipient (2).");

            for (int i = 0; i < forwardDelegateActionDataOfQueryRowResponse.RecipientsData.Length; i++)
            {
                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1006");

                // Verify MS-OXORULE requirement: MS-OXORULE_R1006
                this.Site.CaptureRequirementIfIsInstanceOfType(
                    forwardDelegateActionDataOfQueryRowResponse.RecipientsData[i].PropertiesData,
                    typeof(TaggedPropertyValue[]),
                    1006,
                    @"[In RecipientBlockData Structure] PropertyValues (variable): An array of TaggedPropertyValue structures, each of which contains a property that provides some information about the recipient (2).");
            }
            #endregion
            #endregion
        }
        public void MSOXORULE_S02_TC07_ServerExecuteRule_Action_OP_FORWARD()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForwardTM);
            #endregion

            #region TestUser1 adds a rule for ActionType with OP_Forward ActionFlavor set to TM and rule sequence set to 0.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block of the rule to forward the message to TestUser2.
            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;

            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForwardTM = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 0, RuleState.ST_ENABLED, forwardActionData, (uint)ActionFlavorsForward.TM, ruleProperties);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForwardTM });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed.");
            #endregion

            #region TestUser2 adds a rule for ActionType OP_Forward with rule sequence set to 0.
            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);
            forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block of the rule to forward the message to TestUser1.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForward);
            recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User1Name, this.User1ESSDN);

            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, forwardActionData, ruleProperties, null);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed.");
            #endregion

            #region TestUser1 delivers a message to itself to trigger these rules.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser1 delivers a message to itself to trigger these rules.
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title", 1);
            this.SUTAdapter.SendMailToRecipient(this.User1Name, this.User1Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser2 gets the forwarded message to verify the rule evaluation.
            PropertyTag[] propertyTagList = new PropertyTag[2];

            // pidTagSubject and pidTagMessageClass
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagMessageClass;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;
            uint contentsTableHandle = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse testUser2getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref expectedMessageIndex, mailSubject);
            Site.Assert.AreEqual<uint>(0, testUser2getNormalMailMessageContent.ReturnValue, "Getting message property operation should succeed.");

            string subject = AdapterHelper.PropertyValueConvertToString(testUser2getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value);
            byte[] propertyValue = testUser2getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[1].Value;

            #region Capture Code
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R537");

            // Verify MS-OXORULE requirement: MS-OXORULE_R537.
            // The subject name of the forwarded message should contain the original received message's subject name. 
            bool isVerifiedR537 = subject.ToUpperInvariant().Contains(mailSubject.ToUpperInvariant());

            // If there exists a message under the recipient's Inbox folder, whose subject name contains the original received message's subject name,
            // it means the server has forwarded the message to the corresponding recipient.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR537,
                537,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_FORWARD"": The server MUST forward the message to the recipients (2) specified in the action buffer structure (except for messages forwarded to the sender).");

            if (Common.IsRequirementEnabled(802, this.Site))
            {
                // Add the debug information.
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R802: the value of PidTagSubject is {0}, and the value of PidTagMessageClass is {1}", mailSubject, AdapterHelper.PropertyValueConvertToString(propertyValue));

                // If there exists a message under the recipient's Inbox folder, whose subject name contains the original received message's subject name,
                // it means the server has forwarded the message to the corresponding recipient, and for SMS text messages, the value of the PidTagMessageClass property is set to "IPM.Note.Mobil.SMS.Alert". 
                bool isVerify802 = subject.ToUpperInvariant().Contains(mailSubject.ToUpperInvariant()) && !AdapterHelper.PropertyValueConvertToString(propertyValue).Equals("IPM.Note.Mobil.SMS.Alert");

                // Verify MS-OXORULE requirement: MS-OXORULE_R802.
                Site.CaptureRequirementIfIsTrue(
                    isVerify802,
                    802,
                    @"[In Appendix A: Product Behavior] Implementation does not support forwarding messages as SMS text messages. [<5> Section 2.2.5.1.1: Exchange 2003 and Exchange 2007 do not support forwarding messages as SMS text messages.]");
            }

            if (Common.IsRequirementEnabled(897, this.Site))
            {
                // Add the debug information.
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R897: the PidTagMessageClass of the message is {0}", AdapterHelper.PropertyValueConvertToString(propertyValue));

                // If there exists a message under the recipient's Inbox folder, whose subject name contains the original received message's subject name,
                // it means the server has forwarded the message to the corresponding recipient, and for SMS text messages, the value of the PidTagMessageClass property is set to "IPM.Note.Mobil.SMS.Alert". 
                bool isVerify897 = subject.ToUpperInvariant().Contains(mailSubject.ToUpperInvariant()) && AdapterHelper.PropertyValueConvertToString(propertyValue).Equals("IPM.Note.Mobile.SMS.Alert");

                // Verify MS-OXORULE requirement: MS-OXORULE_R897.
                Site.CaptureRequirementIfIsTrue(
                    isVerify897,
                    897,
                    @"[In Action Flavors] TM (Bitmask 0x00000008): Implementation does forward the message as a Short Message Service (SMS) text message. (Exchange 2010 and above follow this behavior.)");
            }
            #endregion
            #endregion

            #region TestUser1 get the forwarded message to verify the rule evaluation.
            // Let TestUser1 log on to the server.
            this.LogonMailbox(TestUser.TestUser1);

            #region Capture Code
            if (Common.IsRequirementEnabled(799, this.Site))
            {
                // The subject name of the forwarded message should contain the original received message's subject name. 
                uint countOfExepctedMessage = 0;
                RopQueryRowsResponse testUser1getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref countOfExepctedMessage, 2, mailSubject);
                Site.Assert.AreEqual<uint>(0, testUser1getNormalMailMessageContent.ReturnValue, "Getting message property operation should succeed.");

                // Add the debug information.
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R799");

                // Verify MS-OXORULE requirement: MS-OXORULE_R799.
                // If test user2 has forwarded the message that has been forwarded to the test user1, there should be two expected messages in the test user1's Inbox folder.
                Site.CaptureRequirementIfAreEqual<uint>(
                    2,
                    countOfExepctedMessage,
                    799,
                    @"[In Appendix A: Product Behavior] Implementation does forward messages that have been forwarded to the sender. [<17> Section 3.2.5.1: Exchange 2007 forwards messages that have been forwarded to the sender.]");
            }

            if (Common.IsRequirementEnabled(907, this.Site))
            {
                // The subject name of the forwarded message should contain the original received message's subject name. 
                uint countOfExepctedMessage = 0;
                RopQueryRowsResponse testUser1getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref countOfExepctedMessage, 1, mailSubject);
                Site.Assert.AreEqual<uint>(0, testUser1getNormalMailMessageContent.ReturnValue, "Getting message property operation should succeed.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R907");

                // Verify MS-OXORULE requirement: MS-OXORULE_R907
                // If test user2 has not forwarded the message that has been forwarded to the test user1, there should be only one expected message in the test user1's Inbox folder.
                Site.CaptureRequirementIfAreEqual<uint>(
                    1,
                    countOfExepctedMessage,
                    907,
                    @"[In Processing Incoming Messages to a Folder] Implementation does not forward messages that were forwarded to the sender. (Exchange 2003, Exchange 2010 and above follow this behavior.)");
            }
            #endregion
            #endregion

            #region TestUser1 adds a rule for ActionType OP_Forward with OP_Forward ActionFlavor set to PR.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForward);
            forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block of the rule to forward the message to TestUser2.
            recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);

            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForwardPR = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 0, RuleState.ST_ENABLED, forwardActionData, (uint)ActionFlavorsForward.PR, ruleProperties);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForwardPR });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed.");
            #endregion

            #region TestUser2 deletes the previous rule and clean the Inbox folder.
            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);

            // Call RopGetRulesTable with valid TableFlags.
            this.ClearAllRules();

            // Clean all the contents in the Inbox folder of TestUser2.
            this.OxoruleAdapter.RopEmptyFolder(this.InboxFolderHandle, 0);
            #endregion

            #region TestUser1 delivers a message to itself to trigger these rules.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser1 to deliver a message to itself to trigger these rules
            mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title", 2);
            this.SUTAdapter.SendMailToRecipient(this.User1Name, this.User1Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser2 gets the forwarded message to verify the rule evaluation.
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagAutoForwarded;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypBoolean;
            expectedMessageIndex = 0;
            testUser2getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref expectedMessageIndex, mailSubject);
            Site.Assert.AreEqual<uint>(0, testUser2getNormalMailMessageContent.ReturnValue, "Getting message property operation should succeed.");
            bool isAutoForwarded = AdapterHelper.PropertyValueConvertToBool(testUser2getNormalMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[1].Value);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R275: The expected message with subject {0} in TestUser2 inbox has the auto forwarded property set to {1}", mailSubject, isAutoForwarded);

            // If there exists a message under the recipient's Inbox folder
            // it means the server has forwarded the message to the corresponding recipient, and if the value of the PidTagAutoForwarded property is set to "true", means it is autoforwards.
            bool isVerify275 = isAutoForwarded;

            // Verify MS-OXORULE requirement: MS-OXORULE_R275
            Site.CaptureRequirementIfIsTrue(
                isVerify275,
                275,
                @"[In Action Flavors] PR (Bitmask 0x00000001): Preserves the sender information and indicates that the message was auto forwarded.");
            #endregion
        }
        public void MSOXORULE_S03_TC02_OOFBehaviorsExecuteSubRuleWithST_ONLY_WHEN_OOFForST_EXIT_LEVEL()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameTag);
            string setOOFMailAddress = this.User1Name + "@" + this.Domain;
            string userPassword = this.User1Password;
            #endregion

            #region Set TestUser1 to OOF state.
            bool isSetOOFSuccess = this.SUTSetOOFAdapter.SetUserOOFSettings(setOOFMailAddress, userPassword, true);
            Site.Assert.IsTrue(isSetOOFSuccess, "Turn Out of Office on for {0} should succeed.", this.User1Name);
            Thread.Sleep(this.WaitForSetOOFComplete);
            #endregion

            #region TestUser1 adds an OP_TAG rule with PidTagRuleState set to ST_ENABLED | ST_EXIT_LEVEL.
            TagActionData tagActionData = new TagActionData();
            PropertyTag tagActionDataPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagImportance,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            tagActionData.PropertyTag = tagActionDataPropertyTag;
            tagActionData.PropertyValue = BitConverter.GetBytes(2);

            RuleData ruleOpTag = AdapterHelper.GenerateValidRuleData(ActionType.OP_TAG, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED | RuleState.ST_EXIT_LEVEL, tagActionData, ruleProperties, null);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleOpTag });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding OP_TAG rule should succeed");
            #endregion

            #region TestUser1 adds OP_MARK_AS_READ rule with PidTagRuleState set to ST_ENABLED | ST_ONLY_WHEN_OOF.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameMarkAsRead);

            RuleData ruleForMarkRead = AdapterHelper.GenerateValidRuleData(ActionType.OP_MARK_AS_READ, TestRuleDataType.ForAdd, 2, RuleState.ST_ENABLED | RuleState.ST_ONLY_WHEN_OOF, new DeleteMarkReadActionData(), ruleProperties, null);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForMarkRead });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Mark as read rule should succeed.");
            #endregion

            #region TestUser2 delivers a message to TestUser1 to trigger these rules.
            // Sleep enough time to wait for the rule to take effect.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName, 1);
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject);

            // Sleep enough time to wait for the rule to be executed on the delivered message.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region Testuser1 verifies whether the specific property value is set on the received mail.
            PropertyTag[] propertyTagList = new PropertyTag[3];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[2].PropertyId = (ushort)PropertyId.PidTagMessageFlags;
            propertyTagList[2].PropertyType = (ushort)PropertyType.PtypInteger32;

            uint contentsTableHandle = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse getMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref expectedMessageIndex, mailSubject);

            // If the PidTagImportance is the value which is set on OP_TAG rule, it means the rule tacks action and the rule sets the property specified in the rule's action buffer structure.
            Site.Assert.AreEqual<int>(2, BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0), "The value of PidTagImportance field should be the specific value set by the client.");
            #endregion

            #region Testuser1 verifies whether the received mail is marked as read.
            int messageFlags = 0;
            bool isSubjectContainsRuleConditionSubject = false;
            if (getMailMessageContent.RowCount != 0)
            {
                isSubjectContainsRuleConditionSubject = true;
                messageFlags = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value, 0);
            }

            #region Capture Code
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R807, the value of markAsReadFlag is {0}", messageFlags);

            // Verify MS-OXORULE requirement: MS-OXORULE_R807.
            // messageFlags indicates whether the mail is marked as read. 
            // 0x00000001 is the bit which indicates the message has been marked as read. So if this bit is set in messageFlags,
            // it means the message is marked as read, which means the rule has been executed.
            bool isVerifyR807 = isSubjectContainsRuleConditionSubject && (messageFlags & 0x00000001) == 0x00000001;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR807,
                807,
                @"[In Interaction Between ST_ONLY_WHEN_OOF and ST_EXIT_LEVEL Flags] Subsequent rules (2) that have the ST_ONLY_WHEN_OOF flag set MUST be evaluated.");

            // When is not mark as read, it means rule evaluation will not terminate.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R858");

            // Verify MS-OXORULE requirement: MS-OXORULE_R858
            // If the message is marked as read, it means the rule evaluation is not terminate.
            Site.CaptureRequirementIfAreEqual<int>(
                1,
                messageFlags & 1,
                858,
                "[In PidTagRuleState Property] EL (ST_EXIT_LEVEL, Bitmask 0x00000010): rule (2) evaluation will not terminate after executing this rule (2) if for evaluation of Out of Office rules.");

            #endregion
            #endregion

            #region Set TestUser1 back to normal state (not in OOF state).
            isSetOOFSuccess = this.SUTSetOOFAdapter.SetUserOOFSettings(setOOFMailAddress, userPassword, false);
            Site.Assert.IsTrue(isSetOOFSuccess, "Turn Out of Office off for {0} should succeed.", this.User1Name);
            Thread.Sleep(this.WaitForSetOOFComplete);
            #endregion

            #region TestUser1 adds an OP_Forward rule with rule sequence set to 2.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForward);
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            #region Prepare the recipient Block of the rule to forward the message to TestUser2.
            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;

            #endregion

            forwardActionData.RecipientsData = new RecipientBlock[1] { recipientBlock };
            RuleData ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForAdd, 2, RuleState.ST_ENABLED, forwardActionData, ruleProperties, null);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding Forward rule should succeed.");
            #endregion

            #region TestUser2 delivers a message to TestUser1 to trigger these rules.
            mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName, 2);
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject);

            // Sleep enough time to wait for the rule to be executed on the delivered message.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            #endregion

            #region Testuser1 verifies whether the specific property value is set on the received mail.
            PropertyTag[] propertyTagListInNormal = new PropertyTag[3];
            propertyTagListInNormal[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagListInNormal[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagListInNormal[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagListInNormal[1].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagListInNormal[2].PropertyId = (ushort)PropertyId.PidTagMessageFlags;
            propertyTagListInNormal[2].PropertyType = (ushort)PropertyType.PtypInteger32;

            uint contentTableHandlerNormal = 0;
            expectedMessageIndex = 0;
            RopQueryRowsResponse getMailMessageContentNormal = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandlerNormal, propertyTagListInNormal, ref expectedMessageIndex, mailSubject);

            // If the PidTagImportance is the value which is set on OP_TAG rule, it means the rule tacks action and the rule sets the property specified in the rule's action buffer structure.
            Site.Assert.AreEqual<int>(2, BitConverter.ToInt32(getMailMessageContentNormal.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0), "The value of PidTagImportance field should be the specific value set by the client.");
            #endregion

            #region Testuser1 verifies whether the received mail is marked as read.
            bool isSubjectContainsRuleConditionSubjectNormal = false;
            int messageFlagsNormal = 0;
            string mailSubjectNormal = AdapterHelper.PropertyValueConvertToString(getMailMessageContentNormal.RowData.PropertyRows[expectedMessageIndex].PropertyValues[1].Value);
            if (mailSubjectNormal.Contains(mailSubject))
            {
                isSubjectContainsRuleConditionSubjectNormal = true;
                messageFlagsNormal = BitConverter.ToInt32(getMailMessageContentNormal.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value, 0);
            }

            // Verify MS-OXORULE requirement: MS-OXORULE_R67.
            // If the message is marked as read means the execution of the OOF rule was done by the OOF user. 
            bool isExcuted = (messageFlags & 0x00000001) == 0x00000001;

            // If the message is not marked as read, it means the execution of the OOF rule was not done by the normal user.  
            bool isNotExcute = isSubjectContainsRuleConditionSubjectNormal && (messageFlagsNormal & 0x00000001) != 0x00000001;

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R67: the value of markAsReadFlag for OOF user is {0}, and for normal user is {0}", messageFlags, messageFlagsNormal);

            // Indicate whether the OOF rule is executed by the OOF user.
            bool isVerify67 = isExcuted && isNotExcute == true;

            Site.CaptureRequirementIfIsTrue(
                isVerify67,
                67,
                "[In PidTagRuleState] OF (ST_ONLY_WHEN_OOF, Bitmask 0x00000004): The rule (2) is executed only when a user sets the Out of Office (OOF) state on the mailbox, as specified in [MS-OXWOOF] section 2.2.5.2.");
            #endregion

            #region TestUser2 Verifies whether the OP_Forward rule is executed.
            // Let TestUser2 logon to the server.
            this.LogonMailbox(TestUser.TestUser2);

            bool doesUnexpectedMessageExist = this.CheckUnexpectedMessageExist(this.InboxFolderHandle, ref contentTableHandlerNormal, propertyTagListInNormal, mailSubject);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R857");

            // Verify MS-OXORULE requirement: MS-OXORULE_R857.
            // For Out of Office rules, R858 has been verified in the above step, so if the OP_Forward rule can not be executed, this requirement can be captured.
            Site.CaptureRequirementIfIsFalse(
                doesUnexpectedMessageExist,
                857,
                "[In PidTagRuleState Property] EL (ST_EXIT_LEVEL, Bitmask 0x00000010): rule (2) evaluation will terminate after executing this rule (2) except for evaluation of Out of Office rules.");
            #endregion
        }