Extract the name of the folder housing an email

155 Views Asked by At

I am trying to extract email metadata from messages in an Outlook Exchange account. I derive various metadata as described here, but I can't get the name of the folder where the email has been stored.

What I have so far:

Clear-Host
$outlook = New-Object -Com Outlook.Application
$mapi = $outlook.GetNamespace('MAPI')
$mailboxRoot = $mapi.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$walkFolderScriptBlock = {
    param(
        $currentFolder
    )
    foreach ($item in $currentFolder.Folders) {
                $item.Items
                }
            }

$Email = & $walkFolderScriptBlock $mailboxRoot
$Results = $Email | Select ConversationTopic, ReceivedTime;
$Results | Export-Csv -Path C:\Temp\2024-01-25EmailTesting.csv

I tried variants of the word "folder" following the word "Select". It returns an empty column.

Update - @mhu has made a breakthrough and gotten the names of folders. When I run their script, I see folders like "Delete" and "Inbox". Which is a major step forward, but am wondering if I could also get the subfolders under "Inbox" (i.e. "Accessibility Committee" and "Advisory").

enter image description here

enter image description here

3

There are 3 best solutions below

8
mhu On BEST ANSWER

You can select the parent name property like this:

(and you don't need the script block, unless you want to recursively process the folders)

$results     = @()
$outlook     = New-Object -Com "Outlook.Application"
$mapi        = $outlook.GetNamespace("MAPI")
$mailboxRoot = $mapi.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$folders     = $mailboxRoot.Folders | Select-Object -ExpandProperty "Items"
foreach ($folder in $folders)
{
    $results += $folder | 
        Where-Object { $_.Class -eq 43 } | 
        Select-Object -Property "ConversationTopic", "ReceivedTime", @{ "Label" = "Folder"; "Expression" = { $_.Parent.Name } }
}
$results | Export-Csv -Path "C:\Temp\email.csv"

Example output:

ConversationTopic                                    ReceivedTime        Folder
-----------------                                    ------------        ------
This week at Humble: Mega Man franchise pack & more! 10/02/2024 16:16:58 Test

Advanced example for processing nested folders:

Set-StrictMode -Version "Latest"
$ErrorActionPreference = "Stop"

function Get-MailFromOutlookFolder
{
    [CmdletBinding()]
    param 
    (
        [Parameter(Mandatory = $true)]
        [Object] $ParentFolder
    )

    $items = @()

    foreach ($folder in $ParentFolder.Folders)
    {
        foreach ($item in ($folder | Select-Object -ExpandProperty "Items"))
        { 
            if ($item.Class -eq 43)
            {
                # process email
                $items += $item | Select-Object -Property "ConversationTopic", "ReceivedTime", @{ "Label" = "Folder"; "Expression" = { $_.Parent.Name } }
            }
        }

        # process (sub)folder items
        $items += Get-MailFromOutlookFolder -ParentFolder $folder
    }

    return $items    
}

$outlook     = New-Object -Com "Outlook.Application"
$mapi        = $outlook.GetNamespace("MAPI")
$mapi.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent

$results = Get-MailFromOutlookFolder -ParentFolder $mailboxRoot
$results | Export-Csv -Path "C:\Temp\email.csv"
5
Dmitry Streblechenko On

Use MailItem.Parent.Name. But since you are processing items from a particular folder, you already know what the parent folder is - just use $item.Name

3
Eugene Astafiev On

Each item in Outlook has the Parent property which stands for the folder where the items is located. I am not sure whether the property call will work correctly in PS, but let's try the following:

Clear-Host
$outlook = New-Object -Com Outlook.Application
$mapi = $outlook.GetNamespace('MAPI')
$mailboxRoot = $mapi.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$walkFolderScriptBlock = {
    param(
        $currentFolder
    )
    foreach ($item in $currentFolder.Folders) {
                $item.Items
                }
            }

$Email = & $walkFolderScriptBlock $mailboxRoot
$Results = $Email | Select ConversationTopic, ReceivedTime, Parent.Name;
$Results | Export-Csv -Path C:\Temp\2024-01-25EmailTesting.csv

Also you may check the parent folder name in the loop, but I don't see how it can help in the loop:

Clear-Host
$outlook = New-Object -Com Outlook.Application
$mapi = $outlook.GetNamespace('MAPI')
$mailboxRoot = $mapi.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$walkFolderScriptBlock = {
    param(
        $currentFolder
    )
    foreach ($item in $currentFolder.Folders) {
                Write-Host $item.Name
                $item.Items
                }
            }

$Email = & $walkFolderScriptBlock $mailboxRoot
$Results = $Email | Select ConversationTopic, ReceivedTime;
$Results | Export-Csv -Path C:\Temp\2024-01-25EmailTesting.csv