Notification when outlook email arrives
-
Monday, June 18, 2012 8:14 AM
Hi,
I've written a small script that will hopefully run a taskbar alert notification when an email arrives in my inbox. So far all it does is searches through an inbox folder and calls the function if it finds the matching sender:
#Function to fire up system tray notifications
Function TaskTrayAlert email, subject, body {
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = "C:\Windows\System32\PerfCenterCpl.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = "Press a button"
$objNotifyIcon.BalloonTipTitle = "Outlook File Contents"
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(20000)
}#Code to search inbox
$info = New-Object -ComObject Outlook.Application
$objNamespace = $info.GetNamespace("MAPI")
$objFolder = $objNamespace.GetDefaultFolder(6).Folders.Item("Alerts")
$colItems = $objFolder.Items
foreach ($item in $colItems) {
If ($item.SenderEmailAddress -eq "Bill.Smith@newsgroup") {
("$($item.SenderEmailAddress) `t $($item.SentOn) `t $
($item.Subject)")
TaskTrayAlert
}
}The problem I am facing is that my code loops through the complete folder each time. What I really need is for it to find all 'New' items maybe using a real-time monitor or perhaps if it was runing a scheduled task.
I was also thinking maybe if the powershell script was called from an Outlook alert rule but if this is the case is there a way to parse the email for subject body etc add this to the alert information,
Any help
Thanks
All Replies
-
Monday, June 18, 2012 10:37 AM
Hi James,
I'm not very good in macros but I think better will be use Outlook rule "Run a script" with VBA macro.
Something useful articles:
http://msdn.microsoft.com/en-us/library/ee814736.aspx
http://support.microsoft.com/kb/306108Or ask on Technet Outlook forum.
-
Monday, June 18, 2012 8:48 PM
This may be more than you want, but with C# or VB you can make a plug-in that can subscribe to the new email event. You may be able to do this in PowerShell, but I haven't done the research yet. This would give you just the new email that arrived on that event.
Also look at the members of $ObjFolder for something like .Items.Restrict this method will let you filter the folder content. The sample I have in a shelved project is .Restrict("[Subject] > 'Test' AND [Subject] < 'Test~' and [complete] = False" (for a task). the > and < accomplish a contains type evaluation. If you can't get the Event to fire you could run this every X-mIn, and use either the range of time, or set a flag once processed, or modify the email body... move to another folder, there are a few options, I have used several myself.
'http://msdn.microsoft.com/en-us/library/cc668191.aspx - Getting Started and uninstall ' http://msdn.microsoft.com/en-us/library/bb386179.aspx - How to Deploy ' http://msdn.microsoft.com/en-us/library/bb623114(v=office.12).aspx - App Domain ' http://msdn.microsoft.com/en-us/library/bb296010.aspx - Create Custom Task Panes ' http://msdn.microsoft.com/en-us/library/bb157876.aspx - Office Add-in OverView ' http://msdn.microsoft.com/en-us/library/388t39t8.aspx
-
Tuesday, June 19, 2012 3:01 PM
You can subscribe to the application's NewMailEx event, this fires up every time a new item is received and returns the new item's EntryID. Next, setup the Action ScriptBlock for the event subscription; in it, place all the code you will need to check the new item against your filter (SenderEmailAddress). The Action ScriptBlock has its own execution context. You can dot-source or import a module from within the Action ScriptBlock or — as the demo code has — just include it.
In the Action ScriptBlock, the code…
- Retrieves the target folder
- Retrieves the new item through the
GetItemFromID method
- $Event.SourceArgs contains the item's ID
- $folder.StoreID contains the target folder's ID
- Checks the item's
SenderEmailAddress against your criteria
- Display the balloon tip If same address
$Action = {
$folder = $Sender.Session.GetDefaultFolder(6).Folders.Item("Alerts")
$item = $folder.Session.GetItemFromID($Event.SourceArgs, $folder.StoreID)
if ($item.SenderEmailAddress -eq 'Bill.Smith@newsgroup') {
$BalloonTipText = $item.SenderEmailAddress, $item.SentOn, $item.Subject -join "`t"
Write-Host $BalloonTipText -BackgroundColor Yellow -ForegroundColor DarkBlue
Add-Type -AssemblyName System.Windows.Forms
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = "C:\Windows\System32\PerfCenterCpl.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = $BalloonTipText
$objNotifyIcon.BalloonTipTitle = "Outlook File Contents"
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(20000)
}
}$null = Register-ObjectEvent $ol NewMailEx -SourceIdentifier MyNewEmailAlert -Action $Action
The balloon tip's text may not be what you want to display but, you get the idea. The balloon tip works better — close to expected — when PowerShell's runs in Single Thread Apartment (STA).
Note: I tested the code on Outlook 14 (2010) and should work on Outlook 12 (2007). NewEmailEx event behaves different in previous versions.
- Proposed As Answer by King Julien Wednesday, June 20, 2012 11:11 AM
-
Tuesday, June 19, 2012 3:47 PM
My old code showed that the returned sourceArgs can return a comma delimited list of EntryIDs.
Can you also do $Sender.Session.GetItemFromID($Event.SourceArgs) ?
My sample Called GetItemFromID and only passed the EntryID. Without need to also pass an argument about the StoreID.
You will get this event notification for all new messages even the one not in the "Alerts" folder.
So you should also check to ensure that $Item isn't $null.
Another thing I have done is set $item.ReminderSet = $true;$item.ReminderTime=Get-Date;$item.Save();
Depending on how you use reminders this may be an easier way to notify the user vs. rolling your own Toast.
Oh, and thanks zx38 for saving me some time, I had only attempted this from a Outlook Plugin the registering event is going to save me some work.
-
Tuesday, June 19, 2012 4:23 PM
Hi Josh,
First of all, you're welcome :)
Good point about ReminderSet.
You are correct, in Outlook 2003 the EntryIDCollection returns a comma delimited string. This behavior changed in Outlook 2007. That is the reason I placed a Note at the bottom of the code. Thanks fo verifying this, I have no way to test on previous versions.
Yes, you can only pass the EntryID String to GetItemFromID. I complemented the call with the folder's StoreID to focus only in the Alerts folder. Otherwise, it would search every container.
$item can only be Null, if a Rule moves the item to a different container or deletes it. We get the new item's EntryID because it has been received. I have read about a limitation the NewMailEx event had,it canonly process a limited number of items if they arrive at the sane time, but I believe that limitation is irrelevant, given that it only returns one EntryID through EntryIDCollection — yes it kept the collection in its name. Unfortunately, I cannot verify it, I do not have Exchange and my Inboxes are not that busy ;)
- Edited by zx38 Tuesday, June 19, 2012 4:31 PM
- Proposed As Answer by King Julien Wednesday, June 20, 2012 11:11 AM
-
Tuesday, June 19, 2012 4:31 PM
What will $item be if your new email is not in the "Alerts" folder. and your getItemFromID is searching a specific StoreID. Your first post referenced $ol was that to be the Application object? Or is there another place where you are filtering events only to those items where a rule has moved them to the Alerts Folder?
That brings up another question. Is the NewMailEx event going to fire after a rule has moved the email to "Alerts" or will it be the same event that would trigger the outlook rule to move it?
I didn't get past proof of concept when I was working on this type of thing before. I must have been going off some 2003 documentation mixed in with the newer, and an array of 1 behaves the same as a single item (When using .Split(",");)
I hadn't considered the performance implication of searching the entire OST Folder Structure. 2010 seems to have good indexing, I guess I should run some benchmarks, and actually wire up this PowerShell example and stop guessing and do some measuring.
-
Tuesday, June 19, 2012 8:50 PM
Yes, I stand corrected. When the new item is received in a delivery store other than the specified in the call to GetItemFromID, the method throws a nasty error that causes the event subscription to fail, this is very bad, thanks for asking about it Josh.
It is, then, a much safer and the way to approach the OP's objective, to only pass the EntryID to the GetItemFromID method. A quick check to the new item's parent StoreID before checking the target SenderEmailAddress, will ensure the alert to the user happens only when the new item is received in the target delivery store.
$ol is a reference to Outlook.Application
Here a revised version of the previous code, try it and let us know how it behaved. Thanks again go to Josh for keeping me honest ;)
$Action = {
$folder = $Sender.Session.GetDefaultFolder(6).Folders.Item("Alerts")
$item = $folder.Session.GetItemFromID($Event.SourceArgs)
if ($item.Parent.StoreID -eq $folder.StoreID -and $item.SenderEmailAddress -eq 'Bill.Smith@newsgroup') {
$BalloonTipText = $item.SenderEmailAddress, $item.SentOn, $item.Subject -join "`t"
Write-Host $BalloonTipText -BackgroundColor Yellow -ForegroundColor DarkBlue
Add-Type -AssemblyName System.Windows.Forms
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = "C:\Windows\System32\PerfCenterCpl.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = $BalloonTipText
$objNotifyIcon.BalloonTipTitle = "Outlook File Contents"
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(20000)
}
}$null = Register-ObjectEvent $ol NewMailEx -SourceIdentifier MyNewEmailAlert -Action $Action
- Proposed As Answer by King Julien Wednesday, June 20, 2012 11:11 AM
- Marked As Answer by Yan Li_Microsoft Contingent Staff, Moderator Friday, June 29, 2012 9:09 AM
-
Wednesday, October 24, 2012 3:12 PM
I'm a newbie to Powershell, so forgive me if this is obvious, but when I try to run the above I get the error 'Register-ObjectEvent : Cannot register for event. An event with name 'NewMailEx' does not exist.'. If I do $ol | Get-Member it doesn't show NewMailEx or any events at all. Where are my Outlook events?
C:\Scripts (219)> $ol = New-Object -ComObject Outlook.Application C:\Scripts (219)> $ol | Get-Member -MemberType Event C:\Scripts (219)> $null = Register-ObjectEvent $ol NewMailEx -SourceIdentifier MyNewEmailAlert -Action $Action Register-ObjectEvent : Cannot register for event. An event with name 'NewMailEx' does not exist.
-
Friday, October 26, 2012 3:00 PMDoes your Get-Member Show NewMailEx on the list? What version of outlook are you running off? I have used this under 2010. Not sure if I had under an earlier one or not.
-
Monday, November 05, 2012 9:44 AM
Hi, Can anyone tell me why this doesn't seem to work?
$ol = New-Object -ComObject Outlook.Application
$Action = {
$folder = $ol.Session.GetDefaultFolder(6).Folders.Item("Inbox")
$item = $folder.Session.GetItemFromID($Event.SourceArgs)
if ($item.Parent.StoreID -eq $folder.StoreID -and $item.SenderEmailAddress -eq 'bennettj@rsc.org') {
#$BalloonTipText = $item.SenderEmailAddress, $item.SentOn, $item.Subject -join "`t"
$BalloonTipText = "james Bennett"
Write-Host $BalloonTipText -BackgroundColor Yellow -ForegroundColor DarkBlue
Add-Type -AssemblyName System.Windows.Forms
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = "C:\Windows\System32\PerfCenterCpl.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = $BalloonTipText
$objNotifyIcon.BalloonTipTitle = "Email Alert"
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(20000)
}
}
$null = Register-ObjectEvent $ol NewMailEx -SourceIdentifier MyNewEmailAlert -Action $ActionAlter De Ruine
-
Monday, November 05, 2012 2:01 PM
-
Tuesday, November 06, 2012 7:42 AM
Hi Josh,
It doesnt seem to fire when an email arrives. My code seems to point to the inbox but its def not working
james
Alter De Ruine
-
Tuesday, November 06, 2012 2:06 PM
I am having some luck, but I am getting my PC confused with all these registered events.
The issue is something with the if ($item.Parent.StoreID -eq $folder.StoreID -and $item.SenderEmailAddress -eq 'eod@trintech.com') Statement.
Write-Host is not going to work inside the Action and neither are any breakpoints, because PS is registering the event and taking its hands off of it.
What I was able to do was move the $objNotifyIcon out of the IF and send variables to the BalloonTipText for debugging.
$objNotifyIcon.BalloonTipText = ($sender,$Event)
Maybe this will help pin down the issue, I think you may want to reference $sender instead of $ol.
Let me know if that helps.
- Edited by Josh Miller 76 Tuesday, November 06, 2012 3:11 PM Typos

