I want to add a counter, so the number of tickets send will increase by 1 every time an email is sent. I had it working on another powershell script but on this one, seems that something is wrong. Maybe someone can give me a hand with this:
Edit: The counter displays always #1, after every email sent.
if ($Counter -eq $null){
$Counter = 1
}
$Email = "test"
$Internal = ""
$Subject = "Error #$Counter - Test - $(Get-Date -format dd/MM/yy)"
[array]$attachments = Get-ChildItem "path"
if ([array]$attachments -eq $null) {
}
else {
$Msg = #{
to = $Email
cc = $Internal
from = "someone"
Body = 'body'
subject = "$Subject"
smtpserver = "server"
BodyAsHtml = $True
Attachments = $attachments.fullname
}
Send-MailMessage #Msg
$Counter++
}
If you want the counter to always increase, you can store it in the registry or store it in a text file like so:
if(-not(Test-Path C:\PathTo\Counter.txt)){
1 > C:\PathTo\Counter.txt #create the file with a default counter
}
$TicketCounter = [int](Get-Content C:\PathTo\Counter.txt)
#restOfYourScriptHere
$TicketCounter++ #as needed to increment
#end of your Script
$TicketCounter > C:\PathTo\Counter.txt #saves the new counter value
Related
I am trying to write a script that will monitor a log file for time modified. If the file has been monitored on the last minute send me an email saying it is all good. IF the log file is older then a minute and the time is between 6am and 9pm send me an email. IF between 9pm and 6am reboot the server. except it is rebooting the server no matter what
# Set perameters here
$uncPath = 'Unc path to log file'
$Server = 'ServerName'
$min = Get-Date 06:00
$max = Get-Date 21:00
$now = Get-Date -Format hh:mm:ss
# Look at the Printstream Log Files and check last modified time
$files = (Get-ChildItem -Path $uncPath -Filter '*PrintstreamBroker*' -File |
Where-Object { $_.LastWriteTime -Gt (Get-Date).AddMinutes(-1) }).FullName
#If there file is good do nothing, and send email
if ($files) {
$Subject = 'Printstream Broker Is Running'
$message = 'The Printstream Broker Is Running There Is Nothing To Do'
$emailTo = '1#1.com'
}
Else ($min.TimeOfDay -lt $now -and $max.TimeOfDay -gt $now){
{
$Subject = 'Printstream Broker Is Not Running'
$message = 'Printstream Broker Is Not Running Please Log Into $servername and start the Printstream Monarch Broker'
$emailTo = '1#1.com'
}
}
Else {
Restart-Computer –ComputerName $server -Force
$Subject = 'Monarch Server Rebooted'
$message = 'The Monarch Server Has Been Rebooted'
$emailTo = '1#1.com'
}
}
# create a email
$mailParams = #{
From = 'PrintstreamBrokerDEV#visionps.com'
To = $emailTo
Subject = $Subject
Body = $message
SmtpServer = 'smtpserver'
# any other parameters you might want to use
}
# send the email
Send-MailMessage #mailParams
You have if else else.
It should be if elseif else.
$status = Get-VMReplication | Select-Object Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, ReplicaPort | ConvertTo-Html
$Company = ""
$ReplicationHealth = (Get-VMReplication)
function ReplicationHealthFailedTelegram {
$token = (Get-Content -Path C:\temp\telegrambot\token.txt)
$chatid = (Get-Content -Path C:\temp\telegrambot\chatid.txt)
$Message = "Replication Failed"
$Company = ""
$status = Get-VMReplication | Select-Object Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, ReplicaPort | ConvertTo-Html
& 'C:\Program Files\PowerShell\7\pwsh.exe' -Command { $token = (Get-Content -Path C:\temp\telegrambot\token.txt);$chatid = (Get-Content -Path C:\temp\telegrambot\chatid.txt); $status = Get-VMReplication | Select-Object Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, ReplicaPort | ConvertTo-Html;$Message = "Replication Failed";$Company = "Howard Matthews Partnership - Harrogate";Send-TelegramTextMessage -BotToken $token -ChatID $chatid -Message $Company $Message}
}
function EmailAlert {
$User = "alert#domain.co.uk"
$File = (Get-Content C:\Temp\pw.txt | ConvertTo-SecureString)
$MyCredential = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $User, $File
$To = "domain.co.uk"
$from = "domain.co.uk"
$EmailSubject = "Hyper-V Replication Error $Company"
$smtp = "auth.smtp.1and1.co.uk"
$DefaultMessage="
<p>Dear Help,</p>
<p>Replication has failed for $Company </p>
<p>$status</p>
<p>The Robot Checker .<br><br>
</p>"
$MailMessage = #{
To = $To
From = $from
# BCC = $Bcc
Subject = $EmailSubject
Body = $DefaultMessage
priority = "High"
Smtpserver = $smtp
Credential = $MyCredential
ErrorAction = "SilentlyContinue"
}
Send-MailMessage #MailMessage -bodyashtml
}
if ($ReplicationHealth.health) {
"Critical","Warning"
EmailAlert
ReplicationHealthFailedTelegram
} else {
$null
}
The Email sends but it regardless if the status of the replication is normal, warning or critical. How would I go by adding the logic of getting to send me an email when that health status is Critical or Warning and not send me an email when it's normal.
Many Thanks!
This bit doesn't do what you think it should
if ($ReplicationHealth.health) {
"Critical","Warning"
EmailAlert
ReplicationHealthFailedTelegram
} else {
$null
}
With your if you are basically asking; "is $ReplicationHealth.Health a thing?" rather than checking for the value "of the thing", and the answer will always be yes in this case assuming nothing went wrong running Get-VMReplication.
A different example to demonstrate what I mean could be something like the following
if($(Get-ChildItem -Path "$env:windir\System32\WindowsPowerShell\v1.0\powershell.exe").Extension) { "Yup, .Extension is a thing" } else { "Nah, it's not!" }
if($(Get-ChildItem -Path "$env:windir\System32\WindowsPowerShell\v1.0\powershell.exe").Extension -eq ".exe") { "Yup, .Extension is a thing and its value is `'.exe`'" } else { "Nah, it's not!" }
In order to fix your if, you could try something like
if($ReplicationHealth.Health -eq "Critical" -or $ReplicationHealth.Health -eq "Warning") {
EmailAlert
ReplicationHealthFailedTelegram
}
I really stink at scripting and I need your help. I pieced together this script from several places on the internet and it works, until I enable my IF statement...
I'm just trying to get a count of files of a folder from a UNC path, and if it's over a specified amount, then I want it to send an email letting me know with the current count.
However, if I uncomment the if ($count -gt 50) part, then I won't get an email if the count is over 50.
I don't know how to make the ".Count" a variable for me to use elsewhere in the script. Can someone please help?
Then I'll need to figure out how to run it. Was thinking just a scheduled task in windows and have it run every few minutes or something, but if you have any better ideas, I'd like to hear them!
$FolderList = #(
"\\server\path\test"
)
$Body = ($FolderList | ForEach-Object {
"Check to see if Sweep Service is running, file count for '$($_)': " + (Get-ChildItem -Path $_ -File -ErrorAction SilentlyContinue | Measure-Object).Count
}) -join "`r`n"
#if ($count -gt 50)
#{
$From = "me#you.com"
$To = "me#you.com"
$Subject = "Sweep Checker"
$SmtpServer = "webmail.you.com"
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SmtpServer $SmtpServer
#}
your major problem seems to be NOT saving the file count to any variable. instead, you are saving the value as part of a string - not a number. [grin]
the following code explicitly puts the file count for the current dir into a var, adds that to the total count, and then uses the current count to build your output string for the body of your msg.
$FolderList = #(
$env:TEMP
$env:USERPROFILE
$env:ALLUSERSPROFILE
)
$TriggerFileCount = 20
$TotalFileCount = 0
$Body = foreach ($FL_Item in $FolderList)
{
$CurrentFileCount = #(Get-ChildItem -LiteralPath $FL_Item -File -ErrorAction SilentlyContinue).Count
$TotalFileCount += $CurrentFileCount
# send out to the "$Body" collection
'Check to see if Sweep Service is running, file count for [ {0} ] = {1}' -f $FL_Item, $CurrentFileCount
}
if ($TotalFileCount -gt $TriggerFileCount)
{
$SMM_Params = #{
From = 'NotMe#example.com'
To = 'NotYou#example.com'
Subject = 'Sweep Checker'
Body = $Body -join [System.Environment]::NewLine
SmtpServer = $SmtpServer
}
$SMM_Params
#Send-MailMessage #SMM_Params
}
output ...
Name Value
---- -----
Subject Sweep Checker
From NotMe#example.com
To NotYou#example.com
SmtpServer webmail.you.com
Body Check to see if Sweep Service is running, file count for [ C:\Temp ] = 22...
the full content of the $Body variable ...
Check to see if Sweep Service is running, file count for [ C:\Temp ] = 22
Check to see if Sweep Service is running, file count for [ C:\Users\MyUserName ] = 5
Check to see if Sweep Service is running, file count for [ C:\ProgramData ] = 0
I want to monitor the particular Folder where people are placing the excel sheets for some activities.
I want to make sure that people should take care of the below rules before placing the excel sheets.
The excel sheet should be in xls format (Excel 97-2003 Workboomk Format)
The excel file name should not contain any space
The length of the file name should not exceed 15 characters.
I want to set a email alert to me if the users placed a excel sheet without following the above 3 rules.
I need a VB or Powershell script or batch to monitor the folder. Kindly help me on this.
This sounds like two steps. Step 1, write a section of code that can be run to check files for the correct conditions. Step 2, email users the list of incorrectly named files. Step 1 is fairly simple.
Dim fso, scanFolder, files, n, fileList, fileArray
Set fso = CreateObject("Scripting.FileSystemObject")
Set scanFolder = fso.GetFolder("C:\Your\Folder\Here")
Set files = scanFolder.Files
fileList = ""
for each n in files
if len(n.name) > 15 or right(n.name, 3) <> "xls" or InStr(n.name, " ") > 0 then
fileList = fileList & n.name & "|"
end if
next
fileList = left(fileList, len(fileList) - 1)
fileArray = split(fileList, "|")
This will grab a list of all inappropriately named files.
Step 2. Unfortunately, as far as I know, there is no way for an FSO to get the owner name out of file. Best you can do is email a distribution list with the list of files named in error. I hope this helps.
Edit: this is the email code I use in my scripts.
Dim objEmail, strFileList, x
strFileList = ""
for each x in fileArray
strFileList = strFileList & x & vbNewLine
next
Set objEmail = CreateObject("CDO.Message")
with objEmail
.From = "From#email.com"
.To = ""
.CC = ""
.Subject = "List of wrong files"
.Body = strFileList
.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = 'you will need to get the code for this from IT'
.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
.Configuration.Fields.Update
end with
objEmail.Send
I have wrapped the functionality of FileSystemWatcher into a module and provided a small sample of how that can be used for your requirements.
# Module FileSystemWatcher
<#
.SYNOPSIS
Register to receive filesystemwatcher events for a file or folder.
#>
function Register-FileSystemEvent
{
[CmdLetBinding(DefaultParameterSetName="File")]
param
(
[Parameter(Mandatory=$true,Position=0,ParameterSetName="File")]
[string]$path,
[Parameter(Mandatory=$true,Position=0,ParameterSetName="Folder")]
[string]$folder,
[Parameter(Mandatory=$false,Position=1,ParameterSetName="Folder")]
[string]$filter="*.*",
[Parameter(Mandatory=$true,Position=2)]
[string]$event,
[scriptblock]$action={
# Action code here
$sourceidentifier = $Event.SourceIdentifier
$FileName = $Event.SourceEventArgs.FullPath
$EventType = $Event.SourceEventArgs.ChangeType
$EventTime = $Event.TimeGenerated
$message = ("File {0} {1} at {2:yyyyMMdd HH:mm:ss}" -f $FileName, $EventType, $EventTime)
Msg ([environment]::UserName) $message
},
$MessageData
)
if ($PSCMdLet.ParameterSetName -eq "File")
{
$folder = $path.Replace(([System.IO.Path]::GetFileName($path)), "")
$filter = [System.IO.Path]::GetFileName($path)
}
$watcher = New-Object System.IO.FileSystemWatcher -ArgumentList $folder, $filter
$uniqueId = ("{0:yyyyMMddHHmmss}" -f [DateTime]::Now)
$sourceIdentifier = ("File_{0}_{1}" -f $event, $uniqueId)
$job = Register-ObjectEvent -InputObject $watcher -EventName $event -SourceIdentifier $sourceIdentifier -Action $action -MessageData $MessageData
$Script:ActiveWatchers += #{$sourceIdentifier = $job}
}
<#
.SYNOPSIS
Unregister a FileSystem event or All
.PARAMETER All
Unregisters all events
#>
function Unregister-FileSystemEvent
{
param
(
$id,
[switch]$All
)
if ($All.IsPresent)
{
foreach ($item in $Script:ActiveWatchers.Keys)
{
Unregister-Event $item
Remove-Job $item
}
$Script:ActiveWatchers = #{}
}
else
{
Unregister-Event $id
Remove-Job $id
$Script:ActiveWatchers.Remove($id)
}
}
function Init
{
if ($Script:ActiveWatchers.Count -gt 0){Unregister-FileSystemEvent -All}
$Script:ActiveWatchers = #{}
}
Init
Export-ModuleMember -Function Register-FileSystemEvent, Unregister-FileSystemEvent `
-Variable ActiveWatchers
The basic idea with this module is the ability to specify a scriptblock to be executed once the file event is fired. The -MessageData is used to attach more data to the event once it is fired. In below sample it is used to send the smtpserver and the credentials.
Below the sample code to make use of the fileSystemWatcher module and send an email with the results every time a file is created.
Please note that the arguments to Send-MailMessage might not be exactly what is necessary for your mail server, but is what i used to send the email using office365 server.
# Demo using FileSystemWatcher to validate created files
Import-Module .\FileSystemWatcher
$smtpserver = Read-Host -Prompt "Specify your smtp server"
$mailcred = Get-Credential -Message "Specify credentials for your smtp server"
$eventid = Register-FileSystemEvent -folder C:\users\Jower\OneDrive\Documents -event Created -MessageData #{SmtpServer = $smtpserver;Credentials = $mailcred} -action {
function ValidateFile($filename)
{
$messages = #()
if ([System.IO.Path]::GetExtension($filename) -ne ".xls")
{
$messages += ("{0}: Only excel version 97 files allowed here" -f $filename)
}
if ([System.IO.Path]::GetFileName($filename).Contains(" "))
{
$messages += ("{0}: Spaces are not allowed in filename" -f $filename)
}
if ($filename.Length -gt 15)
{
$messages += ("{0}: Filenames of more than 15 characters is not allowed" -f $filename)
}
return $messages
}
$smtpserver = $Event.MessageData.SmtpServer
$credentials = $Event.MessageData.Credentials
$messages = ValidateFile $Event.SourceEventArgs.Name
if ($messages.Count -gt 0)
{
Send-MailMessage -From "filealerts#domain.com" -To "recipient#domain.com" -Subject "File validation" -SmtpServer $smtpserver -Body ([string]::Join("`n", $messages)) -port 587 -UseSsl -Credential $credentials
}
}
# To disable events again.
# Unregister-FileSystemEvent -id $eventid
# Can also use
# Unregister-FileSystemEvent -All
So basically, what I have here is a script that will scan a CSV that it imports, and for every entry in the spreadsheet, except for people in the RANDOM.DOMAIN, it will find the managers email address and send an automated email to the manager telling them user XYZ is about to expire soon, and they need to do something about it.
If the managers email is unavailable for some reason, then it defaults to sending the email to me.
This script works well.
The problem I am running into is, I want to make it so only one email is sent to each manager, despite multiple users (or entries) from the spreadsheet, list them as the manager.
I.e. if Joe Bloggs has a manager Aaron T and Jane Doe has the manager Aaron T, then Aaron T will get two emails, one email for each user.
MY QUESTION:
Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?
$datai = Import-Csv "Soon-to-expire User Accounts22.csv" | select 'Display Name',Manager,'Domain Name','Account Expiry Time'
Connect-QADService -Service another.DC | Out-Null
$expiringUsers = #{}
foreach ($i in $datai) {
$dn = $i.'Display Name'
$dn1 = $i.'Domain Name'
$man = $i.'Manager'
$aet = $i.'Account Expiry Time'
$subject = "Account about to expire: $dn"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
if ($man -eq "-" -or $man -like 'CN=*' -or $getmail -eq $null -or $man -eq "") {
$man = "Aaron T"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
}
if ($expiringUsers.Contains($emailAD)) {
$expiringUsers[$emailAD]["dn"] += $dn += "`n"
$expiringUsers[$emailAD]["aet"] += $aet += "`n"
$expiringUsers[$emailAD]["man"] += $man += "`n"
} else {
$expiringUsers[$emailAD] = #{
#"dn1" = $dn1
#"aet" = $aet
#"man" = $man
# "dn" = #( $dn )
}
}
}
$expiringUsers | fc #as suggested
foreach ($emailAD in $expiringUsers.Keys) {
$dn = $expiringUsers[$emailAD]["dn"]
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account/s About to Expire!"
$content = #"
Hi,
$dn `n
$dn1 `n
$man `n
$aet `n
$emailAD `n
Technology Services
"#
Send-MailMessage -from "aaron#website.com" `
-To $emailAD `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer "relay.server"
#using this as a test instead of sending mass emais all the time
Write-Host $content
}
UPDATED with the new script as requested.... still having issues.
Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?
For this you need to defer e-mail processing. Collect the users in a hashtable, e.g. by manager e-mail address:
...
$expiringUsers = #{}
foreach ($i in $datai) {
If ($i.'Domain Name' -notmatch "RANDOM.DOMAIN") {
...
if ($expiringUsers.Contains($emailAD)) {
$expiringUsers[$emailAD]["dn"] += $dn
} else {
$expiringUsers[$emailAD] = #{
"dn1" = $dn1
"aet" = $aet
"man" = $man
"dn" = #( $dn )
}
}
}
}
and move the actual e-mail processing outside the loop:
foreach ($emailAD in $expiringUsers.Keys) {
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account about to expire: $($expiringUsers[$emailAD]["dn"])"
$content = #"
Hi,
...
Technology Services
"#
Send-MailMessage -from "Test Script - Powershell <email#test.com>" `
-To "$emailAD" `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer servername
Write-Host "Mail Sent to $man"
}
Note that for simplicity reasons the above code only records the expiry date of the first user. If you want the expiry date of each user recorded separately, you'll have to take additonal steps, e.g.
$expiringUsers[$emailAD]["expiry"] += #{
"name" = $dn;
"date" = $aet;
}
instead of
$expiringUsers[$emailAD]["dn"] += $dn
So I finally decided to revisit this script, after many, many months.
I'm get a little better at PowerShell and while I'm sure this isn't the most effective way to do it, this is something that works for me.
I've also changed the input method; it pulls the information directly from AD, instead of using a CSV file that used to be generated from an application called 'AD Manager Plus' (Hate it).
Remember, using Quest CMDlets here because we don't have a 2008 environment. (so using Get-QADUser instead of Get-ADuser)
FYI, I have only posted the code here which sorts out the data into separate tables - you can decide how you want to utilize those results. For our environment, I have it build an nice HTML table and body, then send it to the appropriate manager to deal with.
#user data input
$data = get-qaduser -SizeLimit 0 -includedproperties accountexpires | where {$_.AccountExpires -ne $null -and $_.AccountExpires -le ((Get-Date).AddDays(45)) }
#get a list of managers, unique.
$uniqueMan = $data | select Manager -Unique
#foreach manager from $uniqueman
Foreach ($manager in $uniqueman) {
#create the array variable / clear it out for the next manager.
$myarray = #()
#foreach User found in in $data query
Foreach ($user in $data) {
#Search the $user's query for people with the same manager as that of the $uniqueman list.
If ($user.Manager -eq $manager.Manager) {
#do what with the result.
#add the person to an array
$myarray += New-Object psobject -Property #{
Name = $user.'Name'
UserName = $user.'SAMAccountName'
AccountExpires = $user.'AccountExpires'
Manager = $user.Manager
}
}
#for testing, to output the results to an HTML file.
#$myarray | ConvertTo-Html | Out-File ("C:\test\" + $manager.Manager + ".html")
}
}