0

I have an array of MailItems from Outlook. I want to search each mail item and return the Subject and a Category based on a list of search terms contained in an array - in the example called $searchArray.

For example:

$mailbox = "[email protected]"

$outlook = New-Object -com Outlook.Application
$ns = $outlook.GetNamespace("MAPI")
$inbox = $ns.Folders.Item($mailbox).Folders.Item("Inbox")
$searchItems = $inbox.Folders.Item("MySubFolder").Folders.Item("MyNestedSubFolder").Items

$searchArray = (
    "Category1", ("searchTerm1","searchTerm2","searchTerm3"),
    "Category2", ("searchTerm4","searchTerm5"),
    "Category3", ("searchTerm6")
)

foreach ($msg in $searchItems) {
    $msg | select Subject, # <Category where email address contains one of the search terms>
}

I want to return the Subject, and then a column called Category which will look at the $msg.SenderEmailAddress and if any of the searchTerms in the $searchArray is contained within the address, return the category that had that search term in it.

For example if one of the SenderEmailAddress values was "[email protected]" then return Category1 as the Category.

3
  • Nitpick: use example.com for domain examples. Commented Apr 8, 2016 at 9:35
  • In your output: to ensure that all items return the correct data they have to return the same number of properties. So you either need to return all categories and highlight the one you want or have a custom field that shows the category matched. Can an email match more than one category? What happens when it does? Are you partial to the structure you have now for $searchArray? Some changes to it would make the process easier Commented Apr 8, 2016 at 10:45
  • @Matt I don't care about the structure of the search array. Just that I will have one or more search terms for each category. Consider the search terms to be unique for all categories. The output will be for each email address assign one category. Commented Apr 8, 2016 at 11:12

3 Answers 3

2

I would flip that array on its head and create a hashtable from it. Then use the first matching search term as a lookup key for the category:

$searchArray = (
    "Category1", ("searchTerm1","searchTerm2","searchTerm3"),
    "Category2", ("searchTerm4","searchTerm5"),
    "Category3", ("searchTerm6")
)

# Create hashtable
$searchTable = @{}

# Populate hash table with values from array
for($i=0;$i-lt$searchArray.Count;$i+=2){ 
    foreach($term in $searchArray[$i+1])
    {
        $searchTable[$term] = $searchArray[$i]
    }
}

# Select Category based on first matching search term
$msg |Select-Object Subject,@{Name="Category";Expression={
        $sender = $_.SenderEmailAddress
        $searchTable[$($searchTable.Keys |Where-Object{$sender -like "*$_*"} |Select -First 1)]
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Still need to use a calculated expression just as Mathias did (It's really the simple way). However I wanted to show an approach where you had a custom object array for the $searchArray. If you were to tailor it from scratch it would look like this. I also converted the terms into regex pattern matches since you say they are unique. Only caveat there is you need to be sure that there are no regex meta-characters in your search terms.

$searchArray = (
    [pscustomobject]@{
        Category = "1"
        Pattern = "searchTerm1|searchTerm2|searchTerm3"
    },  
    [pscustomobject]@{
        Category = "2"
        Pattern = "searchTerm4|searchTerm5"
    },
    [pscustomobject]@{
        Category = "3"
        Pattern = "searchTerm6"}
)

foreach ($msg in $searchItems) {
    $msg | select Subject, @{
        Name="Category";
        Expression={$searchArray | Where-Object{$msg.SenderEmailAddress -match $_.pattern } | Select-Object -ExpandProperty Category}
    } 
}

Solution is dependant on PowerShell 3.0 from the type accelerator [pscustomobject]. Could easily bring it back to 2.0 if need be.


To showcase similar structure using 2.0 and automatic conversion of you array to one that works with my code.

$newSearchArray = for($categoryIndex=0;$categoryIndex-lt$searchArray.Count;$categoryIndex+=2){ 
    New-Object -TypeName pscustomobject -Property @{
        Category = $searchArray[$categoryIndex]
        Pattern = ($searchArray[$categoryIndex+1] | ForEach-Object{[regex]::Escape($_)}) -join "|"
    }
}

Now the search terms are automatically escaped and joined into a search pattern.

Comments

0

Using a switch:

$mailbox = "[email protected]"

$outlook = New-Object -com Outlook.Application
$ns = $outlook.GetNamespace("MAPI")
$inbox = $ns.Folders.Item($mailbox).Folders.Item("Inbox")
$searchItems = $inbox.Folders.Item("MySubFolder").Folders.Item("MyNestedSubFolder").Items

foreach ($msg in $searchItems) {
    $object = $msg | select Subject,Category # <Category where email address contains one of the search terms>
    Switch -Regex ($msg.SenderEmailAddress)
    {
      'searchTerm1|searchTerm2|searchTerm3' { $object.Catetory = 'Category1' ; break }
      'searchTerm4|searchTerm5'             { $object.Catetory = 'Category2' ; break }
      'searchTerm6'                         { $object.Catetory = 'Category3' ; break }
    }
    $object
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.