Powershell - Read and Move mails to archive folder - email

Problem:
Outlook:Cannot move read e-mail to Archive folder.
Tried several options I found on the web but all to no avail... Anyone? :D
I already removed the .move property as it was not working, so please don't fuss about that.
Any help will be much appreciated!
Code:
start Outlook
Function Get-OutlookInBox
{
Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
$folder.items |
Select -Property Subject, ReceivedTime, Importance, SenderName, body
} #end function Get-OutlookInbox
###################################################################################
cls
try {
$switches = get-outlookinbox | where subject -eq "Ip was blocked"
$e = $switches.body
$e = $e -replace 'Blocked IP:| for agent| |:\d{1,2}'
}
catch {
$switches = "Fail"
}
$f = $e |select -Unique |sort
ni $File -type file
$f | ac $File
(gc $File) | ? {$_.trim() -ne "" } | sc $File
$IPCount = (gc $File)
$IPCount = $IPCount.count
$index=0;
#Mark mails as read and delete.
function display( [string]$subject, [string]$color , [string]$out) {
# REQUIRED LENGTH OF STRING
$len = 20
# STRINGS THAT ARE LONGER WILL BE CUT DOWN,
# STRINGS THAT ARE TO SHORT WILL BE MADE LONGER
if ( $subject.length -lt 20 ){
$toadd=20-$subject.length;
for ( $i=0; $i -lt $toadd; $i++ ){
$subject=$subject+" ";
}
$len = $subject.length
}
else { $len = 20 }
$index=$index+1
Write -ForegroundColor $color -nonewline " |" ((($subject).ToString()).Substring(0,$len)).ToUpper()
}
$outlook = new-object -comobject outlook.application
#Define folders
$namespace = $outlook.GetNameSpace("MAPI")
$pst = $namespace.Stores
$pstRoot = $pst.GetRootFolder()
$pstFolders = $pstRoot.Folders
$Archive = $namespace.Folders | ?{$_.name -match "Archive"}
$DefaultFolder = $namespace.GetDefaultFolder(6)
$InboxFolders = $DefaultFolder.Folders
$DeletedItems = $namespace.GetDefaultFolder(3)
$Emails = $DefaultFolder.Items
#For($i=($emails.count-1);$i -ge 0;$i--){
# $($emails)[$i].Unread = $false
# $($emails)[$i].delete()
#}
For($i=($emails.count-1);$i -ge 0;$i--){
$($emails)[$i].Unread = $false
$($emails)[$i].move($Archive.Folders.Item("Inbox<Archive>"))
}

