Question
· May 1, 2023

Email Alert - EnsLib.EMail.OutboundAdapter Error

I am running into an error trying to send an Alert Email to test the functionality of IRIS HealthShare Health Connect  2022.1 compared to Cache HealthShare Health Connect 2018.1.3. I was trying to send an Alert email, when I am getting the following error on my EMailAlert operation which is using EnsLib.EMail.OutboundAdpater.

ERROR <Ens>ErrException: <UNDEFINED>FText+4 ^%occMessages *msg -- logged as '-'
number - @''

I verified the message to the EMailAlert was populated, so what could be throwing this error...

 

I found the problem to be with osuwmc.AlertEmail that was created to shorten the data within the email from EnsLib.Email.OutboundAdapter. Can someone take a look at the following code to see if it needs updated for some reason???


Class osuwmc.AlertEmail Extends Ens.Alerting.NotificationOperation [ ClassType = "", ProcedureBlock ]
{

Parameter ADAPTER = "EnsLib.EMail.OutboundAdapter";

Parameter SETTINGS = "IncludeDetails:Basic,SubjectPrefix:Basic,IncludeNodeinSubject:Basic,IncludeManagedAlertHistory:Basic";

Property Adapter As EnsLib.EMail.OutboundAdapter;

/// Control whether detailed information is added to emails sent for standard <class>Ens.AlertRequest</class>
/// messages. The default is 0 (or False) for backward compatibility reasons.
Property IncludeDetails As %Boolean [ InitialExpression = 0 ];

/// Control whether all Managed Alert actions will be included in the email, and the order in which the actions are included.
Property IncludeManagedAlertHistory As %Integer(DISPLAYLIST = ",False,Oldest First,Newest First", VALUELIST = ",0,1,2") [ InitialExpression = 0 ];

/// Prefix to include in the subject of emails sent by this system.
Property SubjectPrefix As %String;

/// This controls whether network information for the node is included in the subject of the outgoing email.
/// If you have many Ensemble installations on multiple systems, this may make it much
/// simpler to identify which system issued an alert.
Property IncludeNodeinSubject As %Boolean [ InitialExpression = 0 ];

/// Property to hold the basic text used to separate sub-sections of each email message.
Property SepLine As %String [ InitialExpression = "===============================================================" ];

Method OnMessage(pRequest As %Library.Persistent, Output pResponse As Ens.Response) As %Status
{
    If pRequest.%Extends("Ens.Alerting.NotificationRequest") {
        Quit ..OnAlertNotification(pRequest,.pResponse)
    }
    Quit ..OnAlertRequest(pRequest,.pResponse)
}

/// Main handler for requests of type <class>Ens.AlertRequest</class>.
/// If <property>IncludeDetails</property> is true, then the actual output will be
/// performed in <method>CreateEmailFromAlertRequest</class>.
Method OnAlertRequest(pAlertRequest As Ens.AlertRequest, Output pResponse As Ens.Response) As %Status
{
    If ..IncludeDetails {
        Set tSC = ..CreateEmailFromAlertRequest(pAlertRequest,.tMailMessage)
        If $$$ISERR(tSC) Quit tSC
    }
    Else {
        Set tMailMessage = ##class(%Net.MailMessage).%New()
        Set tMailMessage.Subject = "Ensemble alert from " _ ..InstanceName _ ":"_pAlertRequest.SourceConfigName
        Set tMailMessage.Charset = "iso-8859-1"
        If (pAlertRequest.AlertDestination '= "") {
            #; if the Ens.AlertRequest supplied an AlertDestination, then add it to the list of configured Recipients
            Set tSC=..Adapter.AddRecipients(tMailMessage, pAlertRequest.AlertDestination)  Quit:$$$ISERR(tSC) tSC
        }
        Set tSC = tMailMessage.TextData.Write(pAlertRequest.AlertText)
        Quit:$$$ISERR(tSC) tSC
    }
    Quit ..Adapter.SendMail(tMailMessage)
}

/// Create a notification email from a standard <class>Ens.AlertRequest</class> object.
Method CreateEmailFromAlertRequest(pAlertRequest As Ens.AlertRequest, Output pMailMessage As %Net.MailMessage) As %Status
{
    $$$LOGINFO("CreateEmailFromAlertRequest")
    Set tStatus = $$$OK
    Try {
        Set pMailMessage = ##class(%Net.MailMessage).%New()
        Set pMailMessage.Charset = "UTF-8"
        Set pMailMessage.Subject = ..SubjectPrefix _ $select(..SubjectPrefix '= "": " ", 1: "")

        Do ..GetSystemInfo(,.tSystemName,.tInstanceName,.tNodeName)

        If ..IncludeNodeinSubject {
            Set pMailMessage.Subject = pMailMessage.Subject _ $$$FormatText($$$Text("Ensemble Alert from configuration item '%1' in system '%2' on node '%3'","Ensemble"),pAlertRequest.SourceConfigName,tSystemName,tNodeName)
        }
        Else {
            Set pMailMessage.Subject = pMailMessage.Subject _ $$$FormatText($$$Text("Ensemble Alert from configuration item '%1' on system '%2'","Ensemble"),pAlertRequest.SourceConfigName,tSystemName)
        }

        If (pAlertRequest.AlertDestination '= "") {
            Set tStatus = ..Adapter.AddRecipients(pMailMessage, pAlertRequest.AlertDestination)
            If $$$ISERR(tStatus) Quit
        }
        Set tNow = $$$timeUTC
        Set tNowLocal = $$$timeUTCtoLocal(tNow)
        Set tTimeMessage = $select(..IncludeUTCTimes: $$$FormatText($$$Text("Ensemble alert email triggered at %1 [%2 UTC]","Ensemble"),tNowLocal,tNow), 1 : $$$FormatText($$$Text("Ensemble alert email triggered at %1","Ensemble"),tNowLocal))
        Set tStatus = pMailMessage.TextData.WriteLine(tTimeMessage)
        If $$$ISERR(tStatus) Quit
        Set tStatus = ..AddBasicData(pMailMessage,pAlertRequest.AlertText,pAlertRequest.AlertTime,pAlertRequest.SourceConfigName,$get($$$EnsRuntime("Name")),pAlertRequest.SessionId,tSystemName,tInstanceName)
        If $$$ISERR(tStatus) Quit
    }
    Catch {
        Set tStatus = $$$EnsSystemError
    }
    Quit tStatus
}

/// Send a notification email for the incoming <class>Ens.Alerting.NotificationRequest</class> in <var>pNotificationRequest</var>.
Method OnAlertNotification(pNotificationRequest As Ens.Alerting.NotificationRequest, Output pResponse As Ens.Response) As %Status
{
    $$$LOGINFO("OnAlertNotification")
    Set tStatus = $$$OK
    Try {
        Set tMailMessage = ##class(%Net.MailMessage).%New()
        Set tMailMessage.Charset = "UTF-8"
        Set tMailMessage.Subject = $select(..SubjectPrefix '= "": ..SubjectPrefix _ " ", 1: "")

        Set tManagedAlert = pNotificationRequest.ManagedAlert
        Do ..GetSystemInfo(tManagedAlert,.tSystemName,.tInstanceName,.tNodeName)
        
        If ..IncludeNodeinSubject {
            Set tMailMessage.Subject = tMailMessage.Subject _ $$$FormatText($$$Text("Ensemble ManagedAlert from configuration item '%1' in system '%2' on node '%3'","Ensemble"),tManagedAlert.SourceConfigName,tSystemName,tNodeName)
        }
        Else {
            Set tMailMessage.Subject = tMailMessage.Subject _ $$$FormatText($$$Text("Ensemble ManagedAlert from configuration item '%1' on system '%2'","Ensemble"),tManagedAlert.SourceConfigName,tSystemName)
        }
        If pNotificationRequest.NotificationType '= $$$eAlertNotificationRequest {
            Set tUpdateSubject = $case(pNotificationRequest.NotificationType, 
                $$$eAlertNotificationReminder: $$$Text("Reminder","Ensemble"),
                $$$eAlertNotificationEscalationChange: $$$Text("Escalation Change","Ensemble"),
                : "")
            If (tUpdateSubject '= "") {
                Set tMailMessage.Subject = tMailMessage.Subject _ " [" _ tUpdateSubject _ "]"
            }
            Set tStatus = ..GetUpdateText(pNotificationRequest,.tUpdateText)
            If $$$ISERR(tStatus) Quit
            //If ($get(tUpdateText) '= "") {
            //    Set tStatus = tMailMessage.TextData.WriteLine(tUpdateText)
            //    If $$$ISERR(tStatus) Quit
            //    Set tStatus = tMailMessage.TextData.WriteLine(..SepLine)
            //    If $$$ISERR(tStatus) Quit
            //}
        }

        For i=1:1:pNotificationRequest.AlertDestinations.Count() {
            Set tDestination = pNotificationRequest.AlertDestinations.GetAt(i)
            If (tDestination '= "") {
                Set tStatus = tMailMessage.To.Insert(tDestination)
                If $$$ISERR(tStatus) Quit
            }
        }
        If $$$ISERR(tStatus) Quit

        Set tStatus = ..AddBasicData(tMailMessage,tManagedAlert.AlertText,tManagedAlert.AlertTime,tManagedAlert.SourceConfigName,tManagedAlert.Production,tSystemName,tInstanceName)
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine(..SepLine)
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Managed Alert Data","Ensemble"))
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine(..SepLine)
        //If $$$ISERR(tStatus) Quit

        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Managed Alert ID","Ensemble") _ ":" _ $char(9,9) _ tManagedAlert.%Id())
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Next Action Time","Ensemble") _ ":" _ $char(9,9) _ $$$timeUTCtoLocal(tManagedAlert.NextActionTime) _ $select(..IncludeUTCTimes: "  [" _ tManagedAlert.NextActionTime _ " UTC]", 1: ""))
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Escalation Level","Ensemble") _ ":" _ $char(9,9) _ tManagedAlert.EscalationLevel)
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Current Owner","Ensemble") _ ":" _ $char(9,9) _ $select(tManagedAlert.CurrentOwner = "": "[" _ $$$Text("No current owner","Ensemble") _ "]", 1: tManagedAlert.CurrentOwner))
        //If $$$ISERR(tStatus) Quit
        //Set tLastActionTime = tManagedAlert.LastActionTime
        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Last Action Time","Ensemble") _ ":" _ $char(9,9) _ $$$timeUTCtoLocal(tLastActionTime) _ $select(..IncludeUTCTimes: "  [" _ tLastActionTime _ " UTC]", 1: ""))
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = tMailMessage.TextData.WriteLine($$$Text("Next Monitor Time","Ensemble") _ ":" _ $char(9,9) _ $$$timeUTCtoLocal(tManagedAlert.NextMonitorTime) _ $select(..IncludeUTCTimes: "  [" _ tManagedAlert.NextMonitorTime _ " UTC]", 1: ""))
        //If $$$ISERR(tStatus) Quit
        
        //If ..IncludeManagedAlertHistory {
        //    Set tStatus = ..AddManagedAlertHistory(tMailMessage,tManagedAlert)
        //    If $$$ISERR(tStatus) Quit
        //}
        
        Set tStatus = ..Adapter.SendMail(tMailMessage)
        If $$$ISERR(tStatus) Quit
    }
    Catch {
        Set tStatus = $$$EnsSystemError
    }
    Quit tStatus
}

/// Helper method to write properties common to basic <class>Ens.AlertRequest</class> and
/// <class>Ens.Alerting.ManagedAlert</class> instances.
Method AddBasicData(pMailMessage As %Net.MailMessage, pAlertText As %String = "", pAlertTime As Ens.DataType.UTC = "", pSourceConfigName As %String = "", pProduction As %String = "", pSessionId As %Integer = "", pSystemName As %String = "", pInstanceName As %String = "") As %Status
{
    $$$LOGINFO("AddBasicData")
    Set tStatus = $$$OK
    Try {
        Set tStatus = pMailMessage.TextData.WriteLine(pAlertText)
        //$$$Text("Alert Text","Ensemble") _ ":" _ $char(9,9) _ 
        If $$$ISERR(tStatus) Quit
        //Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Alert Time","Ensemble") _ ":" _ $char(9,9) _ $select(pAlertTime = "" : $$$Text("Unknown","Ensemble"), 1: $$$timeUTCtoLocal(pAlertTime) _ $select(..IncludeUTCTimes: "  [" _  pAlertTime _ " UTC]", 1: "")))
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Production","Ensemble") _ ":" _ $char(9,9) _ $select(pProduction = "": $$$Text("Unknown","Ensemble"), 1: pProduction))
        //If $$$ISERR(tStatus) Quit
        //Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Source","Ensemble") _ ":" _ $char(9,9) _ pSourceConfigName)
        //If $$$ISERR(tStatus) Quit
        //If (pSessionId '= "") {
        //    Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Session","Ensemble") _ ":" _ $char(9,9) _ pSessionId)
        //    If $$$ISERR(tStatus) Quit
        //}
        //If (pSystemName '= "") {
        //    Set tStatus = pMailMessage.TextData.WriteLine($$$Text("System","Ensemble") _ ":" _ $char(9,9) _ pSystemName)
        //    If $$$ISERR(tStatus) Quit
        //}
        //If (pInstanceName '= "") {
        //    Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Instance","%Utility") _ ":" _ $char(9,9) _ pInstanceName)
        //    If $$$ISERR(tStatus) Quit
        //}
        
        //Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Node","Ensemble") _ ":" _ $char(9,9) _ ##class(%SYS.System).GetNodeName())
        //If $$$ISERR(tStatus) Quit
    }
    Catch {
        Set tStatus = $$$EnsSystemError
    }
    Quit tStatus
}

/// Helper method to write out the Managed Alert History for a given ManagedAlert instance.
Method AddManagedAlertHistory(pMailMessage As %Net.MailMessage, pManagedAlert As Ens.Alerting.ManagedAlert) As %Status
{
    $$$LOGINFO("AddManagedAlertHistory")
    Set tStatus = $$$OK
    Try {
        Set tActionCount = pManagedAlert.Actions.Count()
        If (tActionCount > 0) {
            Set tStatus = pMailMessage.TextData.WriteLine(..SepLine)
            If $$$ISERR(tStatus) Quit
            Set tStatus = pMailMessage.TextData.WriteLine($$$Text("Managed Alert Action History","Ensemble"))
            If $$$ISERR(tStatus) Quit
            Set tStatus = pMailMessage.TextData.WriteLine(..SepLine)
            If $$$ISERR(tStatus) Quit
            If ..IncludeManagedAlertHistory = 1 {
                Set tStart = tActionCount
                Set tIncrement = -1
                Set tEnd = 1
            }
            Else {
                Set tStart = 1
                Set tIncrement = 1
                Set tEnd = tActionCount
            }
            For i=tStart:tIncrement:tEnd {
                Set tAction = pManagedAlert.Actions.GetAt(i)
                If $IsObject(tAction) {
                    Set tStatus = pMailMessage.TextData.WriteLine("(" _ i _ ")" _ $char(9,9) _ $$$Text("Action Time","Ensemble") _ ": " _ $$$timeUTCtoLocal(tAction.ActionTime) _ $select(..IncludeUTCTimes: " [" _ tAction.ActionTime _ " UTC]", 1: ""))
                    If $$$ISERR(tStatus) Quit
                    Set tStatus = pMailMessage.TextData.WriteLine($char(9,9) _ $$$Text("User","Ensemble") _ ": " _ tAction.Username)
                    If $$$ISERR(tStatus) Quit
                    Set tStatus = pMailMessage.TextData.WriteLine($char(9,9) _ $$$Text("Reason","Ensemble") _ ": " _ tAction.Reason)
                    If $$$ISERR(tStatus) Quit
                    #; Only write out changes if there are any
                    If (tAction.OldValues.Next("") '= "") {
                        Set tStatus = pMailMessage.TextData.WriteLine($char(9,9) _ $$$Text("Changed Values","Ensemble") _ ":")
                        If $$$ISERR(tStatus) Quit
                        Set tPropName = ""
                        For {
                            Set tOldValue = tAction.OldValues.GetNext(.tPropName)
                            If (tPropName = "") Quit
                            Set tNewValue = tAction.NewValues.GetAt(tPropName)
                            Set tStatus = pMailMessage.TextData.WriteLine($char(9,9,9) _ tPropName _": '" _ tOldValue _ "' => '" _ tNewValue _ "'")
                            If $$$ISERR(tStatus) Quit
                        }
                        If $$$ISERR(tStatus) Quit
                    }
                    Set tStatus = pMailMessage.TextData.WriteLine()
                    If $$$ISERR(tStatus) Quit
                }
            }
        }
    }
    Catch {
        Set tStatus = $$$EnsSystemError
    }
    Quit tStatus
}

}

Product version: IRIS 2022.1
$ZV: IRIS for UNIX (Red Hat Enterprise Linux 8 for x86-64) 2022.1 (Build 209U) Tue May 31 2022 12:13:24 EDT
Discussion (5)3
Log in or sign up to continue

I see what you mean in 2022.1 it will not compile but however it does compile in 2018.1.3.

2022.1

Compilation started on 05/02/2023 08:05:23 with qualifiers 'cuk'

Compiling class osuwmc.AlertEmail

Compiling routine osuwmc.AlertEmail.1

ERROR: osuwmc.AlertEmail.cls

ERROR:  osuwmc.AlertEmail.1(13) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' in system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",2740803238),/ensemble/TEST/mgr/enslib/' on node '%3'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set pMailMessage.Subject = pMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' in system '%2' on node '%3'""","""Ensemble"""))),pAlertRequest.SourceConfigName,tSystemName,tNodeName)

ERROR:  osuwmc.AlertEmail.1(16) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' on system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",3633416132),/ensemble/TEST/mgr/enslib/'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set pMailMessage.Subject = pMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' on system '%2'""","""Ensemble"""))),pAlertRequest.SourceConfigName,tSystemName)

ERROR:  osuwmc.AlertEmail.1(25) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble alert email triggered at %1 [<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",2328442859),/ensemble/TEST/mgr/enslib/ UTC]""","""Ensemble"""))' failed with an error: %2

 TEXT:    Set tTimeMessage = $select(..IncludeUTCTimes: $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble alert email triggered at %1 [%2 UTC]""","""Ensemble"""))),tNowLocal,tNow), 1 : $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble alert email triggered at %1""","""Ensemble"""))),tNowLocal))

