Getting email Notification Folder count - powershell

With this powershell script i'm able get file count on inside a folder
Get-ChildItem D:\ -Recurse -File | Measure-Object | %{$_.Count}
here is the script sending email.
$Count = Get-ChildItem D:\ -Recurse -File | Measure-Object | %{$_.Count}
$Status= $Event.Message
$From = "sender#sender.com"
$To = "receiver"
$SMTPServer = "smtp"
$SMTPPort = "587"
$Username = "email#email.us"
$Password = "password"
$Subject = "$computer,Files count"
$Body = "Number of Files is $Count |D drive test "
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $false
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($From, $To, $subject, $body);
$computer = "$env:computername
But the output is simply plain text Number of Files is 58 |D drive test
can we have it to alert us with some more text like If file count is mismatch it should consider a warning like "number of files is 60 which is large" or if it gets less it should be critical and error.

you have comparison operators:
-lt = lower than
-gt = greater than
-ge = greater or equal
-le = less or equal
-eq = equal
And you have if, elseif and else
with that you can change your body message (as suggested in the answer of DarkMoon)
if ($count -le '50') {
$Body = 'your text'
}
elseif (($count -gt '50') -and ($count -le '100')) {
$Body = 'your text'
}
elseif (($count -gt '100') -and ($count -le '500')) {
$Body = 'your text'
}
else {
$Body = 'your text'
}

For the warning, it'd be simply something along the lines of:
if ($Count -lt 60) {
$Body = "Number of Files is low at $Count |D drive test "
} else {
$Body = "Number of Files is $Count which is large |D drive test "
}

Related

Powershell to monitor a folder and send email when there are new files

