Mail Flow Receiver Datasource

Mail_flow_receiver.DataSource (DataSourceModuleType)

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsSystem.PrivilegedMonitoringAccount
OutputTypeSystem.PropertyBagData

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource Microsoft.Windows.TimedScript.PropertyBagProvider Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval Seconds
SyncTimestring$Config/SyncTime$Sync Time
MaxSafeMissedRunsint$Config/MaxSafeMissedRuns$Max Safe Missed Runs
LatencyThresholdint$Config/LatencyThreshold$Latency Threshold
MaxNegativeLatencyint$Config/MaxNegativeLatency$Max Negative Latency
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds

Source Code:

<DataSourceModuleType ID="Mail_flow_receiver.DataSource" Accessibility="Internal" RunAs="System!System.PrivilegedMonitoringAccount" Batching="false">
<Configuration>
<xsd:element name="IntervalSeconds" type="xsd:int"/>
<xsd:element name="SyncTime" type="xsd:string"/>
<xsd:element name="TargetNetbiosComputer" type="xsd:string"/>
<xsd:element name="MaxSafeMissedRuns" type="xsd:int"/>
<xsd:element name="LatencyThreshold" type="xsd:int"/>
<xsd:element name="MaxNegativeLatency" type="xsd:int"/>
<xsd:element name="TimeoutSeconds" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string"/>
<OverrideableParameter ID="MaxSafeMissedRuns" Selector="$Config/MaxSafeMissedRuns$" ParameterType="int"/>
<OverrideableParameter ID="LatencyThreshold" Selector="$Config/LatencyThreshold$" ParameterType="int"/>
<OverrideableParameter ID="MaxNegativeLatency" Selector="$Config/MaxNegativeLatency$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedScript.PropertyBagProvider">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime>$Config/SyncTime$</SyncTime>
<ScriptName>VerifyMFR.js</ScriptName>
<Arguments>$Config/TargetNetbiosComputer$ $Config/MaxSafeMissedRuns$ $Config/LatencyThreshold$ $Config/MaxNegativeLatency$</Arguments>
<ScriptBody><Script>
// Event Constants
var EVENT_SOURCE = "Exchange MOM";
var EVENT_TYPE_SUCCESS = 0;
var EVENT_TYPE_ERROR = 1;
var EVENT_TYPE_WARNING = 2;
var EVENT_TYPE_INFORMATION = 4;

var oAPI = new ActiveXObject("Mom.ScriptAPI");

function CreateEvent(lngEventID, lngEventType, strMsg)
{
oAPI.LogScriptEvent(EVENT_SOURCE, lngEventID, lngEventType, strMsg);
}

function EchoEvent(lngEventID, lngEventType, strMsg)
{
var sevString;

switch(lngEventType)
{
case EVENT_TYPE_SUCCESS: sevString = "Success"; break;
case EVENT_TYPE_ERROR: sevString = "Error"; break;
case EVENT_TYPE_WARNING: sevString = "Warning"; break;
case EVENT_TYPE_INFORMATION: sevString = "Infomation"; break;
}

if (lngEventType != EVENT_TYPE_SUCCESS)
{
WScript.Echo(EVENT_SOURCE , "Event ID:" , lngEventID , "Severity: " , sevString);
WScript.Echo(strMsg);
}
}

function HResultToString(hresult)
{
return "0x" + (hresult &lt; 0 ? hresult + 0x100000000 : hresult).toString(16).toUpperCase() + "(" + hresult +")";
}


//Copyright (c) Microsoft Corporation. All rights reserved.
//*******************************************************************************
// $ScriptName: "Mail flow receiver" $
//
// Purpose - Receives mail and verify if mail flow is working
//
// Parameters - "MaxSafeMissedRuns" = number of times mail has not showed up before an
// event is created to warn about mail flow problems.
// "LatencyThreshold" = maximum acceptable latency in seconds; the script creates an
// event if the latency is above the parameter value.
//
// Events - Description
// 9016 - Unexpected exception
// 9551 - Invalid parameter
// 9552 - Different problems preventing the script execution
// 9553 - Negative latency "mail arrived before sent"
// 9554 - Expected mail flow message not received
// 9555 - # of messages not received exceeded the threshold of unsuccessful attempts
// 9557 - Script not running as System
// 9558 - Script context account verification failed
// 9559 - Test mailbox residing on the wrong server
// 9560 - GET_TST_MB_FAILED_ID
// 9561 - MB_NOT_EXIST_ID
// 9563 - TIMEOUT_ID
// 9564 - Latency threshold exceeded
// 4987 - Attempting to publish Exchange Management Pack data
// 4988 - Please run Exchange Management Pack Configuration Utility
// 4990 - Cannot receive mail flow messages: error verifying pub key
//
// $File: VerifyMFR.js $
//
// $Date: 2005/06/14 19:13:43 $ $Revision: 8 $
//*************************************************************************