That's a different way to get the folders than I'm used to using. This should do it for you though:
$Archive = $namespace.Folders | ?{$_.name -match "Archive"}
And then in your For loop if you want to move it to your Inbox in the Archives you can do this:
For($i=($emails.count-1);$i -ge 0;$i--){
$($emails)[$i].Unread = $false
$($emails)[$i].move($Archive.Folders.Item("Inbox"))
}
If you want a subfolder you add more .Folders.Item("<Subfolder Name>) on after ("Inbox")

Related

Looping through folders in outlook Mailbox in archive and get all the items in powershell

I'm very new to powershell and I'm attempting to get recursively all items in archive and the subfolders items with the path in a specified mailbox.
I would really appreciate your help.
as I said before, I am new to powershell and scripting in general so my code isn't viable through the time.
Here is my code :
'''
Clear-Host
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -comobject Outlook.Application
$namespace = $Outlook.GetNameSpace("MAPI")
Write-Host "Démarrage du script . . . ."
$Year = Get-Date -Format ("yyyy")
$YearMonth = Get-Date -Format ("yyyyMM")
$Mailbox = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth)
$Subfolder1 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(1)
$Subfolder2 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(2)
$Subfolder3 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(3)
$Subfolder4 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(4)
$Subfolder4sub1 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(4).folders.item(1)
$Subfolder4sub2 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(4).folders.item(2)
$Subfolder4sub3 = $NameSpace.Folders.Item('spam#exemple.fr').Folders.Item('Archive').Folders.Item($Year).Folders.Item($YearMonth).folders.item(4).folders.item(3)
Write-Host "Traitement des mails . . . ."
$CSVfolder = "C:\TEMP\datas_spamV3.csv"
Clear-Content "C:\TEMP\datas_spamV3.csv"
$headers = "Id;Emplacement;Date;Emetteur;Sujet" | Add-Content -Path $CSVfolder
$Mailbox.Items | foreach {
$Id = New-Guid
$path = $Mailbox.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
$Subfolder1.Items | foreach {
$Id = New-Guid
$path = $Subfolder1.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
$Subfolder2.Items | foreach {
$Id = New-Guid
$path = $Subfolder2.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
$Subfolder3.Items | foreach {
$Id = New-Guid
$path = $Subfolder3.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
$Subfolder4sub1.Items | foreach {
$Id
$path = $Subfolder4sub1.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
$Subfolder4sub2.Items | foreach {
$Id = New-Guid
$path = $Subfolder4sub2.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
$Subfolder4sub2.Items | foreach {
$Id = New-Guid
$path = $Subfolder4sub3.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderEmailAddress);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path $CSVfolder
}
'''
EDIT : I found the solution by myself :
'''
clear-host
$outlook = New-Object -Com Outlook.Application
$mapi = $outlook.GetNamespace('MAPI')
$mailboxRoot =
$NameSpace.Folders.Item('spam#mail.fr').Folders.Item('Archive')
$yearmonth = Get-Date -Format ("yyyyMM")
Clear-Content "C:\TEMP\Out_SPAM.csv"
$headers = "Id;Emplacement;Date;Emetteur;Sujet" | Add-Content -Path
"C:\TEMP\Out_SPAM.csv"
$walkFolderScriptBlockBis = {
param(
$currentFolder
)
foreach ($item in $currentFolder.Folders) {
$item.Items() | Foreach {
$Id = $_.ConversationId
$path = $item.FullFolderPath
$datas = "$($_.ReceivedTime);$($_.SenderName);$($_.Subject)"
"$Id;$path;$datas" | Add-Content -Path "C:\TEMP\Out_SPAM.csv"
}
& $walkFolderScriptBlockBis $item
}
}
$walkFolderScriptBlock = {
param(
$currentFolder,$index
)
foreach ($item in $currentFolder.Folders) {
if($index -lt 3){
#$item.FolderPath
$yearmonth = Get-Date -Format ("yyyyMM")
if ($item.FolderPath.Contains($yearmonth)) {
& $walkFolderScriptBlockBis $item
}
$temp = $index + 1
& $walkFolderScriptBlock $item $temp
}
}
}
$index = 0
& $walkFolderScriptBlock $mailboxRoot $index
'''

How to fix corrupted files when download from outlook using powershell

i have a powershell script that automatically download from outlook and save in the file i already set. the script works fine but then i realise that some of the attachment downloaded is corrupted. here is the script that i use.
Function saveattachmentexcel
{
$Null = Add-type -Assembly "Microsoft.Office.Interop.Outlook"
#olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
#olFolderInbox = 6
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$folder = $nameSpace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)
$filepath = "D:\DMR Folder\"
$folder.Items | Where {$_.UnRead -eq $True -and $($_.attachments).filename -match '.xlsm'} | ForEach-object {
$filename = $($_.attachments | where filename -match '.xlsm').filename
foreach($file in $filename)
{
$outpath = join-path $filepath $file
$($_.attachments).saveasfile($outpath)
}
$_.UnRead = $False
}
}
saveattachmentexcel
i do not know why this is happening. could anyone please help me?
This is likely because you attempt to save every single attachment to the same file name on disk with the $($_.attachments).saveasfile($outpath) statement.
Change this:
$filename = $($_.attachments | where filename -match '.xlsm').filename
foreach($file in $filename)
{
$outpath = join-path $filepath $file
$($_.attachments).saveasfile($outpath)
}
to:
foreach($attachment in $_.attachments)
{
if($attachment.Filename -like '*.xlsm'){
$outpath = Join-Path $filepath $attachment.Filename
# Only save this particular attachment to disk - not all of them
$attachment.SaveAsFile($outpath)
}
}

How to read .xls file and create .xml based on the value entered in the .xls?