I need some assistance on how to create a powershell to monitor a folder and subfolders and send an email every 15 minutes for example, with a list of files that added to this folder
I will set up a schedule task to run every 15 minutes
Email output will be something like:
File Name, Path
TEST.TXT uploaded to C:\ROOT\BUSINESS
test2.txt uploaded to C:\ROOT\BUSINESS\May2021
Here is what I have so far. Any help is appreciated.
SMTPServer = "EMAIL SERVER (ip)"
$SMTPPort = "111"
$Username = "SENDER#EMAIL.COM"
$path="C:\ROOT\BUSINESS\"
$to = "test1#gmail.com"
$cc = "test2#gmail.com"
$subject = " New File available "
$message = New-Object System.Net.Mail.MailMessage
$message.subject = $subject
$message.to.add($to)
$message.cc.add($cc)
$message.from = $username
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
#$smtp.Credentials = New-Object System.Net.NetworkCredential $Username;
If ($File = Get-ChildItem $Path | Where { $_.LastWriteTime -ge [datetime]::Now.AddMinutes(-15) }){
$smtp.send($message)}
write-host "Mail Sent"
Thanks
Try this condition:
if ((Get-ChildItem $Path | Where { $_.LastWriteTime -ge [datetime]::Now.AddMinutes(-15) }).Count -ge 1){ <# do something #> }

Single line break in body of powershell MailMessage not working

For some reason when attempting to populate the body of an email in powershell, a single line break using the `n escape sequence is not working, however a double is.
This is my code...
param([string]$BuildId, [string]$BuildName)
$EmailTo = "[email]"
$EmailFrom = "sepaautomation#gmail.com"
$Subject = "$BuildName $BuildId SpecFlow Reports"
$Body = "The following SpecFlow reports are attached: `n`n"
$SMTPServer = "smtp.sendgrid.net"
$date = Get-Date -Format yyyy-MM-dd
$files = Get-ChildItem "C:\Build\SA.SEPA.Web.UI.Selenium" -Recurse | Where-Object { $_.Name -match "^.*$date.*\.html$" } | % { $_.FullName }
foreach($item in $files)
{
$Body += "$item `n"
}
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
foreach($item in $files)
{
$attachment = New-Object System.Net.Mail.Attachment($item)
$SMTPMessage.Attachments.Add($attachment)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("apikey", "[apiKey]");
$SMTPClient.Send($SMTPMessage)
This is the section that is failing to add a line break
foreach($item in $files)
{
$Body += "$item `n"
}
My email in outlook looks like the following....
You can see that the `n `n double line break has been applied but not the `n. Incidentally if I change to...
foreach($item in $files)
{
$Body += "$item `n`n"
}
I do see a double line break.
How do I get just a single line break?
Just go with [Environment]::NewLine to resolve this one. It will take away most headaches relating to this issue.
Usage:
foreach($item in $files)
{
$Body += "$item " + [Environment]::NewLine
}
If you OK to use HTML body you can use <br> for line breaks.
You will need to set following property on your message variable:
$SMTPMessage.IsBodyHTML = $true
$Body += "$item <br>"

PowerShell multiple email recipients (attachment) from csv / empty cell issue

I recently started to work on PS script for email automation.
Manage to put something together where I have CSV file from where PowerShell is extracting data (multiple recipients, attachment, etc).
The problem is, when some of the cells are empty, script won`t work.
There is one similar question, but I am just not sure how to implement solution on my case:
$importFile = "Users.csv"
$users = import-csv $importFile | select *
foreach($user in $users)
{
$Name = $user.'Name'
$to = $user.'To'
$to2 = $user.'To2'
$Attachment = $user.'Attachment'
$Attachment2 = $user.'Attachment2'
$write = "Emailing account " + $to + " ..."
Write-Host $write
$body = [string]::join([environment]::newline, (Get-Content -path $emailFile))
$body = $body.Replace('[Name]', $Name)
$mail = New-Object System.Net.Mail.MailMessage
$mail.From = $emailFrom
$mail.To.Add($to)
$mail.To.Add($to2)
$mail.Subject = $emailSubject
$mail.IsBodyHtml = $true
$mail.Body = $body
$mail.Attachments.Add($Attachment)
$mail.Attachments.Add($Attachment2)
$smtp = New-Object System.Net.Mail.SmtpClient
$smtp.Host = $smtpServerHost
$smtp.Port = $smtpServerPort
$smtp.EnableSsl = $smtpServerSsl
$smtp.UseDefaultCredentials = $false
$smtp.Credentials = $credentials
$smtp.Send($mail)
This is how looks CSV file
Any suggestion is more than welcome :)
Try Where-Object to filter out rows.
$users = Import-Csv $importFile |
Where-Object {$_.Name -ne ""} |
Select-Object *
For what it is worth: if the whole "row" is blank you can shortcut this to simply be
...
Where-Object {$_} |
...
Implementing IF function resolved the case. For example if ($to2 -ne '') is checking if $to2 cell is empty. If no, then $mail.To.Add($to2). The same situation for $Attachment. Here is the code:
$mail = New-Object System.Net.Mail.MailMessage
$mail.From = $emailFrom
$mail.To.Add($to)
if ($to2 -ne '') {
$mail.To.Add($to2)
}
$mail.Subject = $emailSubject
$mail.IsBodyHtml = $true
$mail.Body = $body
$mail.Attachments.Add($Attachment)
if ($Attachment2 -ne '') {
$mail.Attachments.Add($Attachment2)
}

Powershell Get-ChildItem

I have a powershell script I wrote to check the contents of a folder and if there is a file with a LastWriteTime older than 20 minutes to notify me. The problem I am having is when I get the results it is including all of the files in the email body. How would I write this to get only the latest filename in the email body?
$src = 'c:\test'
$sendmail = $false
Get-ChildItem -path $src | ForEach-Object {
#write-host $_.fullname
$dtdiff = New-TimeSpan ($_.LastWriteTime) $(Get-Date)
if ($dtdiff.TotalMinutes -gt 20){
$strbody=$strbody +$_.fullname+ " Last File Modified at " +$_.LastWriteTime +"`r`n"
$sendmail=$true
}
}
#$strbody
if($sendmail -eq $true){
# Email components
$strFromAddress = "abc#xyz.net"
$strToAddress = "abc#xyz.net"
$strMessageSubject = "REPORT"
$strMessageBody = $strbody
$strSendingServer = "smtp.com"
$SMTPPort = "587"
$emailSmtpUser = "abc#xyz.net"
$emailSmtpPass = "test123"
# Email objects
$objSMTPMessage = New-Object System.Net.Mail.MailMessage $strFromAddress, $strToAddress, $strMessageSubject, $strMessageBody
$objSMTPClient = New-Object System.Net.Mail.SMTPClient( $strSendingServer, $SMTPPort )
$objSMTPClient.EnableSsl = $true
$objSMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
$objSMTPClient.Send($objSMTPMessage)
}
To get only the most actual file: Edited to remove flaw
Get-ChildItem -path $src |
Sort LastWriteTime |
Select -last 1 |
ForEach-Object {
#write-host $_.fullname
$dtdiff = New-TimeSpan ($_.LastWriteTime) $(Get-Date)
if ($dtdiff.TotalMinutes -gt 20){
$strbody=$strbody +$_.fullname+ " Last File Modified at " +$_.LastWriteTime +"`r`n"
$sendmail=$true
}
}
You're appending each filename and its associated timestamp to $strbody in that loop. It's doing exactly what you specified.
If you want only the latest file that was created in the last 20 minutes, change your get-childitem/foreach loop to this:
$mostrecentfile = get-childitem -path $src |
where-object {$_.lastwritetime -gt (get-date).addminutes(-20)} |
sort-object -property lastwritetime -descending | select-object -first 1
}
if ($mostrecentfile -ne $null) {
$strbody=$_.fullname+ " Last File Modified at " +$_.LastWriteTime;
$sendmail = $true;
}
get-childitem "c:\temp" -file | where LastWriteTime -le (Get-Date).AddMinutes(-20) |
Sort lastwritetime -descending |
% {
$strFromAddress = "abc#xyz.net"
$strToAddress = "abc#xyz.net"
$strMessageSubject = "REPORT"
$strMessageBody = "Last file modifed '{0}' at {1}" -f $_.fullname, $_.LastWriteTime
$strSendingServer = "smtp.com"
$SMTPPort = "587"
$emailSmtpUser = "abc#xyz.net"
$emailSmtpPass = "test123"
# Email objects
$objSMTPMessage = New-Object System.Net.Mail.MailMessage $strFromAddress, $strToAddress, $strMessageSubject, $strMessageBody
$objSMTPClient = New-Object System.Net.Mail.SMTPClient($strSendingServer, $SMTPPort )
$objSMTPClient.EnableSsl = $true
$objSMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
$objSMTPClient.Send($objSMTPMessage)
$objSMTPClient.Dispose()
break
}

