Knowledge Base Article

Extender: User Inactivity Email

This Extender can be executed in a Data Management step to automate emailing details of an auto-expiring account to the related user.

Imports System
Imports System.Data
Imports System.Data.Common
Imports System.IO
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Linq
Imports Microsoft.VisualBasic
Imports System.Threading
Imports System.Windows.Forms
Imports OneStream.Shared.Common
Imports OneStream.Shared.Wcf
Imports OneStream.Shared.Engine
Imports OneStream.Shared.Database
Imports OneStream.Stage.Engine
Imports OneStream.Stage.Database
Imports OneStream.Finance.Engine
Imports OneStream.Finance.Database

'** IMPORTANT! Update "InactiveEmailNotification" in line below 
'   with actual name of the Extender business rule you created
Namespace OneStream.BusinessRule.Extender.InactiveEmailNotification 

	Public Class MainClass
		Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As ExtenderArgs) As Object
			'---------------------------------------------------------------------------------------
			'Description:	User Expiration Warning
			'
			'Usage:	Sends an email to users prior their account auto expire date. 
			'       This Snippet should replace an entire rule as it includes non-standard Imports [Lines 1-18]
			'
			'Notes:	Administrator must set the following values prior to use:
			'			BusinessRuleName [Line 20]
			'			EmailConnectionName [Line 58]
			'			UserWarningThreshold [Line 61]
			'			EmailTitle [Line 64]
			'			EmailMessage [Line 68-75]
			'			EmailList [Line 78]
			'
			'Created By:	OneStream Software
			'Date Created:	09-15-2020
			'---------------------------------------------------------------------------------------
			Try
				Select Case args.FunctionType
					Case Is = ExtenderFunctionType.Unknown
						Me.EmailNotification(si)
					Case Is = ExtenderFunctionType.ExecuteDataMgmtBusinessRuleStep
						Me.EmailNotification(si)
				End Select

				Return Nothing
			Catch ex As Exception
				Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
			End Try
		End Function

