<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>The Windows Mobile RSS (Reed and Steve Stuff) Feed : Mail</title><link>http://blogs.msdn.com/hegenderfer/archive/tags/Mail/default.aspx</link><description>Tags: Mail</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Intercepting Mail using IMapiAdviseSink</title><link>http://blogs.msdn.com/hegenderfer/archive/2009/04/28/intercepting-mail-using-imapiadvisesink.aspx</link><pubDate>Wed, 29 Apr 2009 01:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9574523</guid><dc:creator>ReedR</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/hegenderfer/comments/9574523.aspx</comments><wfw:commentRss>http://blogs.msdn.com/hegenderfer/commentrss.aspx?PostID=9574523</wfw:commentRss><description>&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/hegenderfer/WindowsLiveWriter/InterceptingMailusingIMapiAdviseSink_108FC/mailman_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/hegenderfer/WindowsLiveWriter/InterceptingMailusingIMapiAdviseSink_108FC/mailman_2.jpg"&gt;&lt;IMG title=mailman style="BORDER-TOP-WIDTH: 0px; DISPLAY: inline; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=146 alt=mailman src="http://blogs.msdn.com/blogfiles/hegenderfer/WindowsLiveWriter/InterceptingMailusingIMapiAdviseSink_108FC/mailman_thumb.jpg" width=181 border=0 mce_src="http://blogs.msdn.com/blogfiles/hegenderfer/WindowsLiveWriter/InterceptingMailusingIMapiAdviseSink_108FC/mailman_thumb.jpg"&gt;&lt;/A&gt; There is a lot of interesting stuff going on with Windows Mobile right now…unfortunately, I can’t talk about much of it (yet).&amp;nbsp; Hang in there…eventually the “hush” orders will be lifted and the posts will start.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I owe you guys some cool stuff NOW though and you &lt;EM&gt;have been really patient&lt;/EM&gt; waiting for some dev posts.&amp;nbsp; Go ahead, say it.. “You OWE US”.&amp;nbsp;&amp;nbsp; I know…I do.&amp;nbsp; I have been in the dark cave at Microsoft we call “figure out what you can realistically do in a day and double that.”&amp;nbsp; I’m out for air and I’m digging back in to my bag of tricks for some stuff we can talk about NOW. Let’s see…&lt;/P&gt;
&lt;P&gt;Here’s one that comes up from time to time with no sample I am aware of…how to programmatically intercept mail.&amp;nbsp; Intercepting SMS message is pretty easy.&amp;nbsp; We’ve had support for this back in the via SDK &lt;A title="Mapi Rule" href="http://msdn.microsoft.com/en-us/library/bb158685.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb158685.aspx"&gt;MapiRule Sample&lt;/A&gt; and then added support in NETCF to simple &lt;A href="http://msdn.microsoft.com/en-us/library/bb932385.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb932385.aspx"&gt;add an event handler&lt;/A&gt;.&amp;nbsp; Wow, that was easy.&lt;/P&gt;
&lt;P&gt;So the next question becomes, how do I intercept email messages programmatically to do something cool?&amp;nbsp; What if I want to play a special ringtone or kick off some automated process for workflow.&amp;nbsp; It should be really easy, like SMS right?&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The NETCF guys never added a no-brainer message handler for email like they did for SMS, so you actually have to do a little work…in native code.&amp;nbsp; If you are on NETCF 3.5 and using Exchange, you could build something around WCF like David did with the &lt;A href="http://blogs.msdn.com/davidklinems/archive/2007/09/07/the-journey-of-the-lunch-launcher-part-1-the-origins-of-the-lunch-launcher.aspx" mce_href="http://blogs.msdn.com/davidklinems/archive/2007/09/07/the-journey-of-the-lunch-launcher-part-1-the-origins-of-the-lunch-launcher.aspx"&gt;Lunch Launcher.&lt;/A&gt;&amp;nbsp; If you are targeting the consumer market though, not everyone is using Exchange and you would really need an approach that had zero dependencies on the back-end.&amp;nbsp; MAPI provides this and to get it done, you just need to plug into &lt;A href="http://msdn.microsoft.com/en-us/library/ms859710.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms859710.aspx"&gt;IMapiAdviseSink&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I’m always a little stand-offish at SDK docs that refer me to some COM object that I’m supposed to wire up with no example…so let’s hack it out.&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;First we build a simple COM object that inherits from &lt;FONT size=2&gt;IMAPIAdviseSink and then implements OnNotify.&amp;nbsp; When OnNotify fires, we simply look for the fnevObjectCreated event to let us know that a new message has just been added and pull out the goodies.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The COM object part is standard stuff, so here’s what OnNotify might look like:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;STDMETHODIMP_(ULONG) CAdviseSink::OnNotify (ULONG cNotify, LPNOTIFICATION lpNotifications) &lt;BR&gt;{ &lt;BR&gt;HRESULT&amp;nbsp;&amp;nbsp; hRes = S_OK; &lt;BR&gt;&amp;nbsp; &lt;BR&gt;if (!m_hWndParent) return 0; &lt;BR&gt;&amp;nbsp; &lt;BR&gt;// Advise events fire on a number of different events, so be sure you look for the MAPI_MESSAGE+object creation event &lt;BR&gt;// and take some action when one arrives. &lt;BR&gt;try &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp; for (ULONG i=0 ; i&amp;lt;cNotify ; i++) &lt;BR&gt;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp; hRes = S_OK; &lt;BR&gt;&amp;nbsp;&amp;nbsp; if (fnevObjectCreated == lpNotifications[i].ulEventType) &lt;BR&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( lpNotifications[i].info.obj.ulObjType == MAPI_MESSAGE ) // Found a message, so grab it &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // New message has arrived, so take some action... &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // The event can fire before the message is ready to read, so I inject a slight delay here to give the system &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // a second or two to process the new message before I try to read it.&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sleep(1500); &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Process the new message &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetMsg(&amp;amp;lpNotifications[i]); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp; } &lt;BR&gt;} &lt;BR&gt;catch(...) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp; MessageBox(NULL,L"AdviseFail", L"AdviseFail", MB_OK ); &lt;BR&gt;} &lt;BR&gt;return 0; &lt;BR&gt;} &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;What you do with the message is up to you.&amp;nbsp; I created a very simple GetMsg routine to throw a MessageBox with the message subject as the title.&lt;/P&gt;
&lt;P&gt;void GetMsg(NOTIFICATION *pNote) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; HRESULT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr; &lt;BR&gt;&amp;nbsp;&amp;nbsp; IMessage&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *&amp;nbsp;&amp;nbsp; pmsg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; =&amp;nbsp;&amp;nbsp; NULL; &lt;BR&gt;&amp;nbsp;&amp;nbsp; ULONG lType=0,val=0; &lt;BR&gt;&amp;nbsp;&amp;nbsp; ULONG&amp;nbsp; subjectprop[]&amp;nbsp;&amp;nbsp;&amp;nbsp; =&amp;nbsp;&amp;nbsp; { 1, PR_SUBJECT }; &lt;BR&gt;&amp;nbsp;&amp;nbsp; LPSPropValue subjectpropval;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; // Get the message stores table &lt;BR&gt;&amp;nbsp;&amp;nbsp; hr = g_pSession-&amp;gt;OpenEntry(pNote-&amp;gt;info.obj.cbEntryID, pNote-&amp;gt;info.obj.lpEntryID,0,0,&amp;amp;lType,(IUnknown **)&amp;amp;pmsg); &lt;BR&gt;&amp;nbsp;&amp;nbsp; ASSERT(pmsg);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; // Double Check the props on the message for finer control of which types of messages/folders you want to handle &lt;BR&gt;&amp;nbsp;&amp;nbsp; // this example traps every new message... &lt;BR&gt;&amp;nbsp;&amp;nbsp; hr = pmsg-&amp;gt;GetProps((LPSPropTagArray)subjectprop,MAPI_UNICODE,&amp;amp;val,&amp;amp;subjectpropval); &lt;BR&gt;&amp;nbsp;&amp;nbsp; if ( hr == S_OK ) &lt;BR&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;// *** DO SOMETHING HERE *** &lt;BR&gt;// example: popup a message box with subject info, play some cool ringtone based on sender, etc. &lt;BR&gt;if ( subjectpropval-&amp;gt;Value.lpszW ) &lt;BR&gt;&amp;nbsp; MessageBox(NULL,subjectpropval-&amp;gt;Value.lpszW, L"Message Intercepted", MB_OK | MB_TOPMOST | MB_SETFOREGROUND); &lt;BR&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp; RELEASE_OBJ(pmsg);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; return; &lt;BR&gt;} &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;From our main application, now we just do a simple MAPILogon, create our class, and hand it to the Advise method which tells it to listen for any newly created MAPI objects.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; hr = MAPILogonEx(NULL, NULL, NULL, NULL, &amp;amp;g_pSession); &lt;BR&gt;&amp;nbsp;&amp;nbsp; g_pSink = new CAdviseSink(hWnd,0); &lt;BR&gt;&amp;nbsp;&amp;nbsp; hr = g_pSession-&amp;gt;Advise(0,NULL,fnevObjectCreated,g_pSink,&amp;amp;lConn); &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;That’s pretty much it.&amp;nbsp; I’ll attach the sample project for reference to this post if you want to play with it or see the working app.&amp;nbsp; Keep in mind, this sample is really basic and does no filtering.&amp;nbsp; That means if I send a message to myself, it fires twice!&amp;nbsp; Why?&amp;nbsp; Because a message is created when I author it, and another is created when I receive it.&amp;nbsp; You get a message on EVERY new message object.&amp;nbsp; In the real world, you would want to do some filtering.&amp;nbsp; You could modify the GetMsg routine to filter on sender, folder, etc. to make it “smarter”.&amp;nbsp; It’s up to you… go get creative.&lt;/P&gt;
&lt;P&gt;Cheers, &lt;BR&gt;Reed&lt;/P&gt;
&lt;P&gt;This blog entry brought to you by Windows Mobile and 3G Internet Connection Sharing…because a PC shouldn’t be useless just because the WiFi is.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9574523" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/hegenderfer/attachment/9574523.ashx" length="377117" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/hegenderfer/archive/tags/Mail/default.aspx">Mail</category></item></channel></rss>