Error while sending email through outlook in power shell script

I have a powershell script as below. Here I check whether any .err file has been created before 5 minutes and if yes, then I am sending an email for each error file with first 5 lines of the .err file.When I try to run the script I receive an email for the first file, but i get an error for the second file as shown in the snapshot below. I am new to powershell, and I am struggling to find any solution for this error.
$ChkFile = "D:\ErrorLog\*.err"
$ChkFilePath = "D:\ErrorLog"
$o = New-Object -comObject Outlook.Application
$mail = $o.CreateItem(0)
$mail.importance = 2
$mail.subject = “Error Log“
$mail.To = “email#email.com“
$FileExists = Test-Path $ChkFile
$FileCount = Get-ChildItem $ChkFilePath *.err | Measure-Object | %{$_.Count}
If ($FileExists -eq $True) {
If ($FileCount -gt 0)
{
Foreach($file in (Get-ChildItem $ChkFile))
{
Write-Host $file
$createtime = $file.LastWriteTime
$nowtime = get-date
if (($nowtime - $createtime).totalminutes -gt 5)
{
$GetFileContent = Get-Content $file -totalcount 5
$mail.body = $GetFileContent
Write-Host $GetFileContent
$mail.Send()
}
}
}
}
Error generated while executing the script:
After you invoke the $mail.Send() method you will likely need to recreate your mail object. You could do this by placing the object creation in the loop.
$ChkFile = "D:\ErrorLog\*.err"
$ChkFilePath = "D:\ErrorLog"
$o = New-Object -comObject Outlook.Application
$FileExists = Test-Path $ChkFile
$FileCount = Get-ChildItem $ChkFilePath *.err | Measure-Object | %{$_.Count}
If ($FileExists -eq $True) {
If ($FileCount -gt 0) {
Foreach($file in (Get-ChildItem $ChkFile)) {
Write-Host $file
$createtime = $file.LastWriteTime
$nowtime = get-date
if (($nowtime - $createtime).totalminutes -gt 5) {
$mail = $o.CreateItem(0)
$mail.importance = 2
$mail.subject = "Error Log"
$mail.To = "email#email.com"
$mail.importance = 2
$mail.subject = "Error Log"
$mail.To = "email#email.com"
$GetFileContent = Get-Content $file -totalcount 5
$mail.body = $GetFileContent
Write-Host $GetFileContent
$mail.Send()
}
}
}
}