ERROR:  osuwmc.AlertEmail.1(25) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble alert email triggered at %1""","""Ensemble"""))' failed with an error: <PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",3301903811),/ensemble/TEST/mgr/enslib/

 TEXT:    Set tTimeMessage = $select(..IncludeUTCTimes: $$FormatText^%occMessages(,tNowLocal,tNow), 1 : $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble alert email triggered at %1""","""Ensemble"""))),tNowLocal))

ERROR: osuwmc.AlertEmail.cls

ERROR:  osuwmc.AlertEmail.1(14) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' in system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",197323985),/ensemble/TEST/mgr/enslib/' on node '%3'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set tMailMessage.Subject = tMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' in system '%2' on node '%3'""","""Ensemble"""))),tManagedAlert.SourceConfigName,tSystemName,tNodeName)

ERROR:  osuwmc.AlertEmail.1(17) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' on system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",466437042),/ensemble/TEST/mgr/enslib/'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set tMailMessage.Subject = tMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' on system '%2'""","""Ensemble"""))),tManagedAlert.SourceConfigName,tSystemName)

Detected 6 errors during compilation in 0.091s.

2018.1.3

Compilation started on 05/02/2023 08:13:51 with qualifiers 'cuk'

Class osuwmc.AlertEmail is up-to-date.

Compilation finished successfully in 0.199s.

Hi @Scott Roth 

Like the @Jeffrey Drumm told, the problem are because the Database ENSLIB are Read Only. The error occur because you are using the Macros $$$FormatText and $$$Text.

When you use $$$Text macro, the macro try to create a entry in the global ^IRIS.Msg. The global ^IRIS.Msg is mapped from ENSLIB database that is by default Read Only. See imagem bellow that the ^IRIS.Msg("ENSEMBLE") is mapped, but the root global ^IRIS.Msg is mapped to the namespace data base.

To solve the compilation error do change calls to $$$Text("some text", "Ensemble") for some think like $$$Text("some text", "MyDomain")

Click in Replace all

Then compile:

For more information see the documentation String Localization and Message Dictionaries

Regrads.