I found one script to calculate the number of files in a folder(looks Ok), but for some reason it doesn't work. The goal is that if the number of files in the folder exceeds five, I get an automatic notification about it.
If anyone can help me, I'm not very good at scripts, this is script that I found and doesn't work:
$Output = "c:\Test\*"
If (Get-Content -Path $Output | Where-Object {$_.Count -gt10})
{
$MailArgs = #{
'To' = "my#mail.com"
'From' = "some#mail.com"
'Subject' = "some text"
'Body' = "Number of files"
'SmtpServer' = "smtp"
}
Send-MailMessage #MailArgs
}
Replace this:
(Get-Content -Path $Output | Where-Object {$_.Count -gt 10})
with this:
((Get-ChildItem $Output | Measure-Object).Count -gt 10)
Related
I have a question that I hope one of you can help me with.
The following script does its job, it sends the email of the folders that are older than 30 days.
I want to add 2 more features...
If the OwnerEmail.txt is not there or empty.. it will not send the email.
If there are not folders older than 30 days, it will not send the email.
I am just having problems using the CONTINUE feature to skip the ForEach
$ParentFolders = Get-ChildItem -Path "C:\Test\WRA" -Directory |
Select-Object -ExpandProperty FullName
foreach ($SubFolder in $ParentFolders) {
$Contact = Get-Content -Path ($SubFolder + "\OwnerEmail.txt")
$emailTime = (Get-Date).ToString("MM/dd/yyyy")
$WRAHTMLReport = Get-ChildItem -Path $SubFolder -Directory |
Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-30))} |
Select-Object Name, CreationTime |
ConvertTo-Html -Head $Header -PreContent "
<h2>Current Nuix Case(s)</h2>
<body>
Report was sent on $emailTime
<br></br>
When you have a moment can you please confirm if any of these cases can be removed from Nuix:
<body>
<br></br> " |
$WRAHTMLReport = $WRAHTMLReport -join ""
Start-Sleep -s 2
Send-MailMessage -SmtpServer mail.company.com -to $Contact -from cubam1#company.com -Subject "Nuix Cases" -Body $WRAHTMLReport -BodyAsHtml
}
So, it could look something like this, note that I'm only showing the relevant parts of the code.
I think in this case, is safe to put the $emailTime outside the loop since you're only gathering the date in MM/dd/yyyy format and, I also added the $folderLimitDate outside the loop.
This variable contains the HTML body
$mailBody = ConvertTo-Html -InputObject $WRAHTMLReport... so remember to change the -Body $mailBody on Send-MailMessage
$emailTime = (Get-Date).ToString("MM/dd/yyyy")
$folderLimitDate = (Get-Date).AddDays(-30)
foreach ($SubFolder in $ParentFolders)
{
$path = Join-Path $SubFolder -ChildPath 'OwnerEmail.txt'
# If OwnerEmail.txt doesn't exist on this path,
# go to next loop iteration
if(-not(Test-Path $path)){ continue }
$Contact = Get-Content $path
$WRAHTMLReport = Get-ChildItem -Path $SubFolder -Directory |
Where-Object LastWriteTime -LT $folderLimitDate |
Select-Object Name, CreationTime
# If this variable is null, go to next loop iteration
if(-not $WRAHTMLReport){ continue }
[string]$mailBody = ConvertTo-Html -InputObject $WRAHTMLReport...
...
...
...
I never wrote a PowerShell script before, so I created the next script with the help of many different google searches :) so it might be a little patchy, I am by no means a "scripter"
To sum up I need to create a report of emails sent by specific mailboxes and return the data into Excel with this headers: time sent, sender, display name, recipients, subject.
I need help with adding the display name from the $output file
This is the what I created so far:
#Variables:
$output = "C:\temp\Source.csv"
$Unfiltered = "C:\temp\ReportUnfiltered.csv"
$UnfilteredV2 = "C:\temp\ReportV2.csv"
$CSVreport = "C:\temp\ReportV3.csv"
$finaleReportX = "C:\temp\finalReport.xlsx"
$To = "user#domain.com"
$desiredColumns = 'Date','Time','Sender','DisplayName','Recipients','MessageSubject'
#Create Source file:
get-mailbox -resultsize unlimited | where {$_.primarysmtpaddress -like "sales*"} | Select #{N='primarysmtpaddress';E={$_.primarysmtpaddress[0]}},displayname | export-csv $output -NoTypeInformation
$query = Import-Csv -Path $output
#Create Report for sent:
foreach ($Address in $query) {
Get-MessageTrackingLog -server exchange.domain.com -Start (get-date).addhours(-24) -end (Get-Date) -sender $Address.primarysmtpaddress |
where-object {$_.EventID -eq ‘RECEIVE’} |
Select Timestamp,sender,#{Name='Recipients';Expression={[string]::join(“;”, ($_.Recipients))}},MessageSubject,MessageID |
export-csv $Unfiltered -NoTypeInformation -encoding utf8 -Append
}
#Fix Timestamp:
Import-Csv $Unfiltered |
Select-Object *,
#{n='Date';e={$_.Timestamp.Split(" ")[0]}},
#{n='Time';e={$_.Timestamp.Split(" ")[1]}} |
export-csv $UnfilteredV2 -NoTypeInformation -encoding utf8
# Selects desired columns
Import-Csv $UnfilteredV2 | Select $desiredColumns |
Export-Csv -Path $CSVreport –NoTypeInformation -encoding UTF8
# Export to Excel
Import-Csv $CSVreport | Select $desiredColumns |
Export-Excel -Path $finaleReportX | Format-Table –AutoSize
#Send Final Report:
$email = #{
From = "Report#domain.com"
To = $To
subject = “Report for All sent items"
SMTPserver = "exchange.domain.com"
Body = "See the attached Report"
Attachment = $finaleReportX
}
send-mailmessage #email
# Delete Reports From Local Drive
Remove-Item –path $output –recurse
Remove-Item –path $Unfiltered –recurse
Remove-Item –path $UnfilteredV2 –recurse
Remove-Item –path $CSVreport –recurse
Remove-Item –path $finaleReportX –recurse
You are creating a lot of in-between csv files and load them back in. I don't think this is necessary if you combine all queries in a single ForEach-Object{} loop with a foreach() loop inside that.
Also, because of copy/paste from the internet, there were some curly 'smart-quotes' in the code (“, ”). Lots of times, PowerShell can handle that, but it is always better to use straight quotes " and ' in code.
Something like this:
# Variables:
$to = 'user#domain.com'
$from = 'Report#domain.com'
$smtpServer = 'exchange.domain.com'
$finaleReportX = 'C:\temp\finalReport.xlsx'
$today = Get-Date
$yesterday = $today.AddHours(-24)
# Create Report for email. Gather everything in a variable
$result = Get-Mailbox -Resultsize Unlimited |
Where-Object {$_.primarySmtpAddress -like "sales*"} |
ForEach-Object {
$emailAddress = #($_.primarySmtpAddress)[0]
$displayName = $_.DisplayName
$trackingLog = Get-MessageTrackingLog -Server exchange.domain.com -Start $yesterday -End $today -Sender $emailAddress |
Where-Object {$_.EventID -eq 'RECEIVE'}
# loop through the items in the tracking log and create objects from that
$trackingItems = foreach ($item in $trackingLog) {
$date, $time = $item.Timestamp -split ' '
# output an object with the desired properties to be collected in variable $trackingItems
[PsCustomObject]#{
Date = $date
Time = $time
DisplayName = $displayName
Sender = $item.Sender
Recipients = $item.Recipients -join ';'
MessageSubject = $item.MessageSubject
# MessageID = $item.MessageID # usure if you want this in your report aswell..
}
}
# output the in-between results to be collected in variable $result
$trackingItems
}
# Export to Excel file
$result | Export-Excel -Path $finaleReportX -Title 'Email tracking log' -AutoSize
# Send Final Report:
$email = #{
From = $from
To = $to
Subject = 'Report for All sent items'
SMTPserver = $smtpServer
Body = 'See the attached Report'
Attachments = $finaleReportX
}
Send-MailMessage #email
# Delete Report From Local Drive
Remove-Item -Path $finaleReportX
how to delete files older then x days and send only email notification, if files are deleted by script. Here is my script.. files are deleted by script, but email notification is not working. If I delete the if clauses (if(!$messageBody)) then email notification is working, but I am getting email when no files are deleted, too.
Get-ChildItem temp*.zip -Path "c:\tempfiles" |
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-0) }|
ForEach-Object {
$_ | Remove-Item -force
-join $([datetime]::Now) + " " + $_.Name| Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
$OF = "`r`n"
$messageBody = $_.Name + $OF + $messageBody
}
$date = ( get-date )
if(!$messageBody){
$smtpServer = ""
$smtpFrom = ""
$smtpTo = ""
$server = ""
$messageSubject = "Subject $server - $date"
$body= "files"
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)
$messageBody=" "
}
You can do the following to find temp*.zip files, delete them, log the deleted files to a log file, and then email a list of deleted files. This assumes your deletions are successful. You will need to remove the -WhatIf parameter for deletions to occur.
Get-ChildItem -Filter temp*.zip -Path "c:\tempfiles" -File -OutVariable files | Foreach-Object {
$_ | Remove-Item -Force -WhatIf
"{0} {1}" -f (Get-Date),$_.Name |
Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
}
if ($files) {
$MailParams = #{ 'To' = 'to#domain.com'
'From' = 'from#domain.com'
'Subject' = "Subject server $(Get-Date)"
'Body' = $files.Name | Out-String
'SmtpServer' = 'smtpservername'
}
Send-MailMessage #MailParams
}
If you want error checking and only report when files are deleted, you can make some modifications.
$files = [Collections.Generic.List[String]]#()
Get-ChildItem -Filter temp*.zip -Path "c:\tempfiles" -File | Foreach-Object {
$_ | Remove-Item -Force -WhatIf
if ($?) {
"{0} {1}" -f (Get-Date),$_.Name |
Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
$files.Add($_.Name)
}
}
if ($files) {
$MailParams = #{ 'To' = 'to#domain.com'
'From' = 'from#domain.com'
'Subject' = "Subject server $(Get-Date)"
'Body' = $files.Name | Out-String
'SmtpServer' = 'smtpservername'
}
Send-MailMessage #MailParams
}
$? returns true if the last command executed successfully. See About_Automatic_Variables.
The syntax #MailParams is called Splatting. It is simply used here for readability.
I have a task to monitor if files exist in certain folders for longer then 5 minutes. I need the script to only send emails if files exist older then 5 minutes. Right now the script will run and email me however I am having trouble getting the output formatted correctly.
I'd like the email to include the first column of the CSV, Company, the path and the output of get-childitem. I will be removing the write-host's since the script will run via a scheduled task. The CSV has the following format..
\\some\share
\\some\share2
\\some\share3
Though I would like to have it as..
Company1,\\some\share
Company2,\\some\share2
Company3,\\some\share3
So that I can include the first header in the email
Here's what I have for the code so far..
$SmtpClient = new-object system.net.mail.smtpClient
$MailMessage = New-Object system.net.mail.mailmessage
$SmtpClient.Host = "smtp.some.address"
$MailMessage.from = ($ServerName + "#someaddress.com")
$MailMessage.To.add("me#someaddress.com")
$MailMessage.Subject = "File Monitor"
$date = (get-date).AddMinutes(-5)
foreach($path in get-content "C:\Scripts\servers_path.txt") {
if ((Test-Path -path $path)) {
$item = get-childitem $path *.* | where-object {$_.LastWriteTime -lt $date}
$item | Select FullName, Name, LastWriteTime
if ($item) {
$MailMessage.Body += "$path `n"
$MailMessage.Body += "$item `n`n"
$MailMessage.Body += "---------------------------------------------------------------------------------------------------------`n"
}
}
elseif (!(Test-Path $path)) {
Write-Host "The folder," $path "does not exist" -fore red
}
}
$SmtpClient.Send($MailMessage)
Thank you
I think originally I was confusing your input as output in the question. How about something like this then? Assuming the following input data is contained in "c:\temp\data.txt".
Company1,\\some\share
Company2,\\some\share2
Company3,\\some\share3
Read the comments in code to get a sense for what is going on there. This code would go in place of your ForEach loop that you already have in theory. You would need to play with the output to get your desired outcome. If I am off base be as verbose as possible.
$date = (get-date).AddMinutes(-5)
# Import the data as a csv into PowerShell specifying the headers since they dont exist.
Import-csv -Path "c:\temp\data.txt" -Header "Company","Path" | ForEach-Object{
# Check if the path is valid for this item.
If(Test-Path $_.Path){
# This folder exists. Check the contents for certain files.
$data = Get-ChildItem $_.Path | Where-Object {$_.LastWriteTime -lt $date}
If($data){
# Output the company name and path on a separate line.
$message = "`r`n$($_.Company)`r`n$($_.Path)`r`n"
# Output each file on its own line.
$message += "$(($data | Select-Object -ExpandProperty Name) -Join "`r`n")"
# Append built string to the body of the email.
$MailMessage.Body += $message
}
} Else {
# Path does not exist. Have message stating such.
$MailMessage.Body += "`r`n$($_.Company)`r`n$($_.Path) does not exist `r`n"
}
}
If you wanted to return more properties like LastWriteTime we could do that if we replace this one line
$message += "$(($data | Select-Object -ExpandProperty Name) -Join "`r`n")"
With something like this:
$data | ForEach-Object{
$message += "Name: '{0}' - Last Write Time: '{1}'" -f $_.Name, $_.LastWriteTime
}
I'm trying to access a subfolder of "Inbox" named "subfolder" in outlook (2010) using Powershell.
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$ns = $outlook.GetNameSpace("MAPI");
$inbox = $ns.GetDefaultFolder($olFolderInbox)
# how do I specify a subfolder that's inside Inbox???
# I mean, "Inbox\subfolder" where "subfolder" is the name of the subfolder...
How do I specify this subfolder?
I'm sure this is really simple, which is why I am about to "lose it." Thanks in advance!
*Later in my code,
I search the body for a "searchterm" and send the results to a text file if there's a match. The following code works for my Inbox:
$inbox.items | foreach {
if($_.body -match "searchterm") {$_.body | out-file -encoding ASCII foo.txt} # prints to file...
Instead of the inbox, I want to look at the subfolder of inbox as described above...
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EDIT:
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$ns = $outlook.GetNameSpace("MAPI");
$inbox = $ns.GetDefaultFolder($olFolderInbox)
$targetfolder = $inbox.Folders | where-object { $_.name -eq "Subfolder" }
$targetfolder.items | foreach {
if($_.body -match "keyword") {$_.body | out-file -Append -encoding ASCII foo.txt} # keyword match prints body to file...
}
OK, I think this works now...
I don't know what I was doing wrong, although it's literally my first day using Powershell, so it's no surprise, really.
$targetfolder = $inbox.Folders | where-object { $_.name -eq "subfolder" }
$targetfolder.items | where-object { $_.body -match "keyword" } | % { $_.body } # can then redirect the body to file etc.
EDIT: not sure why your newest edit wouldn't work. Yours looks to be similar in construction to the one I have above, which I verified against my own mailbox.
EDIT EDIT: Be sure that if you're using out-file, you append the results rather than overwriting with each match.
Try using the Where-Object cmdlet to filter the Folders returned from $inbox.Folders.
$Subfolder = $inbox.Folders | Where-Object -FilterScript { (Split-Path -Path $_.FolderPath -Leaf) -eq 'Subfolder' }
Here is an alternative / short-hand version of the above. This won't be quite as reliable, since you could have another folder called MySubfolder that's distinct from Subfolder.
$Subfolder = $inbox.Folders | ? { $_.FolderPath.EndsWith('Subfolder') }