I want to read value from .xls and write it as .xml based on the input provided in the .xls.
Get-ChildItem 'C:yourfile*.xml' -Recurse | ForEach {
(Get-Content $_ | ForEach { $_ -replace '[MYID]', 'MyValue' }) |
Set-Content $_
}
$sheetNumber = 1
$startRow = 2
$endRow = 3
$searchResouceId = 3
$searchResourceName = 1
$xls = "C:\Codes\book1.xlsx"
$find = '<title></title>'
$excel = New-Object -Com Excel.Application
$wb = $excel.Workbooks.Open($xls)
$sh = $wb.Sheets.Item($sheetNumber)
$row = $startRow;
for ($j = 1; $j -le $endRow; $j++) {
$resourceId = $sh.Cells.Item($row, $searchResouceId).Value2
$resourceName = $sh.Cells.Item($row, $searchResourceName).Value2
Write-Output "Creating : $resourceId"
Copy-Item "sample.html" -Destination "C:\Codes\$resourceName.html"
$file = "C:\Codes\$resourceName.html"
$row = $row + 1
$replace = "<title>$resourceId/title>"
(Get-Content $file).replace($find, $replace) | Set-Content $file
}
$excel.Workbooks.Close()

Getting No Output from my Powershell Functions

Sorry if you have seen this code but I did make some tweaks after I accepted the answer and got some interesting results and wasn't able to reopen previous thread for continuance.
My powershell seems to be running but the function calls are producing no result after $filestore in function execute. What is going on? Are my functions not reading the inputs due to lack of global variables?
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
function Import-Excel
{
param (
[string]$FileName,
[string]$WorksheetName,
[bool]$DisplayProgress = $true
)
if ($FileName -eq "") {
throw "Please provide path to the Excel file"
Exit
}
if (-not (Test-Path $FileName)) {
throw "Path '$FileName' does not exist."
exit
}
$FileName = Resolve-Path $FileName
$excel = New-Object -com "Excel.Application"
$excel.Visible = $false
$workbook = $excel.workbooks.open($FileName)
if (-not $WorksheetName) {
Write-Warning "Defaulting to the first worksheet in workbook."
$sheet = $workbook.ActiveSheet
} else {
$sheet = $workbook.Sheets.Item($WorksheetName)
}
if (-not $sheet)
{
throw "Unable to open worksheet $WorksheetName"
exit
}
$sheetName = $sheet.Name
$columns = $sheet.UsedRange.Columns.Count
$lines = $sheet.UsedRange.Rows.Count
Write-Warning "Worksheet $sheetName contains $columns columns and $lines lines of data"
$fields = #()
for ($column = 1; $column -le $columns; $column ++) {
$fieldName = $sheet.Cells.Item.Invoke(1, $column).Value2
if ($fieldName -eq $null) {
$fieldName = "Column" + $column.ToString()
}
$fields += $fieldName
}
$line = 2
for ($line = 2; $line -le $lines; $line ++) {
$values = New-Object object[] $columns
for ($column = 1; $column -le $columns; $column++) {
$values[$column - 1] = $sheet.Cells.Item.Invoke($line, $column).Value2
}
$row = New-Object psobject
$fields | foreach-object -begin {$i = 0} -process {
$row | Add-Member -MemberType noteproperty -Name $fields[$i] -Value $values[$i]; $i++
}
$row
$percents = [math]::round((($line/$lines) * 100), 0)
if ($DisplayProgress) {
Write-Progress -Activity:"Importing from Excel file $FileName" -Status:"Imported $line of total $lines lines ($percents%)" -PercentComplete:$percents
}
}
$workbook.Close()
$excel.Quit()
}
function FindFiles {
param(
[string]$filestore
)
$length = $filestore.Length
$GuidArray = #()
for($line=0;$line -le $filestore.Count;$line++){
$check = $filestore[$line]
echo $check
$length2 = $check.Length
$fileGuid = $check | ForEach-Object{$_.FileGuid}
$GuidArray = $GuidArray + $fileGuid
}
write-host "-------------------------------------------------------------" -ForegroundColor Yellow
$filepath = Read-Host " Please Enter File Path to Search"
for ($counter=0;$counter -lt $GuidArray.Count;$counter++){
$fileArray = #()
$guidcheck = $GuidArray[$counter]
$file = Get-ChildItem -Recurse -Force $filePath -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -like "*$guidcheck*") } | Select-Object Directory,Name| Format-Table -AutoSize
$fileArray += $file
}
Write-Output $fileArray
}
function CopyFiles {
param(
[string]$fileArray
)
for ($counter = 0;$counter -lt $fileArrray.Count;$counter++){
echo $fileArray[$counter]
#Copy-Item
}
}
function execute {
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
echo $filestore
$fileArray = #(FindFiles($fileArray))
echo "test"
echo $fileArray
#CopyFiles($fileArray)
}
At the end of FindFiles add this line:
Write-Output $GuidArray
This returns that variable to the standard output stream (the pipeline).
Similarily at the end of FindFiles2 you need to do:
Write-Output $fileArray