// Event Constants
EVENT_SOURCE = "Exchange MOM - MFR";
// TypedPropertyBag
var PerformanceDataType = 2;
var StateDataType = 3;
// Event ID Constants
var EVENT_ID_BASE_STATE_OK = 10000;

//Other Variables
var oBag;
var ERROR_FILE_NOT_FOUND = -2147024894; //ERROR_FILE_NOT_FOUND = 0x00000002

var MaxNegativeLatency, LatencyThreshold, MaxSafeMissedRuns, TargetNetbiosComputer;
if(WScript.Arguments.Unnamed.Count == 4){
TargetNetbiosComputer=WScript.Arguments(0);
MaxSafeMissedRuns=WScript.Arguments(1);
LatencyThreshold=WScript.Arguments(2);
MaxNegativeLatency=WScript.Arguments(3);
}else{
WScript.quit();
}

// The caller is responsible for the exception treatment
function IsRunningAsSystem()
{
var retval = false;
var WshNetwork = new ActiveXObject("WScript.Network");
// Use the well-known SID of the system account ("S-1-5-18") to get the correspondent object
var WMISystemAcct = GetObject("WinMgmts:root/cimv2:Win32_SID='S-1-5-18'");
// WshNetwork.UserName gives the account running the current thread
//
// WMISystemAcct.AccountName gets the localized name of the system account
//
// No worries with string case in the comparison below since, if the account is
// system, the name is extracted from the same location for both objects
if (WshNetwork.UserName == WMISystemAcct.AccountName)
retval = true;
return(retval);
}
function BuildAcctName(strServerName)
{
var objShell = null;
var strAccount = null;
objShell = new ActiveXObject("WScript.Shell");
var testServerMailbox_RegPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Exchange MOM\\Accounts\\"+strServerName+"\\TestServerMailbox";
try
{
strAccount = objShell.RegRead(testServerMailbox_RegPath);
strAccount = strAccount.replace(/(^\s+)|(\s+$)/g, ""); //Trim white spaces
//Deals with the case when the value was created but not touched
// in which RegRead will return the registry path
if ( strAccount == testServerMailbox_RegPath || strAccount.length == 0)
strAccount = strServerName + "MOM";
}
catch(err)
{
// If error is not ERROR_FILE_NOT_FOUND (i.e. RegKey doesn't exist) then throw error
if (ERROR_FILE_NOT_FOUND != err.number)
throw err;
else
strAccount = strServerName + "MOM"
}
return strAccount;
}
function IsFrontEnd(strServerName)
{
var oConnect = new ActiveXObject("ADODB.Connection");
oConnect.Provider = "ADsDSOObject";
oConnect.Open();
var command = new ActiveXObject("ADODB.Command");
command.ActiveConnection = oConnect;
var objRootDSE = GetObject("LDAP://rootDSE");
command.CommandText = "SELECT CN FROM 'LDAP://" + objRootDSE.Get("configurationNamingContext") + "' WHERE CN='" + strServerName + "' AND serverRole=1";
command.Properties("Page Size") = 100;
command.Properties("Timeout") = 10;
command.Properties("searchscope") = 2;
command.Properties("Chase referrals") = 0x20 | 0x40;
command.Properties("Cache Results") = false;
var rs = command.Execute();
var boolIsFrontEnd = false;
if (!rs.EOF){
rs.MoveFirst();
if (rs.Fields(0).Value.toUpperCase() == strServerName.toUpperCase())
boolIsFrontEnd = true;
}
return boolIsFrontEnd;
}
function GetRootGC()
{
var oGCColl = GetObject("GC:");
var enumGCs = new Enumerator(oGCColl);
if (!enumGCs.atEnd())
return enumGCs.item();
return null;
}
function GetAccountServer(strAcctName)
{
var oConnect = new ActiveXObject("ADODB.Connection");
oConnect.Provider = "ADsDSOObject";
oConnect.Open();
var command = new ActiveXObject("ADODB.Command");
command.ActiveConnection = oConnect;
var objRootGC = GetRootGC();
command.CommandText = "SELECT homeMDB, AdsPath, sAMAccountName FROM '" + objRootGC.ADsPath + "' WHERE sAMAccountName='" + strAcctName + "' AND objectclass='user' AND objectCategory='person' ORDER BY sAMAccountName";
command.Properties("Page Size") = 100;
command.Properties("Timeout") = 10; //seconds
command.Properties("searchscope") = 2; //ADS_SCOPE_SUBTREE
command.Properties("Chase referrals") = 0x20 | 0x40; //ADS_CHASE_REFERRALS_ALWAYS
command.Properties("Cache Results") = false; //do not cache the result set
var rs = command.Execute();
var strServerName;
if (!rs.EOF)
{
rs.MoveFirst();
for(i = 0; i&lt;rs.Fields.Count; i++){
if (rs.Fields(i).Name == "homeMDB") {
strServerName = rs.Fields(i).Value.split("CN=")[4].split(",")[0];
}
}
return strServerName;
}
else
return null;
}
var NO_REGKEY_SENTINEL = "...";
function GetRegEntry(strRegEntry)
{
var strEntryValue = "";
var objShell = new ActiveXObject("WScript.Shell");
var strEntryValue = NO_REGKEY_SENTINEL;
try {
strEntryValue = objShell.RegRead(strRegEntry);
} catch(err) {
if (err.number != ERROR_FILE_NOT_FOUND)
throw err;
strEntryValue = NO_REGKEY_SENTINEL;
}
// Deals with the case when the value was created but not touched, in this case RegRead will return the registry entry
if (typeof(strEntryValue) == "string")
if (strRegEntry.toLowerCase() == strEntryValue.toLowerCase())
strEntryValue = NO_REGKEY_SENTINEL;
return (strEntryValue);
}
// Note that elements are 'trimmed' and if str == """ the array will be { "" }
function SplitParams(str)
{
var objRegExp = /[,\s]+/;
var objArray = str.split(objRegExp);
return(objArray);
}
// Registry path (as used by WshShell) to the configuration entries of mail flow
//V3 Changes start
//replaced scriptcontext.TargetNetbiosComputer with TargetNetbiosComputer
var MAILFLOW_BASE_REG_KEY = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Exchange MOM\\Mail Flow\\";
var SEND_TO_MBX_REG_PATH = MAILFLOW_BASE_REG_KEY + TargetNetbiosComputer + "\\SendToMailbox";
var SEND_TO_SRV_REG_PATH = MAILFLOW_BASE_REG_KEY + TargetNetbiosComputer + "\\SendTo";
var EXPECTED_FROM_REG_PATH = MAILFLOW_BASE_REG_KEY + TargetNetbiosComputer + "\\ExpectedFrom";
var MISSED_RUN_REG_PATH = MAILFLOW_BASE_REG_KEY + TargetNetbiosComputer + "\\MissedRun\\";
//V3 Changes end
function IsKeyPublished()
{
var bRet;
var WshShell = new ActiveXObject("WScript.Shell");
var data = null;
try{
data = WshShell.RegRead("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\ExMPLS\\DATA0");
}catch(err){
if (ERROR_FILE_NOT_FOUND != err.number) // If not Invalid entry or key throw the error
throw err;
data = null;
}
bRet = false;
try{
if ((null != data) &amp;&amp;
("unknown" == typeof(data)) &amp;&amp;
(256 &lt;= (data.ubound() - data.lbound() + 1)))
{
var jsArray = data.toArray();
if ("number" == typeof(jsArray[0]))
bRet = true;
}
}catch(err){
// data is not the expected structure
bRet = false;
}
return bRet;
}
function GetPercentProcessorTime()
{
var objWMI, PercentProcessorTime, perf_instance1, perf_instance2, N1, D1, N2, D2, objUtil;
try{
objWMI = GetObject("Winmgmts:Root\\Cimv2");
}catch(err){ return -1;};
PercentProcessorTime = 0;
for(var i = 0; i&lt;5; i++)
{
perf_instance1 = null;
perf_instance2 = null;
N1 = 0;
D1 = 0;
N2 = 0;
D2 = 0;
try{ perf_instance1 = objWMI.Get("Win32_PerfRawData_PerfOS_Processor.Name='_Total'");}catch(err2){return -1;};
N1 = perf_instance1.PercentProcessorTime;
D1 = perf_instance1.TimeStamp_Sys100NS;
//Sleep for 1 second
WScript.Sleep(1000);
try{perf_instance2 = objWMI.Get("Win32_PerfRawData_PerfOS_Processor.Name='_Total'");}catch(err3){return -1;};
N2 = perf_instance2.PercentProcessorTime;
D2 = perf_instance2.TimeStamp_Sys100NS;
//CounterType: PERF_100NSEC_TIMER_INV
//Formula: (1- ((N2 - N1) / (D2 - D1))) x 100
if ((D2-D1)&gt;0)
PercentProcessorTime = (1 - ((N2 - N1)/(D2-D1)))*100 + PercentProcessorTime;
else
return -1;
}
PercentProcessorTime = PercentProcessorTime / 5;
return PercentProcessorTime;
}
// Checks if the string containg an entry value represents an attempt to configure mail flow. This function
// does not validate the entry it only checks if it is not empty.
function IsConfigRegEntryPresent(strConfigEntryRegPath)
{
var blnResult = false;
var strConfigEntryValue = GetRegEntry(strConfigEntryRegPath);
if (strConfigEntryValue!= null)
{
// Trim the string
strConfigEntryValue = strConfigEntryValue.replace(/(^\s+)|(\s+$)/g, "");
if ((strConfigEntryValue.length &gt; 0) &amp;&amp; (strConfigEntryValue != NO_REGKEY_SENTINEL))
blnResult = true;
}
return blnResult;
}
// Not all event messages are declared here check the CreateEvent calls to see the event messages
var INVALID_PARAMETER_ID = 9551;
var UNEXPECTED_EXCEPTION_EVENT_ID = 9016;
var UNEXPECTED_EXCEPTION_EVENT_MSG = "The script aborted its execution due to the following error:\n";
var NO_UNEXPECTED_EXCEPTION_EVENT_ID = EVENT_ID_BASE_STATE_OK + UNEXPECTED_EXCEPTION_EVENT_ID;
var NO_UNEXPECTED_EXCEPTION_EVENT_MSG = "No unexpected exceptions";
var SERVER_ROLE_CHECK_FAILED_ID = 9552;
var SERVER_ROLE_CHECK_FAILED_MSG = "Cannot receive mail flow messages: a problem was encountered when trying to determine if the current computer is a front-end server\nError:\n";
var FAILED_TO_CHECK_MF_CONFIG_ID = 9552;
var FAILED_TO_CHECK_MF_CONFIG_MSG = "Cannot retrieve the mail flow configuration from the registry.\nError:\n";
var FAILED_TO_SET_COMP_DATA_ID = 9552;
var FAILED_TO_SET_COMP_DATA_MSG = "Cannot update the mail flow state component on MOM for this computer.\nError:\n";
var NEGATIVE_LATENCY_ID = 9553;
var NEGATIVE_LATENCY_MSG = "Detected a negative delivery latency in the mail flow verification. In general this indicates clock synchronization problem. Detailed information:\n\n";
var MSG_NOT_RECEIVED_ID = 9554;
var MSG_NOT_RECEIVED_MSG = "Expected mail flow messages were not received from the following servers:\n\n";
var ALL_RECEIVED_MSGS_OK_ID = EVENT_ID_BASE_STATE_OK + MSG_NOT_RECEIVED_ID;
var ALL_RECEIVED_MSGS_OK_MSG = "All expected messages received successfully.";
var MSG_NOT_RECEIVED_EXCEEDED_THRESHOLD_ID = 9555;
var MSG_NOT_RECEIVED_EXCEEDED_THRESHOLD_MSG = "Limit of attempts to receive mail flow messages exceeded. Detailed information:\n\n";
var CANNOT_RUN_AS_SYSTEM_EVENT_ID = 9557;
var CANNOT_RUN_AS_SYSTEM_EVENT_MSG = "Cannot receive mail flow messages: the script is not running as SYSTEM";
var AGENT_ACCT_CHECK_FAILED_ID = 9558;
var AGENT_ACCT_CHECK_FAILED_MSG = "Cannot receive mail flow messages: a problem was encountered when trying to determine the script context\nError:\n";
var TST_MB_ON_WRONG_SERVER_ID = 9559;
var TST_MB_ON_WRONG_SERVER_MSG = "The Mailbox account used for mail flow verification (through MAPI) is not residing on the correct server.\n " +
"Mail flow using this mailbox will be aborted.\n ";
var GET_TST_MB_FAILED_ID = 9560;
var GET_TST_MB_FAILED_MSG = "Cannot receive mail flow messages: a problem was encountered when trying to find the mailbox account (used for sending mail) from the Active Directory\n" +
"Please make sure the Domain Controller is running properly and can be accessed from this server.\n" +
"Please also make sure an Exchange mailbox is created for the account: " ;
var MB_NOT_EXIST_ID = 9561;
var MB_NOT_EXIST_MSG = "The required test mailbox used by mail flow verification does not exist. Please read the configruation guide to perform the required configurations\n";
var TIMEOUT_ID = 9563;
var TIMEOUT_MSG = "Mail Flow: operation timed out while verifying if mail flow message is received in mailbox ";
var LATENCY_THRESHOLD_EXCEEDED_ID = 9564;
var LATENCY_THRESHOLD_EXCEEDED_MSG = "Specified delivery latency of mail flow messages exceeded. Detailed information:\n\n";
var ZERO_MSGS_RECEIVED_ID = 9565;
var ZERO_MSGS_RECEIVED_MSG = "This Exchange server did not receive any mail flow message in the last verification";
var MSG_RECVD_NOT_EXPECTING_ID = 9568;
var MSG_RECVD_NOT_EXPECTING_MSG = "Although this server is not configured to receive mail flow messages it received mail flow messages from the following servers:\n\n";
var UNEXPECTED_SENDERS_ID = 9569;
var UNEXPECTED_SENDERS_MSG = "Unxpected mail flow messages were received from the following servers:\n\n";
var NO_UNEXPECTED_SENDERS_ID = EVENT_ID_BASE_STATE_OK + UNEXPECTED_SENDERS_ID;
var NO_UNEXPECTED_SENDERS_MSG = "No unexpected servers sending messages to this server.";
var MSG_RECEIVED_ID = 9570;
var MSG_RECEIVED_MSG = "Mail flow message received from the following servers:\n\n";
var CALL_PUBLISH_EXMP_ID = 4987;
var CALL_PUBLISH_EXMP_MSG = "Attempting to publish Exchange Management Pack data required to use the test mailbox accounts";
var RUN_CRED_UTIL_ID = 4988;
var RUN_CRED_UTIL_MSG = "Please run Exchange Management Pack Configuration Utility against this server to use the test mailbox accounts";
var VERIFY_PUBLISH_FAILED_ID = 4990;
var VERIFY_PUBLISH_FAILED_MSG = "Cannot receive mail flow messages: error checking the Exchange Management Pack data required to use the test mailbox accounts\nError:\n";
var SUCCESS = 0;
var CALL_PUBLISH = 8000;
var CALL_UTIL = 8001;
var MSG_NOT_RECEIVED = 9000;
var blnMailFlowMonitoringEnabled = false;

