An OP_TAG action Data Buffer is a PropertyValue structure, packaged as specified in [MS-OXCDATA] section 2.11.2.1. This structure contains a PropertyTag_r structure.
상속: IActionData
예제 #1
0
        public void MSOXORULE_S04_TC03_ServerExecuteRule_Action_OP_TAG_OnPublicFolder()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 logs on to the public folder.
            RopOpenFolderResponse openFolderResponse;
            RopLogonResponse      logonResponse;
            bool ret = this.OxoruleAdapter.Connect(ConnectionType.PublicFolderServer, this.User1Name, this.User1ESSDN, this.User1Password);
            Site.Assert.IsTrue(ret, "connect to public folder server should be successful");
            uint publicFolderLogonHandler = this.OxoruleAdapter.RopLogon(LogonType.PublicFolder, this.User1ESSDN, out logonResponse);

            // Assert the client to log on to the public folder successfully.
            Site.Assert.AreEqual <uint>(0, logonResponse.ReturnValue, "Logon the public folder should be successful.");

            // Folder index 1 is the Interpersonal Messages subtree, and this is defined in MS-OXCSTOR.
            uint publicfolderHandler = this.OxoruleAdapter.RopOpenFolder(publicFolderLogonHandler, logonResponse.FolderIds[1], out openFolderResponse);

            // Get the store object's entry ID.
            this.GetStoreObjectEntryID(StoreObjectType.PublicFolder, this.Server, this.User1ESSDN);

            RopCreateFolderResponse createFolderResponse;
            string newFolderName   = Common.GenerateResourceName(this.Site, Constants.FolderDisplayName);
            uint   newFolderHandle = this.OxoruleAdapter.RopCreateFolder(publicfolderHandler, newFolderName, Constants.FolderComment, out createFolderResponse);
            ulong  newFolderID     = createFolderResponse.FolderId;
            Site.Assert.AreEqual <uint>(0, createFolderResponse.ReturnValue, "Creating folder operation should succeed.");
            #endregion

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

            #region TestUser1 adds an OP_TAG rule to the new created folder.
            TagActionData tagActionData            = new TagActionData();
            PropertyTag   tagActionDataPropertyTag = new PropertyTag
            {
                PropertyId   = (ushort)PropertyId.PidTagImportance,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            tagActionData.PropertyTag   = tagActionDataPropertyTag;
            tagActionData.PropertyValue = BitConverter.GetBytes(1);

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

            #region TestUser1 creates a message.
            RopCreateMessageResponse ropCreateMessageResponse;
            uint messageHandle = this.OxoruleAdapter.RopCreateMessage(newFolderHandle, newFolderID, Convert.ToByte(false), out ropCreateMessageResponse);
            Site.Assert.AreEqual <uint>(0, ropCreateMessageResponse.ReturnValue, "Creating message should succeed.");
            #endregion

            #region TestUser1 saves the subject property of the message to trigger the rule.
            string subjectName = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            TaggedPropertyValue subjectProperty          = new TaggedPropertyValue();
            PropertyTag         pidTagSubjectPropertyTag = new PropertyTag
            {
                PropertyId   = (ushort)PropertyId.PidTagSubject,
                PropertyType = (ushort)PropertyType.PtypString
            };
            subjectProperty.PropertyTag = pidTagSubjectPropertyTag;
            subjectProperty.Value       = Encoding.Unicode.GetBytes(subjectName + "\0");

            // Set properties for the created message to trigger the rule.
            RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(messageHandle, new TaggedPropertyValue[] { subjectProperty });
            Site.Assert.AreEqual <uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for the created message should succeed.");

            // Save changes of message.
            RopSaveChangesMessageResponse ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(messageHandle);
            Site.Assert.AreEqual <uint>(0, ropSaveChangesMessagResponse.ReturnValue, "Saving the created message should succeed.");

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

            #region TestUser1 gets the message and its properties to verify the rule evaluation.
            PropertyTag[] propertyTagList = new PropertyTag[2];
            propertyTagList[0].PropertyId   = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId   = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;

            uint contentTableHandle = 0;
            uint rowCount           = 0;
            RopQueryRowsResponse getMailMessageContent = this.GetExpectedMessage(newFolderHandle, ref contentTableHandle, propertyTagList, ref rowCount, 1, subjectName);
            Site.Assert.AreEqual <uint>(1, rowCount, @"The message number in the specific folder should be 1.");
            Site.Assert.AreEqual <int>(1, BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[(int)rowCount - 1].PropertyValues[0].Value, 0), "If the rule is executed, the PidTagImportance property of the message should be the value set by the rule.");

            RopDeleteFolderResponse deleteFolder = this.OxoruleAdapter.RopDeleteFolder(publicfolderHandler, newFolderID);
            Site.Assert.AreEqual <uint>(0, deleteFolder.ReturnValue, "Deleting folder should succeed.");
            #endregion
        }
        public void MSOXORULE_S02_TC09_ServerExecuteRule_Action_OP_TAG()
        {
            this.CheckMAPIHTTPTransportSupported();

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

            #region TestUser1 adds an OP_TAG rule to the Inbox folder.
            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, tagActionData, ruleProperties, null);
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleOpTag });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding OP_TAG rule should succeed.");
            #endregion

            #region TestUser2 delivers a message to TestUser1.

            // 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");

            // TestUser2 delivers a message to trigger these rules.
            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 gets the message and its properties to verify the rule evaluation.
            PropertyTag[] propertyTagList = new PropertyTag[2];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;

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

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R548: the value of PidTagImportance is {0}", BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0));

            // Verify MS-OXORULE requirement: MS-OXORULE_R548.
            // If the PidTagImportance is 2 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.
            bool isVerifyR548 = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0) == 2;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR548,
                548,
                @"[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_TAG"": The server MUST set on the message the property specified in the action buffer structure.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R266: the value of PidTagImportance is {0}", BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0));

            // Verify MS-OXORULE requirement: MS-OXORULE_R266.
            // If the PidTagImportance is 2 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.
            bool isVerifyR266 = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0) == 2;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR266,
                266,
                @"[In ActionBlock Structure] The meaning of action type OP_TAG: Adds or changes a property on the message.");
            #endregion

            #region TestUser1 gets the rule action property to check the rule action property.
            uint ruleHandle;
            RopGetRulesTableResponse ruleTableResponse = new RopGetRulesTableResponse();
            ruleHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ruleTableResponse);

            // Get rule property.
            PropertyTag[] ruleProperty = new PropertyTag[1];
            ruleProperty[0].PropertyId = (ushort)PropertyId.PidTagRuleActions;
            ruleProperty[0].PropertyType = (ushort)PropertyType.PtypRuleAction;
            RopQueryRowsResponse queryRowResponseOfProperty = this.OxoruleAdapter.QueryPropertiesInTable(ruleHandle, ruleProperty);
            Site.Assert.AreEqual<uint>(0, queryRowResponseOfProperty.ReturnValue, "Getting the rule action property should succeed, the actual value is {0}!", queryRowResponseOfProperty.ReturnValue);
            #endregion
        }
        public void MSOXORULE_S02_TC19_RuleState_ST_SKIP_IF_SCL_IS_SAFE()
        {
            this.CheckMAPIHTTPTransportSupported();
            Site.Assume.IsTrue(Common.IsRequirementEnabled(7411, this.Site), "This test case only runs if implementation does not skip evaluation of this rule (ST_SKIP_IF_SCL_IS_SAFE) when the delivered message's PidTagContentFilterSpamConfidenceLevel property has a value of 0xFFFFFFFF");
            
            #region TestUser1 adds an OP_TAG rule with PidTagRuleState set to ST_ENABLED | ST_SKIP_IF_SCL_IS_SAFE.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameTag);
            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_SKIP_IF_SCL_IS_SAFE, 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 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);

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

            TaggedPropertyValue contentFilterSpamConfidenceLevel = new TaggedPropertyValue();
            PropertyTag contentFilterSpamConfidenceLevelTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagContentFilterSpamConfidenceLevel,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            contentFilterSpamConfidenceLevel.PropertyTag = contentFilterSpamConfidenceLevelTag;
            contentFilterSpamConfidenceLevel.Value = BitConverter.GetBytes(0xFFFFFFFF);
            string subject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName);
            this.DeliverMessageToTriggerRule(this.User1Name, this.User1ESSDN, subject, new TaggedPropertyValue[1] { contentFilterSpamConfidenceLevel });

            // 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.
            // Let TestUser2 log on to the server
            this.LogonMailbox(TestUser.TestUser1);

            PropertyTag[] propertyTagList = new PropertyTag[2];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;

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

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R7411
            // 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.CaptureRequirementIfAreEqual<int>(
                2,
                BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0),
                7411,
                @"[In Appendix A: Product Behavior] Implementation does not skip evaluation of this rule (ST_SKIP_IF_SCL_IS_SAFE) if the delivered message's PidTagContentFilterSpamConfidenceLevel property ([MS-OXPROPS] section 2.638) has a value of 0xFFFFFFFF. (Exchange 2003 and above follow this behavior.)");
            #endregion
        }
        public void MSOXORULE_S04_TC03_ServerExecuteRule_Action_OP_TAG_OnPublicFolder()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 logs on to the public folder.
            RopOpenFolderResponse openFolderResponse;
            RopLogonResponse logonResponse;
            bool ret = this.OxoruleAdapter.Connect(ConnectionType.PublicFolderServer, this.User1Name, this.User1ESSDN, this.User1Password);
            Site.Assert.IsTrue(ret, "connect to public folder server should be successful");
            uint publicFolderLogonHandler = this.OxoruleAdapter.RopLogon(LogonType.PublicFolder, this.User1ESSDN, out logonResponse);

            // Assert the client to log on to the public folder successfully.
            Site.Assert.AreEqual<uint>(0, logonResponse.ReturnValue, "Logon the public folder should be successful.");

            // Folder index 1 is the Interpersonal Messages subtree, and this is defined in MS-OXCSTOR.
            uint publicfolderHandler = this.OxoruleAdapter.RopOpenFolder(publicFolderLogonHandler, logonResponse.FolderIds[1], out openFolderResponse);

            // Get the store object's entry ID.
            this.GetStoreObjectEntryID(StoreObjectType.PublicFolder, this.Server, this.User1ESSDN);

            RopCreateFolderResponse createFolderResponse;
            string newFolderName = Common.GenerateResourceName(this.Site, Constants.FolderDisplayName);
            uint newFolderHandle = this.OxoruleAdapter.RopCreateFolder(publicfolderHandler, newFolderName, Constants.FolderComment, out createFolderResponse);
            ulong newFolderID = createFolderResponse.FolderId;
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating folder operation should succeed.");
            #endregion

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

            #region TestUser1 adds an OP_TAG rule to the new created folder.
            TagActionData tagActionData = new TagActionData();
            PropertyTag tagActionDataPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagImportance,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            tagActionData.PropertyTag = tagActionDataPropertyTag;
            tagActionData.PropertyValue = BitConverter.GetBytes(1);

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

            #region TestUser1 creates a message.
            RopCreateMessageResponse ropCreateMessageResponse;
            uint messageHandle = this.OxoruleAdapter.RopCreateMessage(newFolderHandle, newFolderID, Convert.ToByte(false), out ropCreateMessageResponse);
            Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating message should succeed.");
            #endregion

            #region TestUser1 saves the subject property of the message to trigger the rule.
            string subjectName = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            TaggedPropertyValue subjectProperty = new TaggedPropertyValue();
            PropertyTag pidTagSubjectPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSubject,
                PropertyType = (ushort)PropertyType.PtypString
            };
            subjectProperty.PropertyTag = pidTagSubjectPropertyTag;
            subjectProperty.Value = Encoding.Unicode.GetBytes(subjectName + "\0");

            // Set properties for the created message to trigger the rule.
            RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(messageHandle, new TaggedPropertyValue[] { subjectProperty });
            Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for the created message should succeed.");

            // Save changes of message.
            RopSaveChangesMessageResponse ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(messageHandle);
            Site.Assert.AreEqual<uint>(0, ropSaveChangesMessagResponse.ReturnValue, "Saving the created message should succeed.");

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

            #region TestUser1 gets the message and its properties to verify the rule evaluation.
            PropertyTag[] propertyTagList = new PropertyTag[2];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;

            uint contentTableHandle = 0;
            uint rowCount = 0;
            RopQueryRowsResponse getMailMessageContent = this.GetExpectedMessage(newFolderHandle, ref contentTableHandle, propertyTagList, ref rowCount, 1, subjectName);
            Site.Assert.AreEqual<uint>(1, rowCount, @"The message number in the specific folder should be 1.");
            Site.Assert.AreEqual<int>(1, BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[(int)rowCount - 1].PropertyValues[0].Value, 0), "If the rule is executed, the PidTagImportance property of the message should be the value set by the rule.");

            RopDeleteFolderResponse deleteFolder = this.OxoruleAdapter.RopDeleteFolder(publicfolderHandler, newFolderID);
            Site.Assert.AreEqual<uint>(0, deleteFolder.ReturnValue, "Deleting folder should succeed.");
            #endregion
        }
        public void MSOXORULE_S03_TC07_OOFBehaviorsForFlagDisableSpecificOOFRule()
        {
            this.CheckMAPIHTTPTransportSupported();
            Site.Assume.IsTrue(Common.IsRequirementEnabled(624, this.Site), "This case runs only when implementation does use flag 0x00000080 to disable a specific Out of Office rule.");

            #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 TestUser1 adds an OP_TAG rule with PidTagRuleState set to ST_ENABLED | ST_ONLY_WHEN_OOF.
            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_ONLY_WHEN_OOF, 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");

            // Call 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.");

            // Get rule properties.
            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;

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

            ulong ruleId = 0;

            // Filter the correct rule.
            for (int i = 0; i < queryRowsResponse.RowCount; i++)
            {
                string ruleName = AdapterHelper.PropertyValueConvertToString(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[0].Value);
                if (ruleName == ruleProperties.Name)
                {
                    ruleId = BitConverter.ToUInt64(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[1].Value, 0);
                    break;
                }
            }

            #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 TestUser2 delivers a message to TestUser1 to trigger these rules.
            string messageSubjectName1 = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName, 1);

            // Sleep enough time to wait for the rule to take effect.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, messageSubjectName1);

            // 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[2];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;

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

            // 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.
            bool isRuleExecuteWhenInOOFState = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0) == 2;
            Site.Assert.IsTrue(isRuleExecuteWhenInOOFState, "The OP_TAG rule should be executed in OOF state!");
            #endregion

            #region Disable the OP_TAG rule.
            ruleOpTag = AdapterHelper.GenerateValidRuleData(ActionType.OP_TAG, TestRuleDataType.ForModify, 1, RuleState.X_DisableSpecificOOFRule | RuleState.ST_ONLY_WHEN_OOF, tagActionData, ruleProperties, ruleId);
            ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleOpTag });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Modifying the OP_TAG rule should succeed.");
            #endregion

            #region TestUser2 delivers a message to TestUser1 to trigger these rules.
            string messageSubjectName2 = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName, 2);

            // Sleep enough time to wait for the rule to take effect.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, messageSubjectName2);

            // 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.
            contentsTableHandle = 0;
            expectedMessageIndex = 0;
            getMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref expectedMessageIndex, messageSubjectName2);

            // 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.
            isRuleExecuteWhenInOOFState = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0) == 2;

            #region Capture Code

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R624.
            Site.CaptureRequirementIfIsFalse(
                isRuleExecuteWhenInOOFState,
                624,
                @"[In Appendix A: Product Behavior] Bit flag 0x00000080 is used to disable a specific Out of Office rule on the implementation. [<1> Section 2.2.1.3.2.3: Bit flag 0x00000080 is used to disable a specific Out of Office rule on Exchange 2007.]");

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

                // Verify MS-OXORULE requirement: MS-OXORULE_R621.
                // If r624 and r625 are completed, it means it does use the bit flags 0x00000080 and 0x00000100.
                Site.CaptureRequirement(
                    621,
                    "[In Appendix A: Product Behavior] The implementation uses bit flags 0x00000080 and 0x00000100 to store information about Out of Office functionality. [<1> Section 2.2.1.3.1.3: The Exchange 2007 implementation uses bit flags 0x00000080 and 0x00000100 to store information about Out of Office functionality.]");
            }
            #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
        }
        public void MSOXORULE_S03_TC06_OOFBehaviorsForFlagSameSemanticAsST_ONLY_WHEN_OOF()
        {
            this.CheckMAPIHTTPTransportSupported();
            Site.Assume.IsTrue(Common.IsRequirementEnabled(625, this.Site), "This case runs only when the flag 0x00000100 has the same semantics as ST_ONLY_WHEN_OOF of PidTagRuleState.");

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

            // Set the OOF status to false.
            bool isSetOOFSuccess = this.SUTSetOOFAdapter.SetUserOOFSettings(setOOFMailAddress, userPassword, false);
            Site.Assert.IsTrue(isSetOOFSuccess, "Turn Out of Office off for {0} should succeed.", this.User1Name);
            #endregion

            #region TestUser1 adds an OP_TAG rule with PidTagRuleState set to ST_ENABLED | 0x00000100.
            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.X_Same_Semantic_ST_ONLY_WHEN_OOF, 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 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[2];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagImportance;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypInteger32;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;

            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.
            bool isRuleNotExecuteWhenNotInOOFState = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0) != 2;
            Site.Assert.AreNotEqual<int>(2, BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0), "The value of PidTagImportance field should not be set!");
            #endregion

            #region Set TestUser1 to OOF state
            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 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);
            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.
            contentsTableHandle = 0;
            expectedMessageIndex = 0;
            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.
            bool isRuleExecuteWhenInOOFState = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0) == 2;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R625: whether rule is executed or not when it is not in out of office state is {0}, and when it is in out of office state is {1}", isRuleNotExecuteWhenNotInOOFState, isRuleExecuteWhenInOOFState);

            // Verify MS-OXORULE requirement: MS-OXORULE_R625
            // isRuleNotExecuteWhenNotInOOFState == true and  isRuleExecuteWhenInOOFState == true means the rule with rule state 0x000001000
            // will be executed only when the mail box is in OOF state, then this requirement can be verified.
            bool isVerifyR625 = isRuleNotExecuteWhenNotInOOFState && isRuleExecuteWhenInOOFState;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR625,
                625,
                @"[In Appendix A: Product Behavior] Bit flag 0x00000100 has the same semantics as the ST_ONLY_WHEN_OOF bit flag on the implementation. [<1> Section 2.2.1.3.2.3: Bit flag 0x00000100 has the same semantics as the ST_ONLY_WHEN_OOF bit flag on Exchange 2007.]");
            #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 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);
            mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName, 3);
            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.
            contentsTableHandle = 0;
            expectedMessageIndex = 0;
            getMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, ref expectedMessageIndex, mailSubject);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R584
            // 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.CaptureRequirementIfAreNotEqual<int>(
                2,
                BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value, 0),
                584,
                @"[In Entering and Exiting the Out of Office State] When the mailbox exits the Out of Office state, the server MUST stop processing rules (2) marked with the ST_ONLY_WHEN_OOF flag in the PidTagRuleState property.");
            #endregion
        }
        public void MSOXORULE_S03_TC01_OOFBehaviorsNotExecuteSubRuleWithoutST_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.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameMarkAsRead);
            RuleData ruleForMarkRead = AdapterHelper.GenerateValidRuleData(ActionType.OP_MARK_AS_READ, TestRuleDataType.ForAdd, 2, RuleState.ST_ENABLED, 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);
            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.
            bool isSubjectContainsRuleConditionSubject = false;
            int messageFlags = 0;
            mailSubject = AdapterHelper.PropertyValueConvertToString(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[1].Value);
            if (mailSubject.Contains(ruleProperties.ConditionSubjectName))
            {
                isSubjectContainsRuleConditionSubject = true;
                messageFlags = BitConverter.ToInt32(getMailMessageContent.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value, 0);
            }

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

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

            Site.CaptureRequirementIfIsTrue(
                isVerifyR560,
                560,
                @"[In Interaction Between ST_ONLY_WHEN_OOF and ST_EXIT_LEVEL Flags] When the Out of Office state is set on the mailbox, as specified in [MS-OXWOOF], and a rule (2) condition evaluates to ""TRUE"", if the rule (2) has the ST_EXIT_LEVEL flag specified in section 2.2.1.3.1.3 set, then the server MUST NOT evaluate subsequent rules (2) that do not have the ST_ONLY_WHEN_OOF flag set.");
            #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
        }
        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
        }