powershell [发送自定义HTML通知]最近,我们更改了PRTG处理通知电子邮件的方式并简化了方法,因此只有
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了powershell [发送自定义HTML通知]最近,我们更改了PRTG处理通知电子邮件的方式并简化了方法,因此只有相关的知识,希望对你有一定的参考价值。
#Requires -Version 4
<#
___ ___ _____ ___
| _ \ _ \_ _/ __|
| _/ / | || (_ |
|_| |_|_\ |_| \___|
HTMLMailNotifier
With this, you can send personalized HTML mails using templates and PRTGs EXE notification
#>
param(
## From
[string] $From = "",
## Sensor ID
[int] $SensorID = 0,
## The recipient of the mail message
[string] $Recipients = "",
## Set this if you want to use a PRTG group as recipient
[string] $PrtgGroup = "",
## The subjecty of the message
[string] $Subject = "",
## The template folder
[string] $TemplateFolder = "",
## The template we'll use
[string] $Template = "",
## Placeholder set
$Placeholders = @(),
## Use HTML or text based template (this will use the .htm instead of the .txt file for the template)
$HTML = $true,
## The priority of the mail
[ValidateSet("Low","Normal","High")][string]$priority = "High",
## Only use primary contact - if false, all mail contacts will receive the notification
[switch] $primaryOnly = $true,
## For the initial password setup, call it with -SetupPasswords
[switch] $SetupPasswords = $false
)
#region configuration
[string] $ConfigurationFilePath = ((Get-ItemProperty -Path "hklm:SOFTWARE\Wow6432Node\Paessler\PRTG Network Monitor\Server\Core" -Name "Datapath").DataPath) + "PRTG Configuration.dat"
[xml] $configuration = New-Object -TypeName XML;
$configuration.Load($ConfigurationFilePath)
## server configuration
[hashtable]$servers = @{
smtpFrom = $From
smtpHost = ""
smtpPort = 0
smtpUser = ""
smtpSsl = $false
smtpBackupFrom = $From
smtpBackupHost = ""
smtpBackupPort = 0
smtpBackupUser = ""
smtpBackupSsl = ""
prtgHost = ""
prtgPort = 80
prtgProtocol = "http"
prtgUsername = ""
prtgPasshash = ""
}
## mail configuration
[System.Collections.ArrayList]$global:recipientList = @();
[string] $priority = "high"
## template configuration
[string] $templateBaseDir = "C:\Program Files (x86)\PRTG Network Monitor\webroot\mailtemplates\custom"
[string] $templateDefaultLogo = "C:\Program Files (x86)\PRTG Network Monitor\webroot\images\prtglogo.png"
[string] $Global:graphGUID = [guid]::NewGuid()
[string] $iconFolder = "C:\Program Files (x86)\PRTG Network Monitor\webroot\icons"
[string] $tempFolder = "C:\temp";
[string] $global:stateIcon = "";
## miscallenious
[hashtable]$directories = @{
"templateBaseDir" = "C:\Program Files (x86)\PRTG Network Monitor\webroot\mailtemplates\custom";
"tempFolder" = "C:\temp";
"iconFolder" = "C:\Program Files (x86)\PRTG Network Monitor\webroot\icons";
"templatePath" = ""; }
###########################################################################
# /!\ DON'T CHANGE ANYTHING BELOW - Except you know what you're doing /!\ #
###########################################################################
[hashtable] $stateColors = @{
"1" = "#808282"; #unknown
"3" = "#b4cc38"; #up
"4" = "#ffcb05"; #warning
"5" = "#d71920"; #down
"8" = "#447fc1"; #paused-dependency
"9" = "#447fc1"; #paused-schedule
"10" = "#f99d1c"; #unusual
"11" = "#447fc1"; #paused-license
"12" = "#447fc1"; #paused-until
"13" = "#e77579"; #acknowledged
"14" = "#d71920"; #down-partial
}
[hashtable]$stateIcons = @{
"1" = "led_grey.png"; #unknown
"3" = "led_green.png"; #up
"4" = "led_yellow.png"; #warning
"5" = "led_red.png"; #down
"8" = "led_blue.png"; #paused-dependency
"9" = "led_blue.png"; #paused-schedule
"10" = "led_orange.png"; #unusual
"11" = "led_blue.png"; #paused-license
"12" = "led_blue.png"; #paused-until
"13" = "led_redok.png"; #acknowledged
"14" = "led_redgreen.png";#down-partial
}
## debugging
[switch] $verbose = $true;
#endregion
#region function library
## show messages, nicely formatted.
function Console-ShowMessage([string]$type,$message){
if($verbose){
Write-Host ("[{0}] [" -f (Get-Date)) -NoNewline;
switch ($type){
"done" { Write-Host "done" -ForegroundColor Green -NoNewline;}
"info" { Write-Host "info" -ForegroundColor DarkCyan -NoNewline; }
"warn" { Write-Host "warn" -ForegroundColor DarkYellow -NoNewline; }
"fail" { Write-Host "fail" -ForegroundColor Red -NoNewline; }
default{ Write-Host $type -NoNewline; }
}
Write-Host ("]`t{0}{1}" -f $message,$Global:blank)
}
}
## check the password files for completeness
function Check-PasswordFiles(){
$checklist = @("Primary","Secondary")
foreach($server in $checklist){
$fileCount = (Get-ChildItem "C:\Program Files (x86)\PRTG Network Monitor\Notifications\EXE\*" -Include "*$($server).key","*$($server).pass").Count
if(!($fileCount -eq 2)){
Console-ShowMessage "fail" "The credential set for the $($server) server is missing or incomplete."
Passwords Set $server
}
}
if($SetupPasswords){ PRTG-ShowMessage "info" "Credentials created successfully."; exit 0; }
if((Get-ChildItem "C:\Program Files (x86)\PRTG Network Monitor\Notifications\EXE\*" -Include "*.key","*.pass").Count -eq 4){
Console-ShowMessage "done" "All credentials found."
}
}
## check the mail server availability
function Check-MailServers([hashtable]$global:servers){
begin { Console-ShowMessage "info" "Checking mail server availability..." }
process {
## lets create a new TCP client first
$tcpClient = New-Object System.Net.Sockets.TCPClient
try{
$tcpClient.Connect($global:servers.smtpHost,$global:servers.smtpPort)
Console-ShowMessage "info" "Using primary mail server"
}
catch{
try {
$tcpClient.Connect($global:servers.smtpBackupHost,$global:servers.smtpBackupPort)
Console-ShowMessage "warn" "Primary mail server not responding, using fallback server"
$global:servers.smtpHost = $global:servers.smtpBackupHost
$global:servers.smtpPort = $global:servers.smtpBackupPort
$global:servers.smtpSsl = $global:servers.smtpBackupSsl
$global:servers.smtpUser = $global:servers.smtpBackupUser
}
catch {
Console-ShowMessage "fail" "None of the configured mailservers is responding, please check them for availability."
#exit 1;
}
}
finally { $tcpClient.Close(); }
}
}
function ValidateEmail{
param([string]$address)
($address -as [System.Net.Mail.MailAddress]).Address -eq $address -and $address -ne $null
}
## store the passwords
function Passwords([ValidateSet("Get","Set")][string]$action, [ValidateSet("Primary","Secondary")][string]$Server = ""){
switch($Server)
{
"primary" {
$passFile = "C:\Program Files (x86)\PRTG Network Monitor\Notifications\EXE\HTMLNotifyPrimary.pass";
$keyFile = "C:\Program Files (x86)\PRTG Network Monitor\Notifications\EXE\HTMLNotifyPrimary.key";
}
"secondary" {
$passFile = "C:\Program Files (x86)\PRTG Network Monitor\Notifications\EXE\HTMLNotifySecondary.pass"
$keyFile = "C:\Program Files (x86)\PRTG Network Monitor\Notifications\EXE\HTMLNotifySecondary.key";
}
}
if($action -eq "set"){
$Key = New-Object Byte[] 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$Key | out-file $keyFile
Read-Host "Enter Password for the $($Server) server" -AsSecureString | ConvertFrom-SecureString -key $Key | Out-File $passFile
}
if($action -eq "get"){
$Key = Get-Content $KeyFile
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $global:servers.smtpUser, (Get-Content $passFile | ConvertTo-SecureString -Key $key)
return $Credentials;
}
}
## set up the template paths
function Set-TemplatePaths(){
begin { Console-ShowMessage "info" "Setting up template paths..." }
process {
## set up the paths...
if($templateFolder.Length -ne 0)
{ $directories.templatePath = [string]::Format("{0}\{1}\{2}.htm",$templateBaseDir,$templateFolder,$Template) }
else
{ $directories.templatePath = [string]::Format("{0}\{1}.htm",$templateBaseDir,$Template) }
## Check the paths for existance
$directories.Keys | % {
if(!(Test-Path $directories.Item($_)))
{ Write-Host "Template or directory not found. Please make sure all folders and templates exist!" -ForegroundColor Red; exit 2; }
}
## if there's no logo, use the default
if(!(Test-Path -Path ([string]::Format("{0}\{1}\logo.png",$templateBaseDir,$templateFolder))))
{
$global:templateLogo = $templateDefaultLogo
Console-ShowMessage "info" "No customized logo found, using the specified default logo..."
}
else
{
Console-ShowMessage "info" "Customized logo found."
$global:templateLogo = [string]::Format("{0}\{1}\logo.png",$templateBaseDir,$templateFolder)
}
}
}
## this function will return the group ID of the given group
function Get-PrtgGroup( [string]$prtgGroup ){
if($prtgGroup.Length -ne 0){
## retrieve the group id of the corresponding PRTG user group
$group = $configuration.SelectSingleNode([string]::Format('//usergroup[@id][data/name[normalize-space(text())="{0}"]]',$prtgGroup))
## return the id, otherwise error if you found nothing
if($group -ne $null)
{ return $group.id.Trim(); }
else
{ Console-ShowMessage -type "fail" "The specified user group was not found. Please make sure that the name is correct." }
}
}
## this will retrieve the single users from PRTG and create the recipientList
function Get-PrtgUsers([string]$prtgGroup){
begin { Console-ShowMessage -type "info" "Retrieving recipients..." }
process {
if($prtgGroup.Length -ne 0){
Console-ShowMessage -type "info" "Retrieving users of PRTG group $($prtgGroup)"
## lets retrieve the ID of the corresponding group first.
$groupId = (Get-PrtgGroup -prtgGroup $prtgGroup)
## now lets get all active users within that group
$userList = $configuration.SelectNodes([string]::Format('//user[@id][data/primarygroup = {0}][data/active = 1]',$groupId))
$availableUsers = Foreach($user in $userList){
## we only want the primary contacts if PrimaryOnly is true.
if($PrimaryOnly)
{ $contacts = $user.SelectNodes('//user[@id='+$user.id+']/contacts/contact[data/status = 1][data/contacttype = 0][@id = -100]') }
else
{ $contacts = $user.SelectNodes('//user[@id='+$user.id+']/contacts/contact[data/status = 1][data/contacttype = 0]') }
$availableContacts = foreach($contact in $contacts)
{ $recipientList.Add($contact.data.recipient.Trim()) }
}
## create the final recipient list and remove duplicates
$recipients = $recipientList + $recipients.Trim().Split(",") | Select -Unique
}
else
{
$recipients = $recipients.Trim().Split(",") | Select -Unique
}
$correctedRecipients = @();
# remove all recipients that are not valid
foreach($recipient in $recipients){
if(ValidateEmail($recipient))
{ $correctedRecipients += $recipient }
}
}
end {
# stop it if we don't have any recipients
if($correctedRecipients.Length -eq 0) { Console-ShowMessage -type "fail" "No recipients found. Please check the group name and the recipient list for errors. Exiting."; exit 0; }
Console-ShowMessage -type "done" "Found $($userList.count) users in group $($prtgGroup), sending to $($correctedRecipients.count) contacts in total."
return $correctedRecipients;
}
}
## this function will retrieve the latest sensor informations
function Get-SensorLiveInfo([int]$SensorId){
begin { Console-ShowMessage -type "info" "Retrieving information for sensor #$($SensorID)" }
process {
## build the graph URL
$params = @($global:servers.prtgProtocol,$global:servers.prtgHost,$global:servers.prtgPort,$SensorId,$global:servers.prtgUsername,$global:servers.prtgPasshash)
$url = [string]::Format("{0}://{1}:{2}/api/getsensordetails.json?id={3}&username={4}&passhash={5}",$params);
## download the graph and store it with the current guid
$wc = New-Object System.Net.WebClient
$sensorInfo = ($wc.DownloadString($url)) | ConvertFrom-Json;
}
end { return $SensorInfo }
}
## retrieves the live graph from the given sensor id
function Get-SensorLiveGraph([int]$id){
begin { Console-ShowMessage -type "info" "Retrieving current live graph for sensor #$($SensorID)" }
process {
## build the graph URL
$params = @($global:servers.prtgProtocol,$global:servers.prtgHost,$global:servers.prtgPort,600,280,$SensorId,$global:servers.prtgUsername,$global:servers.prtgPasshash)
$url = [string]::Format("{0}://{1}:{2}/chart.png?type=graph&width={3}&height={4}&graphid=0&id={5}&username={6}&passhash={7}",$params);
## download the graph and store it with the current guid
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($url, [string]::Format("{0}\{1}.png",$directories.tempFolder,$Global:GraphGUID))
}
end { Console-ShowMessage -type "done" "Graph downloaded and stored as $($tempFolder)\$($Global:GraphGUID).png" }
}
## sets up the template and replaces the placeholders accordingly.
function Get-Template(){
begin { Console-ShowMessage "info" "Preparing notification mail" }
process {
## retrieve current sensor information
$SensorInfo = (Get-SensorLiveInfo($SensorID))
## set the status icon
$global:stateIcon = $stateIcons[$SensorInfo.sensordata.statusid]
## retrieve the template of the specified content
[string]$body = (Get-Content $directories.templatePath) -join "`n"
## check if the amount of placeholders does match
try
{$body = [string]::Format($body,$placeholders) }
catch
{ Console-ShowMessage "warn" "The amount of placeholders doesn't match with the template. Please make sure that they're equal." }
[hashtable]$placeholderTable = @{
"miscLOGO" = [string]::Format("<img src='{0}' />",(Split-Path -Path $global:templateLogo -Leaf))
"sensorNAME" = $SensorInfo.sensordata.name;
"sensorTYPE" = $SensorInfo.sensordata.sensortype;
"sensorLIVEGRAPH" = [string]::Format("<img src='{0}.png' />",$Global:GraphGUID);
"sensorSTATECOLOR" = $stateColors[$SensorInfo.sensordata.statusid];
"sensorSTATEICON" = [string]::Format("<img src='{0}' />",$global:stateIcon)
"sensorINTERVAL" = $SensorInfo.sensordata.interval;
"sensorPARENTGROUP" = $SensorInfo.sensordata.parentgroupname;
"sensorPARENTDEVICE" = $SensorInfo.sensordata.parentdevicename;
"sensorPARENTDEVICEID" = $SensorInfo.sensordata.parentdeviceid;
"sensorLASTVALUE" = $SensorInfo.sensordata.lastvalue;
"sensorLASTMESSAGE" = $SensorInfo.sensordata.lastmessage;
"sensorSTATUSTEXT" = $SensorInfo.sensordata.statustext;
"sensorSTATUSID" = $SensorInfo.sensordata.statusid;
"sensorLASTUP" = $SensorInfo.sensordata.lastup;
"sensorLASTDOWN" = $SensorInfo.sensordata.lastdown;
"sensorLASTCHECK" = $SensorInfo.sensordata.lastcheck;
"sensorUPTIME" = $SensorInfo.sensordata.uptime;
"sensorUPTIMETIME" = $SensorInfo.sensordata.uptimetime;
"sensorDOWNTIME" = $SensorInfo.sensordata.downtime;
"sensorDOWNTIMETIME" = $SensorInfo.sensordata.downtimetime;
"sensorUPDOWNTOTAL" = $SensorInfo.sensordata.uptimetotal;
"sensorUPDOWNSINCE" = $SensorInfo.sensordata.updownsince;
"sensorURL" = [string]::Format("{0}://{1}:{2}/sensor.htm?id={3}",$global:servers.prtgProtocol,$global:servers.prtgHost,$global:servers.prtgPort,$SensorID);
"deviceURL" = [string]::Format("{0}://{1}:{2}/device.htm?id={3}",$global:servers.prtgProtocol,$global:servers.prtgHost,$global:servers.prtgPort,$SensorInfo.sensordata.parentdeviceid);
}
## replace all existing placeholders within the template
foreach ($placeholder in $placeholderTable.Keys)
{
$body = ($body -replace $placeholder, $placeholderTable.$placeholder)
$subject = ($subject -replace $placeholder, $placeholderTable.$placeholder)
}
[hashtable]$mail = @{
Body = $body;
Subject = $subject;
};
}
end { return $mail }
}
## this function will format the mail and send it to the given recipient(s)
function Send-NotificationMail([hashtable]$mail){
## There will always be a logo and a livegraph available for every template.
## Use logo,livegraph,probeicon,breadcrumb as img src to embed them, like this:
## See the following placeholders to insert them in your mail
[string[]]$images = @(
$global:templateLogo,
[string]::Format("{0}\{1}.png",$directories.tempFolder,$Global:GraphGUID),
[string]::Format("{0}\{1}",$directories.iconFolder,$global:stateIcon)
)
$mailparameters = @{
SmtpServer = $global:servers.smtpHost;
Port = $global:servers.smtpPort;
Credential = (Passwords -Action Get -Server Primary);
From = $global:servers.smtpFrom;
To = Get-PrtgUsers($prtgGroup);
Body = $mail.Body;
Subject = $mail.Subject;
Attachments = $images;
BodyAsHtml = $HTML;
UseSsl = $global:servers.smtpSsl;
Priority = $priority;
}
try{
Send-MailMessage @mailparameters
Console-ShowMessage "info" "Recipient(s) should be notified now."
}
catch { PRTG-ShowMessage "fail" "The notification could not be sent." }
}
#endregion
function Main(){
begin{
Check-PasswordFiles;
Check-MailServers;
Set-TemplatePaths;
}
process{
Get-SensorLiveGraph;
Send-NotificationMail -mail (Get-Template)
}
end{
Console-ShowMessage "info" "Removing live graph image. Exiting."
Remove-Item ([string]::Format("{0}\{1}.png",$tempFolder,$Global:graphGUID))
}
}
Main;
以上是关于powershell [发送自定义HTML通知]最近,我们更改了PRTG处理通知电子邮件的方式并简化了方法,因此只有的主要内容,如果未能解决你的问题,请参考以下文章
OneSignal - 使用来自 url 的自定义图像从 android 应用发送通知