$mail = New-Object System.Net.Mail.MailMessage
$mail.From = “"
$mail.To.Add("”)
$mail.Subject = “Event Viewer Log Issues”
$mail.Body = “The following are the Errors and Warnings logged from the Event Viewer Over-Night”
Can you please format your code using the “preformatted text” button in the composition window, or put 3 back ticks above and below your code (same thing)?
I’ll do some research on the SMTP problem but right now you’re biggest problem is you just posted your Yahoo password on the internet. Edit your post immediately and take that out, and change your Yahoo password.
EDIT: seeing as how you have mfa turned on for your yahoo account I suspected it was something to do with that. A quick search yielded this page:
You’ll have to log in to your Yahoo account and generate an App password and then re-test using that. The rest of your code seems fine from what I can see and test.
Ultimately I would recommend using a 3rd party service for sending mail instead of a personal account. Something like: https://www.smtp2go.com/
Thanks so much for catching that Grey. I thought I “starred” it out but apparently I wasnt paying attention when I posted that. Password changed. God bless you Sir. As far as the rest of the code is concerned still not working. Will test some more today. Thank you
Trying to add the following before send but I believe its the wrong syntax:
$mail.Attachments =
Getting a Read only error
What I am trying to do is attach the contents of a folder using the folder path as follows:
$mail.Attachments = "C:\WindowsEventLogs"
getting the following error msg:
InvalidOperation:
Line |
39 | $mail.Attachments = "C:\WindowsEventLogs"
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| ‘Attachments’ is a ReadOnly property.
pretty sure you can’t just point at a folder and have it assume the contents.
You’re gonna need to specify them manually, and even then I wouldn’t. You’ll probably want to add them to a zip archive first and be wary of the size because SMTP still has a max size limit.
EDIT:
Ok, first off, please make sure you’re always using the “Preformatted Text” button when sharing any kind of code (code from an IDE, shell output, errors, etc). It makes it much easier to read.
Secondly, maybe it’s time to look at using the built-in cmdlet Send-MailMessage. It’s not going to solve your attachments problem but it can be easier to read.
There are a lot of parameters for Send-MailMessage so I suggest building a hashtable and then splatting it. good article on Send-MailMessage
$Credential = Get-Credential -Credential nal2us2@yahoo.com
#then provide your password at the prompt
$SendMail = @{
From = "nal2us2@yahoo.com"
To = "nal2us2@yahoo.com"
Subject = "Event Viewer Log Issues"
Body = "The following are the Errors and Warnings logged from the Event Viewer Over-Night"
Priority = "High"
Attachments = Get-ChildItem "C:\WindowsEventLogs"
SMTPServer = "smtp.mail.yahoo.com"
Port = "465"
Credential = $Credential
BodyAsHtml = $true
ErrorAction = "Stop"
}
Send-MailMessage @SendMail
If you really must leave your password in plain text in your script. then change the top part out for this
I tested this in my own environment (using different SMTP settings) and it works. Get-ChildItem is providing an array of files to the Attachments parameter, which automatically leverages the ToString() method on them to satisfy the type requirement for the parameter. I end up with an email containing multiple attachments.
Now as long as your files in that directory are small you should be able to get away with doing this (less than 25MB total is the figure to keep in mind).
Your code is still using the .NET SmtpClient, which should work, but why do that when Send-MailMessage exists?
Either way, you’re still not feeding “Attachments” an array of strings which is what it requires.
Change this line:
Ok, stop using the .NET method for sending mail and just use Send-MailMessage.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Define the event logs to extract
$logArray = @("Application", "System", "Security", "Setup")
#, "Forwarded Events"
# Provide the path to store the log file extraction
$destinationPath = "C:\WindowsEventLogs\"
# Get the current date in YearMonthDay format
$logDate = Get-Date -Format yyyyMMddHHmm
# Initialize an empty array to store log entries
$output = @()
# Extract each log file listed in $logArray
foreach ($log in $logArray) {
$destination = Join-Path $destinationPath "$env:COMPUTERNAME-$log-$logDate.evtx"
Write-Host "Extracting the $log file now."
wevtutil epl $log $destination
}
# Send the log file via email
$Password = "MyPassword" | ConvertTo-SecureString -AsPlainText -Force
$Credential = [System.Management.Automation.PSCredential]::new("nal2us2@yahoo.com", $Password)
$SendMail = @{
From = "nal2us2@yahoo.com"
To = "nal2us2@yahoo.com"
Subject = "Event Viewer Log Issues"
Body = "The following are the Errors and Warnings logged from the Event Viewer Over-Night"
Priority = "High"
Attachments = Get-ChildItem "C:\WindowsEventLogs\*.evtx"
SMTPServer = "smtp.mail.yahoo.com"
Port = 587
Credential = $Credential
BodyAsHtml = $true
ErrorAction = "Stop"
}
Send-MailMessage @SendMail
EDIT:
and the reason why you’re getting this error:
Is because according to the documentation for this .NET class you can’t provide a string as a value for the Attachments property on a MailMessage object. You have to create an Attachment object, and then call the “Add” method on MailMessage to add the object.
But the “New” method on the Attachment object only accepts a single string for input, so you’d have to loop through all of the attachments you want to add, create them as Attachment objects and add them one at a time to the Attachments property of the MailMessage.
Again, use Send-MailMessage instead and avoid all of this.
It looks like there are no built in cmdlets that can output an .evtx file. There’s a Get-WMIObject method that a lot of people reference but that’s not available in Powershell 7.4 so I went looking further and found a post on this same forum with another technique:
They use a .NET class to read the logs and it has an ExportLog method. It relies on some XML filtering to get what you want but that’s fairly well documented out there too.
Try using this block of code in your script:
# Extract each log file listed in $logArray
$EventSession = New-Object System.Diagnostics.Eventing.Reader.EventLogSession
foreach ($log in $logArray) {
$destination = Join-Path $destinationPath "$env:COMPUTERNAME-$log-$logDate.evtx"
Write-Host "Extracting the $log file now."
$EventSession.ExportLog($Log,'LogName',"*[System[(Level=2 or Level=3)]]",$Destination)
}
This creates the EventLogSession object for reading/exporting the logs, then in your existing loop we just replace the use of wevtutil with the ExportLog method with the following arguments
$Log = The path from Windows Event Viewer
‘LogName’ = the path type from Windows Event Viewer
“*[System[(Level=2 or Level=3)]]” = string query where level correpsonds to the Event Level
Level 1 = Critical
Level 2 = Error
Level 3 = Warning
etc…
$Destination = the filepath destination for where to export the filtered log to
I tested this on my machine with Powershell 7.4 and it worked. The resulting combined file size went from 60MB (too big for email) to only 4.5MB.