#Region "General Helpers"
		Public Sub EmailNotification(ByVal si As SessionInfo)
			Try
				'Specify the email connection (Defined in Application Server setup)
				Dim emailConnectionName As String = "OneStreamEmail"
				'Enter number of days prior to user expiration that warning will be sent.
				' Email will only be sent if "Remaining Allowed Inactivity" is less than or equal to threshold days.
				Dim userWarningThreshold As Double = 20
				'Define the the email title to be sent.  The value [days] will be updated during processing.
				Dim emailTitle As String = "OneStream User ID Expiration - [days] day warning"
				'Define the the email body to be sent.
				'  [user] & [days] will automatically be replaced, during processing,
				'  with the OneSteam Username & number of days till expiration.
				Dim emailMessage As New Text.StringBuilder
				emailMessage.AppendLine("Attention: [user]")
				emailMessage.AppendLine("")
				emailMessage.AppendLine("Your login for OneStream will expire in [days] due to inactivity."
				emailMessage.AppendLine("Please login as soon as possible.")
				emailMessage.AppendLine("")
				' replace xxx in text below with relevant email address
				emailMessage.AppendLine("If you require assistance, please contact xxxx .") 
				emailMessage.AppendLine("")
				emailMessage.AppendLine("Thank you.")
				emailMessage.AppendLine("The Support Team")
				
				'Define any additional email addresses to include other than the user that is expiring.
				' All emails will be listed in the "To: field" of the email.
				Dim emailList As New List(Of String)
				' Uncomment following lines if necessary and update with relevant addresses.
				'emailList.Add("emailaddress1@customer.com")
				'emailList.Add("emailaddress2@customer.com")
				' If you need more addresses, just add more lines like the ones above
				
				'Account Expiration Warning
				Me.ValidateUserExpiration(si, emailConnectionName, _
					userWarningThreshold, emailTitle, emailMessage.ToString, emailList)
				
			Catch ex As Exception
				Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
			End Try
		End Sub

		Public Sub ValidateUserExpiration(ByVal si As SessionInfo, ByVal emailConnectionName As String, _
				ByVal userWarningThreshold As Double, ByVal emailTitle As String, 
				ByVal emailMessage As String, ByVal emailList As List(Of String))
			Try
				Dim dtResults As New DataTable
				Using dbConnApp As DbConnInfo = BRAPi.Database.CreateApplicationDbConnInfo(si)
					Dim ds As DataSet = BRApi.Database.ExecuteMethodCommand( _
						dbConnApp, XFCommandMethodTypeID.Users, "{}", "Users", Nothing)
					If Not ds Is Nothing Then
						Dim dt As DataTable = ds.Tables(0).Copy
						Dim userID As Guid = Guid.Empty
						Dim userName As String = String.Empty
						Dim remainingDays As Double = 0
						Dim updatedEmailList As New List(Of String)
						Dim updatedEmailTitle As String = String.Empty
						Dim updatedEmailMessage As String = String.Empty
						Dim objUserInfoAndStatus As UserInfoAndStatus = BRApi.Security.Admin.GetUserAndStatus( _
																			si, si.UserName)
						For Each dr As DataRow In dt.Rows
							'Filter out inactive users and users without a defined email address
							If(dr(4).ToString().XFContainsIgnoreCase("TRUE")) And (Not String.IsNullOrEmpty(dr(7).ToString)) Then
								'Get UserName and UserInfoAndStatus
								userName = dr(1)
								objUserInfoAndStatus = BRApi.Security.Admin.GetUserAndStatus(si, userName)
								If objUserInfoAndStatus.LogonStatus.GetNumDaysOfRemainingAllowedInactivity <= userWarningThreshold Then
									remainingDays = objUserInfoAndStatus.LogonStatus.GetNumDaysOfRemainingAllowedInactivity
									'Reset email list for next user
									updatedemailList.Clear
									updatedemailList.AddRange(emailList)
									'Add user to email list
									updatedemailList.Add(dr(6).ToString)
									'Replace [days] & [user] values in email EmailTitle and EmailMessage
									updatedEmailTitle = emailTitle.Replace( _
											"[days]", ConvertHelper.ToInt32(remainingDays))
									updatedEmailMessage = emailMessage.Replace( _
											"[days]", ConvertHelper.ToInt32(remainingDays))
									updatedEmailMessage = updatedEmailMessage.Replace( _
											"[user]", userName)
									'Send the email using a worker background thread
									Dim mailThread As New SendMailThread(si, _
											emailConnectionName, updatedemailList, _
											updatedEmailTitle, updatedEmailMessage, Nothing)
									mailThread.Start
								End If
							End If
						Next
					End If
				End Using
			Catch ex As Exception
				Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
			End Try
		End Sub

#End Region
#Region "Constants and Enumerations"
		'String Messages
		Public m_MsgNoEmailConnection As String = "Cannot Send Notifications: Email Connection must be specified."

#End Region
		Public Class SendMailThread

#Region "Module Level Variables"
			Private Const m_ThreadNamePrefix As String = "XF Send Mail Thread"
			Private m_SI As SessionInfo = Nothing
			Private m_MailConnectionName As String = String.Empty
			Private m_ToEmailAddresses As New List(Of String)
			Private m_Subject As String = String.Empty
			Private m_Body As String = String.Empty
			Private m_AttachmentFilePaths As New List(Of String)
			Private m_WorkerThread As Thread

#End Region
#Region "Constructor"
			Public Sub New(ByVal si As SessionInfo, ByVal mailConnectionName As String, _
					ByVal toEmailAddresses As List(Of String), ByVal subject As String, _
					ByVal body As String, ByVal attachmentFilePaths As List(Of String))
				'Copy the input parameters so the background thread can access them.
				m_SI = si
				m_MailConnectionName = mailConnectionName
				m_ToEmailAddresses = toEmailAddresses
				m_Subject = subject
				m_Body = body
				m_AttachmentFilePaths = attachmentFilePaths
			End Sub

#End Region
#Region "Public Methods"
			Public Sub Start()
				Try
					'Create the Background Thread
					m_WorkerThread = New Thread(AddressOf Me.WorkerThreadMethod)
					'We don't want this worker thread to keep the process from being shut down.
					m_WorkerThread.IsBackground = True 
					'Naming thread to provide a unique recognizable marker when debugging.
					m_WorkerThread.Name = m_ThreadNamePrefix & " " & Guid.NewGuid().ToString("N") 
					XFWcfOperationInvoker.SetCultureInfoForUserToThread(m_SI, m_WorkerThread)
					m_WorkerThread.Start()
				Catch ex As Exception
					Throw ErrorHandler.LogWrite(m_SI, New XFException(m_SI, ex))
				End Try
			End Sub

#End Region
#Region "Private Methods"
			Private Sub WorkerThreadMethod()
				Try
					'Send the email
					BRApi.Utilities.SendMail(m_SI, m_MailConnectionName, m_ToEmailAddresses, m_Subject, m_Body, m_AttachmentFilePaths)
				Catch ex As Exception
					'Important: do not re-throw the exception from this worker thread since it will be processed by .NET as an unhandled exception.
					'Even if an exception could be processed normally, it couldn't be sent back to the client via WCF because the client isn't
					'waiting for a WCF method to complete and the client might not not even be logged on anymore.
					Try
						BRApi.ErrorLog.LogError(m_SI, ex)
					Catch
					End Try

				End Try
			End Sub
#End Region
		End Class
	End Class
End Namespace
Updated 2 years ago
Version 3.0