none
Any command/Module to capture the AD account information that was used to authenticate the SMTP server for sending email ? RRS feed

  • Question

  • Hello Everyone,

    In our SMTP environment (MS exchange 2010), we gave permission to an AD Security group in receive connector for sending emails. So new users who want to use SMTP service will be added to this security group. We have around 1K users that are sending emails. We are able to get the account that is used to authenticate while sending emails from Protocol logs(Receive Logs). My requirement is to capture all the email logs with fields -TimeStamp, Client, sender, Receiver, Message subject, Account, SourceServer ...etc. in to a database/csv so we can calculate the utilization by our customers.

    I could get most of the fields from Get-MessageTrackingLog cmdlet but it doesn't give the authenticated account that was used to send the email. So for this, I have to go check the Receive text logs for the sessionID of the email and then filter the account information. Applied this logic in script and it is running as expected but it's taking loooooong time :-) . I have reduced the execution time of the powershell script by applying conditional scans of the text files but since the servers are used heavily, the speed we get the output is making the script unreliable (to pull 30 mins of emails (~40K emails) is taking 3 hours). Could someone please let me know if there is any command or module that can be used to get the Authenticated account information straight away?

    Below is the working script but taking too long time. I know this looks way big but I need to figure out a way to get the service account information quickly.

    #Input parameters for starttime, EndTime and SMTPServer
    [CmdletBinding()]
    param(
        [parameter(Mandatory=$true,
            HelpMessage='Enter time in format MM/DD/YYYY 00:00',
            Position=0)]
            [string]$StartTime,
        [parameter(Mandatory=$true,
            HelpMessage='Enter time in format MM/DD/YYYY 00:00',
            Position=1)]
            [string]$EndTime,
        [parameter(Mandatory=$true,
            HelpMessage='Enter time in format MM/DD/YYYY 00:00',
            Position=2)]
            [string]$Server
    )
    #Import-Exchange powershell module
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
    $LogsPath = "\E$\Receivelogs"
    $Outdata = "\E$\CSVFiles"
    #Save Receive logs into a variable
    $logs1 = Get-MessageTrackingLog -server $Server -EventId Receive -Start $StartTime -End $EndTime -ResultSize unlimited
    #Convert inputted strings into DateTime type
    $first = ([system.DateTime]$StartTime).AddHours(-2).GetDateTimeFormats()[56]
    $last = ([system.DateTime]$EndTime).AddHours(2).GetDateTimeFormats()[56]
    #output filename is based on the start time like "server1 10-10-2017 5:30"
    $filename = "$Server"+" "+((([system.DateTime]$StartTime).GetDateTimeFormats()[65]).ToString()).Replace(":","-")
    #Since we have more than 5K log files, I am filtering files based on first and end times in order to save the process time (+/- 2 hours to be safe)
    $Files = Get-ChildItem "\\$server"+"$LogsPath" | select Name,LastWriteTime,CreationTime | ?{($_.LastWriteTime -le $last) -and ($_.Creationtime -ge $first)}
    for($i=0;$i -lt $logs1.count;$i++)
    {
    #Required properties in output file
    $object = New-Object –TypeName PSObject
    $ReceiveTimeStamp = $logs1[$i].Timestamp.GetDateTimeFormats()[56]
    $EventID = $logs1[$i].EventId
    $ClientName = $logs1[$i].ClientHostname
    $Sender = $logs1[$i].Sender
    $Recipients = [system.String]::Join(",", (($logs1[$i] | select Recipients).Recipients))
    $ClientIP = $logs1[$i].ClientIp
    $InternalMessageId = $logs1[$i].InternalMessageId
    $MessageSubject = $logs1[$i].MessageSubject
    $SMTPServer = $logs1[$i].ServerHostname
    $Source = $logs1[$i].Source
    $SourceContext = $logs1[$i].SourceContext
    $sessionID = $SourceContext.Split(';')[0]
    $RecipientStatus = $logs1[$i].RecipientStatus
    $ReceiveTime = [system.DateTime] $ReceiveTimeStamp
    #Identify the file based on Receive timestamp of the email request
    $file = ($files | ?{($_.LastWriteTime -ge $ReceiveTime) -and ($_.Creationtime -le $ReceiveTime)}).Name
    $object | Add-Member –MemberType NoteProperty –Name ReceiveTimeStamp –Value $ReceiveTimeStamp -Force
    $object | Add-Member –MemberType NoteProperty –Name EventID –Value $EventID -Force
    $object | Add-Member –MemberType NoteProperty –Name ClientName –Value $ClientName -Force
    $object | Add-Member –MemberType NoteProperty –Name ClientIP –Value $ClientIP -Force
    $object | Add-Member –MemberType NoteProperty –Name Sender –Value $Sender -Force
    $object | Add-Member –MemberType NoteProperty –Name Recipients –Value $Recipients -Force
    $object | Add-Member –MemberType NoteProperty –Name MessageSubject –Value $MessageSubject -Force
    $object | Add-Member –MemberType NoteProperty –Name SMTPServer –Value $SMTPServer -Force
    #Now capture the lines with mail sessionid and get only the Authenticated string where we could get the service account information
    $maillog = Select-String -Path "$server+$LogsPath\$file" -Pattern $sessionID | select-string 'Authenticated'
    if ($maillog)
       {
       #trimming to get only the service account name
       $AccountInfo = (($maillog.ToString()).Split('*')[1]).Split(',')[1]
       }
    Else
       {
       #If no "Authenticated" string is found then Account information is a failure
       $AccountInfo = "Failure"
       }
    $object | Add-Member –MemberType NoteProperty –Name AuthenticatedAccount –Value $AccountInfo -Force
    #Save the row to a csv file
    $object | Export-Csv -Path "\\$server\$Outdata\$filename.csv" -Append -Force
    #Nullify all variables
    $object = $Null
    $maillog = $Null
    $ReceiveTimeStamp = $Null
    $EventID = $Null
    $ClientName = $Null
    $Sender = $Null
    $Recipients = $Null
    $ClientIP = $Null
    $InternalMessageId = $Null
    $MessageSubject = $Null
    $SMTPServer = $Null
    $Source = $Null
    $SourceContext = $Null
    $sessionID = $Null
    $RecipientStatus = $Null
    $AccountInfo = $Null
    }

    • Moved by Bill_Stewart Wednesday, October 25, 2017 3:25 PM Move to more appropriate forum
    Wednesday, October 25, 2017 3:22 PM

Answers

  • Hello Folks,, 

    I Sat with my Developer and came up with HashTable logic. We implemented this logic and results are real quick (Enough for my environment). Able to pull 50K records in less than 10 mins in one server. I converted the workflow logic into a simple function (Systems RAM is getting consumed so workflow is of no help) , passed the required cmd line variables and it worked :-).

    Logic used:

    When the script is executed, it will pull all the AD account details from the .log files and place all the values against their sessionIDs. Then I am calling function by passing this variable. Since I already have session ID's and its AD account, output is impressive. Thanks to the HashTable logic my Dev friend :-).

    $AuthAccounts = @{"Key"="Value";}

    foreach($f in $Files)

    {

    $fName = $f|Select -ExpandProperty Name

    $ada= Select-String -Path \\$Server\SmtpReceive\$fName -Pattern "Authenticated" | select-string -Pattern "not authenticated" -NotMatch -AllMatches

    foreach($line in $ada)

    {

    $l=$line.Line.Split(',')

    $SessionId = $l[2]

    $Adaccount = $l[7]

    $AuthAccounts.Add($SessionId,$Adaccount)

    }

    }
    • Marked as answer by KB Ramana Monday, December 25, 2017 10:26 AM
    Monday, December 25, 2017 10:26 AM