I have a question on Powershell. What I'm trying to do is looping through the inbox of a shared (group) mailbox, if the e-mail comes from a set of 2 sender names then save the CSV Attachments to a specific folder and then move the e-mail to another sub-folder of inbox. I managed this morning to make it work for the loop-save attachment part on one sender's name, but then somehow broke the code (on the first foreach loop). Plus, I am not able to run the "move e-mail" part.
Here's the code I got:
#define outlook object and ask to pick folder
$outlook = New-Object -comobject outlook.application
$mapi = $outlook.GetNamespace("MAPI")
$fldr = $mapi.PickFolder()
$DestFolder = "\\MAIBOXNAME\Inbox\01.Reports"
#use i as counter to define filenumber to save PendingOrders
$i = 1
$fldr.Items| foreach {$fldr.Items.Sender.Name -like "Name1" - or $fldr.Items.Sender.Name -like "Name2"
$year = $fldr.Items.ReceivedTime.ToString("yyyy")
$month = $fldr.Items.ReceivedTime.ToString("MM")
$fdate = $fldr.Items.ReceivedTime.ToString("yyyy.MM.dd")
$fpath = "Path\02.Daily Files\" $year '\' $year '.' $month '\' $fdate
#loop through attachments to find CSV extension - if found, save file to target path with the counter in the name and update the counter
$fldr.Items.Attachments|foreach {
$_.Filename
If ($_.filename.Contains("CSV")) {
$fname = $_.filename
$_.saveasfile((Join-Path $fpath "00$i $fname"))
$i = $i 1
}
$_.Move($DestFolder)
}
}
Could you please assist me in finalising this?
Thanks a lot!!
CodePudding user response:
Never loop through all items in a folder - it is like having a SELECT clause in SQL without a WHERE clause. Use Items.Restrict
or Items.Find
/FindNext
with a query @SQL=("http://schemas.microsoft.com/mapi/proptag/0x0C1A001F" LIKE '%Name1%') OR ("http://schemas.microsoft.com/mapi/proptag/0x0C1A001F" LIKE '%Name1%')
(the DASL name is for the PR_SENDER_NAME
MAPI property.
Secondly, I am not a PS expert, but your syntax is off - $fldr.Items.ReceivedTime
is invalid: ReceivedTime
is a property on the MailItem
object (returned from the Items collection), not on the Items
collection itself.
CodePudding user response:
This works as expected. it's not sexy, but it works :)
#define outlook object and ask to pick folder
$outlook = New-Object -comobject outlook.application
$mapi = $outlook.GetNamespace("MAPI")
$fldr = $mapi.Stores['xxxxxxxxxx'].GetRootFolder().Folders("Inbox")
$DestFolder = $mapi.Stores['xxxxxxxxxx'].GetRootFolder().Folders("Inbox").Folders("01.Reports")
$delFile = 1
$fldr.Items|
Where-Object{$_.SenderName -eq "Name1" -or $_.SenderName -eq "Name2"} |
ForEach-Object{
$year = $_.ReceivedTime.ToString("yyyy")
$month = $_.ReceivedTime.ToString("MM")
$fdate = $_.ReceivedTime.ToString("yyyy.MM.dd")
#Find newest csv file in folder and use it as counter, if empty start from 1
$fpath = "SomePath\" $year '\' $year '.' $month '\' $fdate
#create temporary csv file to start archiving xls file from 1
New-Item -Path (Join-Path $fpath "00.csv") -ItemType File
if ($delFile -ne 1) {
Remove-Item (Join-Path $fpath "00.csv")
}
$delFile = $delFile 1
$filter="*CSV"
$lastCsv= Get-ChildItem -Path $fpath -Filter $filter | Sort-Object LastAccessTime -Descending | Select-Object -First 1
if ($lastCsv) {
$i = [int]$lastCsv.name.substring(0,3) 1
}
else {
$i = [int]1
}
#loop through attachments to find CSV extension - if found, save file to target path with the counter in the name and update the counter
$_.Attachments|foreach {
$_.FileName
If ($_.FileName.Contains("CSV")) {
$fname = $_.FileName
$i = '{0:d3}' -f $i
$_.SaveAsFile((Join-Path $fpath "$i $fname"))
$i = [int]$i 1
}
}
$_.Move($DestFolder)
}