How to Return Value to use in another function powershell

In the below code I am having trouble understanding why when I return FileArray why my other function is returning it as being empty?
I am looking to use copyfiles with FileArray. Am I just supposed to put all the steps into one huge function?
function Import-Excel
{
param (
[string]$FileName,
[string]$WorksheetName,
[bool]$DisplayProgress = $true
)
if ($FileName -eq "") {
throw "Please provide path to the Excel file"
Exit
}
if (-not (Test-Path $FileName)) {
throw "Path '$FileName' does not exist."
exit
}
$FileName = Resolve-Path $FileName
$excel = New-Object -com "Excel.Application"
$excel.Visible = $false
$workbook = $excel.workbooks.open($FileName)
if (-not $WorksheetName) {
Write-Warning "Defaulting to the first worksheet in workbook."
$sheet = $workbook.ActiveSheet
} else {
$sheet = $workbook.Sheets.Item($WorksheetName)
}
if (-not $sheet)
{
throw "Unable to open worksheet $WorksheetName"
exit
}
$sheetName = $sheet.Name
$columns = $sheet.UsedRange.Columns.Count
$lines = $sheet.UsedRange.Rows.Count
Write-Warning "Worksheet $sheetName contains $columns columns and $lines lines of data"
$fields = #()
for ($column = 1; $column -le $columns; $column ++) {
$fieldName = $sheet.Cells.Item.Invoke(1, $column).Value2
if ($fieldName -eq $null) {
$fieldName = "Column" + $column.ToString()
}
$fields += $fieldName
}
$line = 2
for ($line = 2; $line -le $lines; $line ++) {
$values = New-Object object[] $columns
for ($column = 1; $column -le $columns; $column++) {
$values[$column - 1] = $sheet.Cells.Item.Invoke($line, $column).Value2
}
$row = New-Object psobject
$fields | foreach-object -begin {$i = 0} -process {
$row | Add-Member -MemberType noteproperty -Name $fields[$i] -Value $values[$i]; $i++
}
$row
$percents = [math]::round((($line/$lines) * 100), 0)
if ($DisplayProgress) {
Write-Progress -Activity:"Importing from Excel file $FileName" -Status:"Imported $line of total $lines lines ($percents%)" -PercentComplete:$percents
}
}
$workbook.Close()
$excel.Quit()
}
function FindFiles {
param(
[string]$fiestore
)
$length = $filestore.Length
$GuidArray = #()
for($line=0;$line -le $filestore.Count;$line++){
$check = $filestore[$line]
$length2 = $check.Length
echo $check
$fileGuid = $check | ForEach-Object{$_.FileGuid}
$GuidArray = $GuidArray + $fileGuid
}
write-host "-------------------------------------------------------------" -ForegroundColor Yellow
$filepath = Read-Host " Please Enter File Path to Search"
for ($counter=0;$counter -lt $GuidArray.Count;$counter++){
$fileArray = #()
$guidcheck = $GuidArray[$counter]
echo $guidcheck
$file = Get-ChildItem -Recurse -Force $filePath -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -like "*$guidcheck*") } | Select-Object Directory,Name| Format-Table -AutoSize
$fileArray += $file
}
echo $fileArray
return $fileArray
}
function CopyFiles {
param(
[string]$filearray
)
echo $fileArray
for($counter = 0;$counter -lt $filearrray.Count;$counter++){
echo $filearray[$counter]
#Copy-Item
}
}
function execute {
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
$fileArray = #()
FindFiles($filestore)
echo $fileArray
CopyFiles($fileArray)
}
$fileArray doesn't become available outside of the Function by doing Return, but you could make it accessible outside of the function by defining it with a Global scope (although this is not best practice): Return $Global:fileArray.
Instead, it becomes the value of the Function call itself, so in Execute you could do:
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
$fileArray = #(FindFiles($filestore))
echo $fileArray
CopyFiles($fileArray)
However I think you also need to remove any echo statements from within the FindFiles function or they may be returned as well.
Note: This is untested code.