MainRoutine:
{
try
{
blnMailFlowMonitoringEnabled = IsMailFlowMonitoringEnabled();
}
catch(err)
{
CreateEvent(FAILED_TO_CHECK_MF_CONFIG_ID, EVENT_TYPE_ERROR, FAILED_TO_CHECK_MF_CONFIG_MSG + HResultToString(err.number) + " " + err.description);
break MainRoutine;
}
// If mail flow disabled create the appropriate success events to correctly update the problem state
// of alerts related to the mail flow component
if (!blnMailFlowMonitoringEnabled)
{
oBag= oAPI.CreateTypedPropertyBag(StateDataType);
oBag.AddValue("State", "GOOD" );
oAPI.AddItem(oBag) ;
CreateEvent(ALL_RECEIVED_MSGS_OK_ID, EVENT_TYPE_SUCCESS, ALL_RECEIVED_MSGS_OK_MSG);
CreateEvent(NO_UNEXPECTED_EXCEPTION_EVENT_ID, EVENT_TYPE_SUCCESS, NO_UNEXPECTED_EXCEPTION_EVENT_MSG);
}
ReceiveMailFlow(TargetNetbiosComputer);
} //MainRoutine
try{
oAPI.ReturnItems();
}catch(error){
oBag = oAPI.CreateTypedPropertyBag(StateDataType);
oAPI.AddItem(oBag);
try{
oAPI.ReturnItems();
}catch(errNeg){}
}
function ReceiveMailFlow(strExServer)
{
var blnIsFrontEnd, blnMailFlowConfigured;
strExServer = strExServer.toLowerCase();
var strMsgExpectedFromList = GetRegEntry(EXPECTED_FROM_REG_PATH).toLowerCase();
if(("" == strMsgExpectedFromList) || (NO_REGKEY_SENTINEL == strMsgExpectedFromList))
blnMailFlowConfigured = false; // We need to proceed even if not configured to delete possible mails in the Inbox and report some issues
else
blnMailFlowConfigured = true;
try{
if (!IsKeyPublished())
{
CreateEvent(CALL_PUBLISH_EXMP_ID, EVENT_TYPE_INFORMATION, CALL_PUBLISH_EXMP_MSG);
return;
}
} catch(err) {
if (blnMailFlowConfigured)
CreateEvent(VERIFY_PUBLISH_FAILED_ID, EVENT_TYPE_ERROR, VERIFY_PUBLISH_FAILED_MSG + HResultToString(err.number) + " " + err.description);
return;
}
try{
if (!IsRunningAsSystem() &amp;&amp; blnMailFlowConfigured)
{
CreateEvent(CANNOT_RUN_AS_SYSTEM_EVENT_ID, EVENT_TYPE_ERROR, CANNOT_RUN_AS_SYSTEM_EVENT_MSG);
return;
}
} catch(err) {
if (blnMailFlowConfigured)
CreateEvent(AGENT_ACCT_CHECK_FAILED_ID, EVENT_TYPE_ERROR, AGENT_ACCT_CHECK_FAILED_MSG + HResultToString(err.number) + " " + err.description);
return;
}
try{
blnIsFrontEnd = IsFrontEnd(strExServer);
} catch(err) {
if (blnMailFlowConfigured)
CreateEvent(SERVER_ROLE_CHECK_FAILED_ID, EVENT_TYPE_ERROR, SERVER_ROLE_CHECK_FAILED_MSG + HResultToString(err.number) + " " + err.description);
return;
}
try{
if (!blnIsFrontEnd) ReceiveMailFlowMsgs(strExServer, strMsgExpectedFromList, blnMailFlowConfigured);
}catch(err){
CreateEvent(
UNEXPECTED_EXCEPTION_EVENT_ID,
EVENT_TYPE_ERROR,
UNEXPECTED_EXCEPTION_EVENT_MSG + HResultToString(err.number) + " " + err.description);
return;
}

CreateEvent(NO_UNEXPECTED_EXCEPTION_EVENT_ID, EVENT_TYPE_SUCCESS, NO_UNEXPECTED_EXCEPTION_EVENT_MSG);
}
function ReceiveMailFlowMsgs(strDestSrv, strMsgExpectedFromList, blnMailFlowConfigured)
{
var errID, objMFR, strToAcct, strToAcctServerName, strSenderServer, lngMaxSafeMissedRuns, MailFlowReceiverObjName,
LatencyThreshold, MaxNegativeLatency, latency, i, objShell, err2, err3, fPercentProcessorTime;
MailFlowReceiverObjName = "EMPMR.MailFlowReceiver";
lngMaxSafeMissedRuns = GetParamMaxMissedRuns();
LatencyThreshold = GetParamLatencyThreshold();
MaxNegativeLatency = GetParamMaxNegativeLatency();
strToAcct = BuildAcctName(strDestSrv);
try{
strToAcctServerName = GetAccountServer(strToAcct);
}catch(err){
if (blnMailFlowConfigured)
CreateEvent(
GET_TST_MB_FAILED_ID,
EVENT_TYPE_ERROR,
GET_TST_MB_FAILED_MSG + strToAcct + "\nError: "+ HResultToString(err.number) + "\n" + err.description);
return;
}
//GetAccountServer returns null if the user object or its homeMDB property does not exist in AD
//Need to inform administrator to create the test mailbox according to the configuration guide
if (strToAcctServerName == null)
{
if (blnMailFlowConfigured)
CreateEvent(
MB_NOT_EXIST_ID,
EVENT_TYPE_WARNING,
MB_NOT_EXIST_MSG + "The test mailbox for mail flow either does not exist or is misconfigured. Please run the Exchange Management Pack Configuration Utility to configure mail flow.");
return;
}
strToAcctServerName = strToAcctServerName.toLowerCase();
if (strToAcctServerName != strDestSrv)
{
if (blnMailFlowConfigured)
CreateEvent(
TST_MB_ON_WRONG_SERVER_ID,
EVENT_TYPE_WARNING,
TST_MB_ON_WRONG_SERVER_MSG + "Please move mailbox '" + strToAcct + "' to " + strDestSrv + " or delete this mailbox.");
return;
}
objMFR = new ActiveXObject(MailFlowReceiverObjName);
objShell = new ActiveXObject("WScript.Shell");
try{
errID = objMFR.ReceiveMail(strDestSrv, strToAcct, 30000);
}catch(err2){
try {
//objMFR would set the reg value MFRTimeOut prior to termination if it is a time out
if (objShell.RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\ExMPLS\\MFRTimeOut") == "Y")
{
fPercentProcessorTime = GetPercentProcessorTime();
if (fPercentProcessorTime &gt;= 0)
CreateEvent(TIMEOUT_ID, EVENT_TYPE_ERROR, TIMEOUT_MSG + strToAcct + "\nCPU is running at " + fPercentProcessorTime.toFixed(2) + " percent.");
else
CreateEvent(TIMEOUT_ID, EVENT_TYPE_ERROR, TIMEOUT_MSG + strToAcct);
return;
}
} catch(err3) {
//some unknown error caused the object to terminate, throw error
throw err2;
}
}
if (errID == CALL_PUBLISH)
{
if (blnMailFlowConfigured)
CreateEvent(CALL_PUBLISH_EXMP_ID, EVENT_TYPE_ERROR, CALL_PUBLISH_EXMP_MSG);
}
else if (errID == CALL_UTIL)
{
if (blnMailFlowConfigured)
CreateEvent(RUN_CRED_UTIL_ID, EVENT_TYPE_ERROR, RUN_CRED_UTIL_MSG);
}
else if ((errID == SUCCESS) || (errID == MSG_NOT_RECEIVED))
{
var strUnexpectedSenders = "";
var strNegativeLantencySenders = "";
var strLatencyExceededSenders = "";
var strMsgNotReceivedFromSenders = "";
var strMaxAttempsExceededSenders = "";
var strMsgReceivedFromSenders = "";
var arrMFStatus = BuildCurrentMailFlowStatusArray(strMsgExpectedFromList, strDestSrv);
var tmpVBArray = new VBArray(objMFR.ReceivedMailFlowInfo);
var arrReceivedMFInfo = tmpVBArray.toArray();
arrReceivedMFInfo.sort(compareMailFlowMsgBySenderServer);
// We are in one of the following situations: (errID == SUCCESS) || (errID == MSG_NOT_RECEIVED)
if ((errID == MSG_NOT_RECEIVED) &amp;&amp; blnMailFlowConfigured)
{
//No msg received, report this fact. We need to continue to update the number of attempts to receive msgs
CreateEvent(ZERO_MSGS_RECEIVED_ID, EVENT_TYPE_ERROR, ZERO_MSGS_RECEIVED_MSG);
}
else if ((errID == SUCCESS) &amp;&amp; !blnMailFlowConfigured)
{
var strSenderServers = "";
for (i in arrReceivedMFInfo)
if (-1 == strSenderServers.toLowerCase().indexOf(arrReceivedMFInfo[i].SenderServer.toLowerCase()))
strSenderServers += arrReceivedMFInfo[i].SenderServer + "\n";
// The server received some mail flow message but it is not configured to expect mail from any server, get out!!!!
CreateEvent(MSG_RECVD_NOT_EXPECTING_ID, EVENT_TYPE_ERROR, MSG_RECVD_NOT_EXPECTING_MSG + strSenderServers);
return;
}
for (i in arrReceivedMFInfo)
{
strSenderServer = arrReceivedMFInfo[i].SenderServer.toLowerCase();
if(null == arrMFStatus[strSenderServer])
{
if (-1 == strUnexpectedSenders.toLowerCase().indexOf(strSenderServer.toLowerCase()))
strUnexpectedSenders += strSenderServer + "\n"; // Msg received from an unexpected server
}
else
{
arrMFStatus[strSenderServer].MsgReceived = true;
latency = (arrReceivedMFInfo[i].TimeReceived - arrReceivedMFInfo[i].TimeSent)/1000;
if (latency &lt; -MaxNegativeLatency)
{
strNegativeLantencySenders += "Delivery latency from " + strSenderServer + " (at " +
arrReceivedMFInfo[i].TimeSent + ") = " + latency + " (seconds)\n"; // Negative latency
}
else
{
if (-1 == strMsgReceivedFromSenders.toLowerCase().indexOf(strSenderServer.toLowerCase()))
strMsgReceivedFromSenders += strSenderServer + "\n"; // Msg received
oBag= oAPI.CreateTypedPropertyBag(PerformanceDataType) ;
oBag.AddValue("StatusInstance", strSenderServer.toLowerCase() + " -&gt; " + strDestSrv.toLowerCase());
oBag.AddValue("StatusValue", latency);
oAPI.AddItem(oBag);
if (latency &gt; LatencyThreshold)
{
strLatencyExceededSenders += "Delivery latency from " + strSenderServer + " (at " +
arrReceivedMFInfo[i].TimeSent + ") = " + latency + " (seconds)\n"; // Latency exceeded
arrMFStatus[strSenderServer].NumMissedRuns++;
}
else
{
arrMFStatus[strSenderServer].NumMissedRuns = 0;
}
}
}
}
for (strSenderServer in arrMFStatus)
{
if (!arrMFStatus[strSenderServer].MsgReceived)
{
strMsgNotReceivedFromSenders += strSenderServer + "\n"; // No msg from this server
arrMFStatus[strSenderServer].NumMissedRuns++;
}
if (arrMFStatus[strSenderServer].NumMissedRuns &gt; lngMaxSafeMissedRuns)
strMaxAttempsExceededSenders += "Failed to receive mail flow message within allowed latency from " + strSenderServer +
" in the last " + arrMFStatus[strSenderServer].NumMissedRuns + " attempts.\n"; // Max missed runs exceeded
if (arrMFStatus[strSenderServer].NumMissedRuns &gt; 0)
objShell.RegWrite(MISSED_RUN_REG_PATH + strSenderServer.toString(), arrMFStatus[strSenderServer].NumMissedRuns, "REG_DWORD");
}

var State = "BAD";
if ("" != strUnexpectedSenders)
CreateEvent(UNEXPECTED_SENDERS_ID, EVENT_TYPE_WARNING, UNEXPECTED_SENDERS_MSG + strUnexpectedSenders);
else
CreateEvent(NO_UNEXPECTED_SENDERS_ID, EVENT_TYPE_SUCCESS, NO_UNEXPECTED_SENDERS_MSG);
if ("" != strNegativeLantencySenders)
CreateEvent(NEGATIVE_LATENCY_ID, EVENT_TYPE_WARNING, NEGATIVE_LATENCY_MSG + "Current MaxNegativeLatency = " + MaxNegativeLatency + " seconds\n\n" + strNegativeLantencySenders);
if ("" != strLatencyExceededSenders)
CreateEvent(LATENCY_THRESHOLD_EXCEEDED_ID, EVENT_TYPE_WARNING, LATENCY_THRESHOLD_EXCEEDED_MSG + strLatencyExceededSenders);
if ("" != strMsgReceivedFromSenders)
CreateEvent(MSG_RECEIVED_ID, EVENT_TYPE_INFORMATION, MSG_RECEIVED_MSG + strMsgReceivedFromSenders);
if ("" == strMsgNotReceivedFromSenders)
CreateEvent(ALL_RECEIVED_MSGS_OK_ID, EVENT_TYPE_SUCCESS, ALL_RECEIVED_MSGS_OK_MSG);
else
CreateEvent(MSG_NOT_RECEIVED_ID, EVENT_TYPE_WARNING, MSG_NOT_RECEIVED_MSG + strMsgNotReceivedFromSenders);
if ("" == strMaxAttempsExceededSenders)
State = "GOOD";
else
CreateEvent(MSG_NOT_RECEIVED_EXCEEDED_THRESHOLD_ID, EVENT_TYPE_ERROR, MSG_NOT_RECEIVED_EXCEEDED_THRESHOLD_MSG + strMaxAttempsExceededSenders);
if(blnMailFlowConfigured)
{
oBag= oAPI.CreateTypedPropertyBag(StateDataType);
oBag.AddValue("State", State);
oAPI.AddItem(oBag);
}
}
else
{
if(blnMailFlowConfigured)
{
oBag= oAPI.CreateTypedPropertyBag(StateDataType);
oBag.AddValue("State", "BAD");
oAPI.AddItem(oBag) ;
}
var objError = new Error(errID, "Unexpected error code received from '" + MailFlowReceiverObjName + "', description: " + objMFR.errDes);
throw objError;
}
}
function BuildCurrentMailFlowStatusArray(strCurrentListOfServers, strServer)
{
var arrMFStatus = BuildMailFlowStatusArrayFromList(strCurrentListOfServers);
var missedRuns = 0;
var objShell = new ActiveXObject("WScript.Shell");
for (server in arrMFStatus)
{
arrMFStatus[server].Deleted = false;
try
{
missedRuns = objShell.RegRead(MISSED_RUN_REG_PATH + server.toString());
arrMFStatus[server].NumMissedRuns = missedRuns;
}
catch (err)
{
if (err.number != ERROR_FILE_NOT_FOUND)
throw err;
arrMFStatus[server].NumMissedRuns = 0;
}
}
// clear out all missed runs in registry once they are read to memory
try
{
objShell.RegDelete(MISSED_RUN_REG_PATH);
}
catch (err)
{
if (err.number != ERROR_FILE_NOT_FOUND)
throw err;
}
return arrMFStatus;
}
function BuildMailFlowStatusArrayFromList(strListOfServers)
{
var arrMFStatus = new Array();
if(null != strListOfServers)
{
var arrServers = SplitParams(strListOfServers);
for (i in arrServers)
if(("" != arrServers[i]) &amp;&amp; (NO_REGKEY_SENTINEL != arrServers[i]))
arrMFStatus[arrServers[i].toLowerCase()] = new MailFlowStatus();
}
return arrMFStatus;
}
function MailFlowStatus()
{
this.Deleted = true;
this.MsgReceived = false;
this.NumMissedRuns = 0;
}
// ASSUMPTION a &amp; b are objects containing a property called SenderServer
function compareMailFlowMsgBySenderServer(a, b)
{
var ret = +1;
if (a.SenderServer &lt; b.SenderServer)
ret = -1;
else if ((a.SenderServer.toLowerCase() == b.SenderServer.toLowerCase()))
ret = 0;
return ret;
}
function GetParamMaxMissedRuns()
{
var tmpParam = MaxSafeMissedRuns;
var lngNumMsgs = parseInt(tmpParam);
if (isNaN(lngNumMsgs) || (lngNumMsgs &lt; 0))
{
CreateEvent(
INVALID_PARAMETER_ID,
EVENT_TYPE_ERROR,
"The parameter \"MaxSafeMissedRuns\" passed to the script is invalid. The value passed was \"" + tmpParam + "\". It must be an integer greater than zero. Using default value (0).");
return(0);
}
return(lngNumMsgs);
}
function GetParamLatencyThreshold()
{
var tmpParam = LatencyThreshold;
var lngNumMsgs = parseInt(tmpParam);
if (isNaN(lngNumMsgs) || (lngNumMsgs &lt;= 0))
{
CreateEvent(
INVALID_PARAMETER_ID,
EVENT_TYPE_ERROR,
"The parameter \"LatencyThreshold\" passed to the script is invalid. The value passed was \"" + tmpParam + "\". It must be an numerical value greater than zero. Using default value (60).");
return(60);
}
return(lngNumMsgs);
}
function GetParamMaxNegativeLatency()
{
var tmpParam = MaxNegativeLatency;
var lngMaxNegativeLatency = parseInt(tmpParam);

if (isNaN(lngMaxNegativeLatency) || (lngMaxNegativeLatency &lt; 0))
{
CreateEvent(
INVALID_PARAMETER_ID,
EVENT_TYPE_ERROR,
"The parameter \"MaxNegativeLatency\" passed to the script is invalid. The value passed was \"" + tmpParam + "\". It must be an numerical value equal or greater than zero. Using default value (30).");

return(30);
}

return(lngMaxNegativeLatency);
}
// Checks if this server is configured to perform any mail flow verification
function IsMailFlowMonitoringEnabled()
{
var blnResult = false;
if ( (IsConfigRegEntryPresent(SEND_TO_MBX_REG_PATH)) ||
(IsConfigRegEntryPresent(SEND_TO_SRV_REG_PATH)) ||
(IsConfigRegEntryPresent(EXPECTED_FROM_REG_PATH)))
{
blnResult = true;
}
return blnResult;
}

</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</DataSource>
</MemberModules>
<Composition>
<Node ID="DS"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
</DataSourceModuleType>