Advertisement
Guest User

process_alert_reply_email.ps1

a guest
Aug 18th, 2016
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #
  2. # Originally from https://thwack.solarwinds.com/docs/DOC-188081
  3. # Posted on pastebin to get assistance with script breaking
  4. # ----------------------------------------------------------------------------
  5. # process_alert_reply_email.ps1
  6. #
  7. # Retrieve unread messages in a specified Exchange mailbox, then strip out
  8. # the Solarwinds alert definition ID, the object that triggered the alert,
  9. # and the object type (Solarwinds requires all three to handle an alert).
  10. #
  11. # This script assumes that the first word in the email message is a
  12. # command verb such as ack or comment. Any text between the command and a
  13. # return and/or newline character(s) is treated as a comment, and it will
  14. # be appended to the alert in Solarwinds.
  15. #
  16. # Message syntax
  17. # --------------
  18. # At minimum, the email message must contain these elements, formatted as
  19. # described below. These elements can appear anywhere in the message body.
  20.  
  21. # Alert definition ID: A GUID in brackets, formatted like this:
  22. #     [AlertDefinition=D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D]
  23. # Object ID: A string of digits, in brackets, formatted like this:
  24. #     [ObjectID=99999]
  25. # Object Type: A string representing a valid Solarwinds object type, formatted
  26. # like this:
  27. #     [ObjectType=APM: Application]
  28. #
  29. # Commands
  30. # --------
  31. # The command must be the first word in the message body.
  32. #
  33. # ack:     Acknowledge the alert and append a comment if one is supplied.
  34. # comment: Append a comment to the alert
  35. #
  36. # Comments
  37. # --------
  38. # Comments are optional. Any text between the command verb and a newline or return
  39. # character will be treated as a comment. There are no formatting requirements
  40. # for comments.
  41. #
  42. # Example
  43. # -------
  44. # This message would acknowledge an alert and append a comment.
  45. #
  46. #    Ack Kurt is looking into this
  47. #    ~~~~~~~~~~~~~~~~~~~~~
  48. #    Me, Senior Systems Administrator
  49. #    ~~~~~~~~~~~~~~~~~~~~~~
  50. #    From: Solarwinds
  51. #    Sent: Friday, October 02, 2015 12:33 PM
  52. #    To: Me <me@myemail.com>
  53. #    Subject: Solarwinds Alert: Oracle database disk utilization KURTSDB on Node kurtsserver.mydomain.com is Down
  54. #    
  55. #    When replying, type your text above this line
  56. #    ________________________________________
  57. #    
  58. #    To acknowledge this alert, click here or reply to this message with "ack" as the first word in the body.
  59. #    
  60. #    Alert details:
  61. #    Oracle database disk utilization KURTSDB on Node kurtsserver.mydomain.com is Down at Friday, October 2, 2015 12:32 PM.
  62. #    
  63. #    When replying, do not delete text below
  64. #    ________________________________________
  65. #    
  66. #    [AlertDefinition=535d1493-a543-4df0-acbf-6b43770aceeb] [ObjectID=1271][ObjectType=APM: Application]
  67. #
  68. # Example
  69. # -------
  70. # This message would also acknowledge an alert and append a comment
  71. #
  72. #    Ack  Third alert comment from ME
  73. #    [AlertDefinition=535d1493-a543-4df0-acbf-6b43770aceeb] [ObjectID=673] [ObjectType=APM: Application]
  74. # ----------------------------------------------------------------------------
  75. #
  76. # Thanks
  77. # ------
  78. # Many thanks to everyone who shared code, answers, and insights online, for
  79. # you made this code possible.
  80. #
  81.  
  82.  
  83. # Load the Solarwinds snapin
  84. Add-PSSnapin SwisSnapin  
  85.  
  86. # Process-Message ($message)
  87. # $message: An object representing and Exchange email message
  88. function Process-Message ($message) {
  89.     $subject = $message.Subject
  90.     $fromName = $message.From.Name
  91.     $fromAddress = $message.From.Address
  92.  
  93.     # MM We want to look for white spaces when finding the comment
  94.     # Replace any whitespace in the message body with a single space
  95.     #$body = $message.Body.Text -replace '\s+', ' '
  96.     $body = $message.Body.Text
  97.  
  98.     # Search for a regular expression matching a string of word characters, digits, and dashes surrounded by "[AlertDefinition=]"
  99.     # and retrieve the Alert Definition ID
  100.     if ($body -match "\[AlertDefinition=([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12})\]") {
  101.         $alertDefID = $Matches[1]
  102.     }
  103.     else {
  104.         throw [System.Exception] "Message must contain an Alert Definition ID like [AlertDefinition=D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D]"
  105.         exit 1
  106.     }
  107.    
  108.  
  109.     # Search for a regular expression matching a string of digits surrounded by "[ObjectID=]"
  110.     # and retrieve the Object ID
  111.     if ($body -match "\[ObjectID=([0-9]+)\]") {
  112.         $objectID = $Matches[1]
  113.     }
  114.     else {
  115.         throw [System.FormatException] "Message must contain an Object ID like [ObjectID=99999]"
  116.         exit 1
  117.     }
  118.    
  119.  
  120.     # Search for a regular expression matching a string of word characters, spaces, periods, and colons) surrounded by "[ObjectType=]"
  121.     # and retrieve the Object Type
  122.     if ($body -match "\[ObjectType=([\d\w\s\.\:]+)\]") {
  123.         $objectType = $Matches[1].Trim()
  124.     }
  125.     else {
  126.         throw [System.FormatException] "Message must contain an Object Type like [ObjectID=APM Application]"
  127.         exit 1
  128.     }
  129.    
  130.  
  131.     # Strip off the first word of the body - this should be the command
  132.     if ($body -match "^(\S+)\s") {
  133.         $command = $Matches[1]
  134.     }
  135.     else {
  136.         throw [System.FormatException] "Message must include a command"
  137.         exit 1
  138.     }
  139.    
  140.     # By default, add a comment with the sender's address and timestamp
  141.     # Use the '+' operator because Powershell does something odd with the date string
  142.     $comment = (Get-Date).ToString('M-dd-yyyy HH:mm:ss') + " Updated by "+ $fromName + " (" + $fromAddress +")"
  143.  
  144.     # Strip off everything between the first word and the return or newline
  145.     # and add it to the default comment
  146.     #if ($body -match "^\S+\s+([^\[\r\n]*)\s") {
  147.     if ($body -match "^\S+\s+([^\[\r\n]|^\r\n|[\w\s!""#$%&'()*+,\-\./:;<=>?@\\^`{|}~]*)\s") {
  148.         $comment = $comment + ": " + $Matches[1]
  149.     }
  150.  
  151.     Write-Host "Alert Definition ID ", $alertDefID
  152.     Write-Host "Object ID ", $objectID
  153.     Write-Host "Object Type ", $objectType
  154.     Write-Host "Command ", $command
  155.     Write-Host "Comment '",$comment,"'"
  156.  
  157.     #Hand off the command to the appropriate function
  158.     try {
  159.     switch ($command.ToLower()) {
  160.         "ack" {
  161.             Acknowledge-Alert $alertDefID $objectID $objectType $comment
  162.         }
  163.         "comment" {
  164.             Comment-Alert $alertDefID $objectID $objectType $comment
  165.         }
  166.         default {
  167.             throw [System.FormatException] "The ",$command," command is not supported."
  168.             exit 1
  169.         }
  170.     }
  171.     } catch {
  172.         Write-Host $_.Exception.Message
  173.         throw $_.Exception
  174.     }
  175.  
  176.     return $true
  177.  
  178. }
  179.  
  180. # Acknowledge-Alert ($alertDefId, $objectId, $objectType)
  181. # alertDefId: GUID, The ID of the alert definition that was fulfilled to produce this alert
  182. #             Corresponds to Orion.AlertStatus.AlertDefID
  183. # objectID:   Integer, The ID of the object that triggered the alert
  184. #             Corresponds to Orion.AlertStatus.ActiveObject
  185. # objectType: String, The name of the type of object that triggered the alert
  186. #             Corresponds to Orion.AlertStatus.ObjectType
  187. # comment:    String, A comment to append to the alert
  188. #             Corresponds to Orion.AlertStatus.Notes
  189. #
  190. function Acknowledge-Alert () {
  191.     Param(
  192.     [String] $alertDefId,
  193.     [String] $objectId,
  194.     [String] $objectType,
  195.     [String] $comment = ""
  196.     )
  197.     $swis = Connect-Swis $SWServer -UserName $SWUsername -Password $SWPassword
  198.     $xmlString = "<ArrayOfAlertInfo xmlns='http://schemas.solarwinds.com/2008/Orion'>  
  199. <AlertInfo>  
  200.    <DefinitionId>$($alertDefId)</DefinitionId>  
  201.        <ObjectType>$($objectType)</ObjectType>  
  202.        <ObjectId>$($objectId)</ObjectId>  
  203.    </AlertInfo>  
  204. </ArrayOfAlertInfo>"  
  205.     $xmlElement = ([xml]$xmlString).DocumentElement  
  206.  
  207.     # Acknowledge the alert
  208.     Invoke-SwisVerb $swis Orion.AlertStatus Acknowledge @( $xmlElement )
  209.  
  210.     # If there is a nonempty comment, add it to the alert
  211.     if ($comment -notmatch "^([\s]*)$" ) {
  212.         try {
  213.             Comment-Alert $alertDefID $objectID $objectType $comment
  214.         } catch {
  215.             Write-Host $_.Exception.Message
  216.             throw $_.Exception
  217.         }
  218.     }
  219.  
  220.     return $true
  221. }
  222.  
  223. # Comment-Alert ($alertDefId, $objectId, $objectType)
  224. # alertDefId: GUID, The ID of the alert definition that was fulfilled to produce this alert
  225. #             Corresponds to Orion.AlertStatus.AlertDefID
  226. # objectID:   Integer, The ID of the object that triggered the alert
  227. #             Corresponds to Orion.AlertStatus.ActiveObject
  228. # objectType: String, The name of the type of object that triggered the alert
  229. #             Corresponds to Orion.AlertStatus.ObjectType
  230. # comment:    String, A comment to append to the alert
  231. #             Corresponds to Orion.AlertStatus.Notes
  232. #
  233. function Comment-Alert () {
  234.     Param(
  235.     [String] $alertDefId,
  236.     [String] $objectId,
  237.     [String] $objectType,
  238.     [String] $comment = ""
  239.     )
  240.     # Exit if the comment string is empty spaces
  241.     if ($comment -notmatch "^([\s]*)$" ) {
  242.         $swis = Connect-Swis $SWServer -UserName $SWUsername -Password $SWPassword
  243.         Invoke-SwisVerb $swis Orion.AlertStatus AddNote @($alertDefId, $objectId, $objectType, $comment)
  244.     } else {
  245.         throw [System.FormatException] "Comment may not contain only spaces"
  246.         exit 1
  247.     }
  248.  
  249.     return $true
  250. }
  251.  
  252.  
  253. # Begin main script body
  254.  
  255. # How many messages to process at once
  256. $batchSize = 5
  257.  
  258. # Email address of the Exchange mailbox to read
  259. $exchangeEmail    = "solarwinds@mydomain.com"
  260.  
  261. # Exchange user credentials, if not using your own
  262. $exchangeUsername = "ORG-MYUNIT-Solarwinds"
  263. $exchangePassword = "ORG-MYUNIT-Solarwinds_password"
  264. $exchangeDomain   = "DOMAINNAME"
  265.  
  266. # Solarwinds credentials
  267. $SWUsername = "Solarwinds_user"
  268. $SWPassword = "Solarwinds_users_password"
  269. $SWServer = "solarwinds.mydomain.com"
  270.  
  271. # load the Exchange Web Services assembly
  272. [void] [Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll")
  273.  
  274. # set ref to exchange, first references 2007, 2nd is 2010 (default)
  275. $s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
  276. #$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
  277.  
  278. # use first option if you want to impersonate, otherwise, grab your own credentials
  279. $s.Credentials = New-Object Net.NetworkCredential($exchangeUsername, $exchangePassword, $exchangeDomain)
  280. #$s.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
  281. #$s.UseDefaultCredentials = $true
  282.  
  283. # Discover the URL from the Exchange email address
  284. $s.AutodiscoverUrl($exchangeEmail)
  285.  
  286. # Get a handle to the Inbox
  287. $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
  288.  
  289. # Get a handle to the Deleted Items folder
  290. $trash = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::DeletedItems)
  291.  
  292. # Create a property set (to let us access the body & other details not available from the FindItems call)
  293. $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
  294. $psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
  295.  
  296. $items = $inbox.FindItems($batchSize)
  297.  
  298. # output unread count
  299. Write-Host "Number of unread messages in",$inbox.DisplayName,":",$inbox.UnreadCount
  300.  
  301. foreach ($item in $items.Items)
  302. {
  303.     # load the property set to allow us to get to the body
  304.     $item.load($psPropertySet)
  305.  
  306.     # Process the message
  307.     try {
  308.         Process-Message $item
  309.         $status_message="Your request was handled successfully."
  310.         Write-Host "Processed message with subject [ "$item.Subject" ]"
  311.     } catch {
  312.         $status_message="Your request failed. Please contact the monitoring team for support. Error details: " + $_.Exception.Message
  313.         Write-Host "Unable to process message with subject [ "$item.Subject" ]. Error: "$_.Exception.Message
  314.     } finally {
  315.         $item.Reply($status_message, $false)
  316.         $item.Move($trash.Id)
  317.         $item.IsRead = $true
  318.     }
  319.  
  320. }
  321.  
  322. # End main script body
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement