Sorry I am just starting out writing a PowerShell scripts. I am trying to use a script to send a email once an event (error) comes across the Event Viewer. I do not want to use the feature that is incorporated in Event Viewer because it does not work on all Operating Systems. Here is what I have in my script now but I cannot import the Message or Data from the error that cut.
$event = Get-EventLog -LogName Application -Source "My Script-1" | where {$_.eventID -eq 1}
if ($event.EntryType -eq "Error")
{
[string]$EmailBody = Event.Data
$EmailFrom = "Test#google.com"
$EmailTo = "lmill130#kent.edu"
$EmailSubject = "This was sent from a PowerShell Script"
$SMTPServer = "Example Server SMTP"
Write-host "Sending Email Test"
Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -Body $EmailBody -SmtpServer $SMTPServer
}
else
{
write-host "No error found"
write-host "Here is the log entry that was inspected:"
$event
}
If I put my own string in $EmailBody then it works with no issue but when I try to grab data from the Event I have no luck.
This is the script I use to create the test event.
#New-EventLog -LogName Application -Source "My Script-1"
Write-EventLog -LogName Application -Source "My Script-1" -EntryType Error -
EventId 1 -Message "This is a test Entry."
I have a task created that when that event cuts then it runs the first script.
I have searched all over the internet and I have had no luck. Help please.
Thats probaly because Event.Data doesn't return anything.
It has to be $event.Data, but I think you should maybe use $event.Message to get the info message of the error.
So all together would look like this:
$event = Get-EventLog -LogName Application -Source "My Script-1" | where {$_.eventID -eq 1}
if ($event.EntryType -eq "Error")
{
[string]$EmailBody = $event.Data
#or [string]$EmailBody = $event.Message
$EmailFrom = "Test#google.com"
$EmailTo = "lmill130#kent.edu"
$EmailSubject = "This was sent from a PowerShell Script"
$SMTPServer = "Example Server SMTP"
Write-host "Sending Email Test"
Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -Body $EmailBody -SmtpServer $SMTPServer
}
else
{
write-host "No error found"
write-host "Here is the log entry that was inspected:"
$event
}
Replace [string]$EmailBody = Event.Data
with [string]$EmailBody = $Event.Data
And its always better to use Message rather than data cause you are more bothered about the error message not the data which is going to be get captured.
Hope it helps.
Related
Can someone please help me figure this part out.
#Mail Configuration
$smtpUser = "email#domain.com"
$smtppass = ConvertTo-SecureString "PasswordAsPlainText" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential -ArgumentList ($smtpuser, $smtppass)
$ToAddress = "toaddress#domain.com"
$FromAddress = "send#domain.com"
$SMTPSERVER = "smtp.office365.com"
$SMTPPORT = "587"
$MailParam = #{
To = $ToAddress
From = $FromAddress
Subject = $subject
Body = $Mail
SMTPServer = $SMTPServer
Port = $SMTPPORT
Credential = $pscred
}
#Send Email
$GetChildItem = Get-ChildItem -Path C:\Temp
if ($GetChildItem -ne $Null)
{
Write-Host "Backup Success"
$subject = "$env:COMPUTERNAME SQL Backup Success"
$Mail = "SQL Backup Succeded on the server, please see the attached report for more details"
$attachment = $reportfile
Send-MailMessage #MailParam -BodyAsHtml -usessl
#Exit
}
if ($GetChildItem -eq $Null)
{
Write-Host "Backup Failed"
$subject = "$env:COMPUTERNAME SQL Backup Failed"
$Mail = "SQL Backup Failed on the server, please see the attached report for more details"
$attachment = $reportfile, $debuglog
Send-MailMessage #MailParam -usessl -BodyAsHtml
#Exit
}
Now I don't think anything is wrong with the code above, I am no expert coder but I can pretty much copy and paste :) and take stuff from there to get it working for me.
The issue with the above code is that when run it, it doesn't work for the 1st time but when you run it again it works fine. The error you get the first time is
Send-MailMessage : Cannot validate argument on parameter 'Body'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\Aasim\Desktop\Untitled1.ps1:29 char:26
+ Send-MailMessage #MailParam -BodyAsHtml -usessl
+ ~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
I am not sure what the issue is and why it doesn't work only the first time but works every other subsequent time until you close and reopen the script.
Basically I am creating a SQL backup script that backs up databases to our Network Share and then emails me whether it was successful or not. so far the rest of the script works just fine.
In your If and Else blocks, instead of creating a variable $subject, or $Mail, update the hashtable, $MailParam. Also, you seem to be missing the Attachment variable in your Send-MailMessage
if ($GetChildItem -eq $Null)
{
Write-Host "Backup Failed"
$MailParam.Subject = "$env:COMPUTERNAME SQL Backup Failed"
$MailParam.Body = "SQL Backup Failed on the server, please see the attached report for more details"
$attachment = $reportfile, $debuglog
Send-MailMessage #MailParam -usessl -BodyAsHtml -Attachments $attachment
#Exit
}
I'm creating a PS script to automate email blast to 17k users. Our exchange security baseline is set to only accept 60 requests per minute. Because I'm looping through the email list (CSV) line by line (sleep 1 sec), it took hours for my script to complete. What I'm trying to achieve now is to send the email to 100 users per request. I'm figuring out how to store the emails in an array of 100 & send the mail before going for the next 100. Any suggestion?
$recipients = Get-Content "mailinglist.csv"
foreach($rcpt in $recipients)
{
Write-Host "Attempt sending email to $rcpt ..."
Send-MailMessage -ErrorAction SilentlyContinue -ErrorVariable SendError -From $From -to $rcpt -Subject $Subject -SmtpServer $SMTPServer -port $SMTPPort -UseSsl -Credential $Cred -BodyAsHtml ($Body -f $Subject, $Date, $Venue, $Description, $Image)
$ErrorMessage = $SendError.exception.message
If($ErrorMessage)
{
Write-Host "Failure - $ErrorMessage" -ForegroundColor Red
Start-Sleep -Seconds 60
Send-MailMessage -ErrorAction SilentlyContinue -ErrorVariable SendError -From $From -to $rcpt -Subject $Subject -SmtpServer $SMTPServer -port $SMTPPort -UseSsl -Credential $Cred -BodyAsHtml ($Body -f $Subject, $Date, $Venue, $Description, $Image)
}
ElseIf($SendError.exception.message -eq $null)
{
Write-Host "Email has been sent to $rcpt" -ForegroundColor Green
Start-Sleep -Seconds 1
$n++
}
}
Write-Host "Total sent = $n"
You could use a traditional for loop and access your array elements by index.
$recipients = Get-Content "mailinglist.csv"
$To = <SomeValidEmailAddress>
$LastIndex = $recipients.GetUpperBound(0)
for ($i = 0; $i -le $LastIndex; $i+=100) {
$upperRange = [Math]::Min(($i+99),$LastIndex)
$Params = #{
ErrorAction = 'SilentlyContinue'
ErrorVariable = 'SendError'
Bcc = $recipients[$i..$upperRange]
To = $To
From = $From
Subject = $Subject
SmtpServer = $SMTPServer
Port = $SMTPPort
Credential $Cred
Body = $Body -f $Subject, $Date, $Venue, $Description, $Image
BodyAsHTML = $true
UseSsl = $true
}
"Attempt sending email to $($recipients[$i..$upperRange]) ..." # You may want to alter this to be more readable
Send-MailMessage #Params
# Other code
}
Explanation:
I've opted to use Splatting here for readability and manageability with the $Params hash table. It is entirely optional.
The -bcc parameter of Send-MailMessage supports a string array (string[]). Using this over the -To parameter will preserve privacy of the recipients. You can then easily send an email to multiple recipients provided you pass it an array. However, -To is required for Send-Mailmessage to work. It is recommended to make the email address passed into -To something that can be spammed or has a way of handling these types of emails. I have set up the $To variable for you to provide that email address. If privacy is of no concern whatsoever, -Bcc can just be replaced with -To.
Since $recipients is an array, you can access its elements by index, which supports the range operator ... $recipients[0..99] would be the first 100 items in the list.
$LastIndex stores the last index of the list, which is the value returned by the Array.GetUpperBound(Int32) method with dimension 0. Since the array is one-dimensional, 0 is the only dimension.
$upperRange is the beginning index ($i) plus 99. Should $upperRange ever be larger than $LastIndex, it will be set to $LastIndex. Depending on your PowerShell version, the $i+99 and $LastIndex comparison may not be necessary. Accessing an upperbound range beyond the size of the array, will just return all of the remaining elements of the array without throwing an error. This is likely just for completeness.
I am new to powershell and I am trying to write a script that will email me whenever someone moves or deletes a file or folder from a shared drive. I already set up the task scheduler to execute the script when one of those events happen. The problem that I have is that I execute script from the shell it provides me with all the information regarding the last entry in the event logs. However, when it runs from the task scheduler it does not execute. I believe that it has to do with the body line. Any suggestions or insights will be greatly appreciated.
This is my code:
$events = Get-EventLog -Logname Security -Newest 1
$From = $env:COMPUTERNAME + "#company.com"
$To = "me#company.com"
$Subject = $env:COMPUTERNAME + " " + $env:UserName + " " + $_.eventID
$Body = $events | format-list -property * | out-string
$SMTPServer = "exch"
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SMTPServer $SMTPServer
Quick question;
I want to make a log of bad stuff happening to the servers, but that's not the question.
The log should be deleted upon send, and if there is no log at the time the script is being run it should send a different message, without an attachment.
Here's the script so far:
<#
Set-ExecutionPolicy unrestricted -Force
iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
cinst BetterCredentials
#>
Import-Module BetterCredentials
$Mailcred = Get-Credential -user user#gmail.com -pass 12345password
Try{
$File = C:/path/errorfile.log
}
Catch [System.Management.Automation.PSArgumentException]
{
"invalid object"
}
Catch [system.exception]
{
"caught a system exception"
}
Finally
{
If ($File -eq ){
then (send-mailmessage -ErrorAction SilentlyContinue -from "Server <Server#company.com>" -to "IT Dept. <Itdept#company.com>" -subject "Log of the day." -body "Good Morning,
Fortuneatly, nothing bad to report today!" -priority High -dno onSuccess, onFailure -smtpServer smtp.company.com -credential ($Mailcred) -usessl)
else (send-mailmessage -ErrorAction SilentlyContinue -from "Servers <Server#company.com>" -to "IT Dept. <ITDept#company.com>" -subject "Log of the day." -body "Good Morning,
Here is your daily report." -Attachments $File -priority High -dno onSuccess, onFailure -smtpServer smtp.company.com -credential ($Mailcred) -usessl)
}
}
What AM I doing wrong here?
Some parts of your code do not make any sense. Let's review those.
$File = C:/path/errorfile.log
...
If ($File -eq ){
The first part is about assignment. In order to find out wether errorfile.log exists, use the Test-Path cmdlet like so,
$File = test-path 'C:/path/errorfile.log'
Always use quotes around file name. If you got spaces within path, unquoted path doesn't work.
The second part is the actual test.
If ($File){
... # file was on disk, send alert and delete it
} else {
... # no file found, send ok
}
Here is my code that checks when users passwords will expire and emails them if it will expire in less than 14 days. Since the link in the body of the email has spaces in it, the link does not encompass the whole file name.
#Add the Quest PowerShell snapin
Add-PsSnapIn Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
#Clear the placeholder log file
Clear-Content O:\logs\network\passwordchangeemails.txt
#Set Email Variables
$today = Get-Date
$logdate = Get-Date -format yyyyMMdd
$emailFrom = "my.name#mycompany.com"
$body = "Good Morning, `n`n"
$body += "As a courtesy reminder, your Company password will be expiring soon. `n`n"
$body += "If you allow your password to expire, you will be unable to access our network, mail or QAD until you recieve assistance from the Helpdesk. `n`n"
**$body += "To avoid this, please change your network password as soon as possible. (Remote users, please follow the password change procedure for remote users. Click Here -> " + "\\mydfsshare.net\share\helpdesk\guides\Passwords - Change procedure for remote users.pdf ) `n`n"**
$body += "Feel free to contact the Help Desk by phone at 555-555-5555 or by email at Helpdesk#mycompany.com `n"
$body += "Thanks!"
#Get Active Directory Information
Get-QADUser -SizeLimit 0 | Select-Object samAccountName,mail,PasswordStatus |
Where-Object {$_.PasswordStatus -ne "Password never expires" -and $_.PasswordStatus -ne "Expired" -and $_.PasswordStatus -ne "User must change password at next logon." -and $_.mail -ne $null} |
#For each user, get variables
ForEach-Object {
$samaccountname = $_.samAccountName
$mail = $_.mail
$passwordstatus = $_.PasswordStatus
$passwordexpiry = $passwordstatus.Replace("Expires at: ","")
$passwordexpirydate = Get-Date $passwordexpiry
$daystoexpiry = ($passwordexpirydate - $today).Days
#If days to expire is lessthan 14 days, send email to user
if ($daystoexpiry -lt 14) {
$emailTo = "$mail"
$subject = "Company IT Notification: Your Network password will expire in $daystoexpiry day(s). "
Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -SmtpServer 192.168.1.191
Write-Host "Email was sent to $mail on $today"
Add-Content O:\logs\network\passwordchangeemails.txt "Email was sent to $mail on $today"
}
}
$recipients = "my.name#mycompany.com"
#Copy contents of log file to email and send to IT Department
$content = [IO.File]::ReadAllText("O:\logs\network\passwordchangeemails.txt")
Send-MailMessage -To $recipients -From "my.name#mycompany.com" -Subject "Password change log for $today" -Body "This is the log from $today, $content" -SmtpServer 111.111.111.111
Sorry I can't test this right now but if HTML is OK to use, try wrapping the link as follows...
"Text you want the users to see goes here<br>`n
Then set -BodyAsHtml on Send-Mailmessage:
Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -SmtpServer 192.168.1.191 -BodyAsHtml