All posts by Craig Murphy

Passwords alone, are not enough. Even if they were, are they hard to break?

[As quoted in the Guardian: http://www.guardian.co.uk/technology/blog/2008/nov/23/technology-letters-blogs]

Relying on a single password for more than one purpose, e.g. logging on to your web-mail, instant messaging service, Facebook, Bebo, etc. is probably very commonplace.  Indeed, exposés such as Twitterank, and even it’s parody site TwitterAwesomeness, highlight the ease at which folks will essentially surrender their username and passwords.  Twitterank didn’t just catch the unsuspecting Internet user, they also caught a number of people who really should have known better. 

Sites that do need your Twitter username and password, such as BrightKite, use it in order to post tweets on your behalf.  In BrightKite’s case, it tweets each time you “check in” to their “where am I” service.  The check-in process involves you telling BrightKite where you are, it then sends out a Tweet telling the world.  Such sites make their intentions very clear in the Terms Of Use, Code of Conduct and Privacy pages. 

However, so did Twitterank. The site made it clear what it wanted you to believe it was doing with your username and password.  Even if you didn’t read the Twitterank terms of service or FAQ, it was embedded within the source code, as Barry Dorrans carefully points out.  The speed at which the Twitter population flocked to Twitterank suggests that were there any ulterior motives, the site would be well placed to exploit a significant portion of the Twitter accounts that it had opportunity to harvest.

Twitterank was different.  It relied on our instinctual want to graded or rank ourselves amongst our peers.  No matter how hard we try, we’re all competitive by nature.  We want to know where we stand/sit in relation to our peers.  Some services, such as Twitter Grader have managed to achieve this without the need for a Twitter password.  Granted there’s only so much Twitter Grader can do, however it’s a polite service that has introduced me to a number of Twitter users in Scotland – users that I may not have discovered.

There was little indication whether a Twitterank of 100 was good or bad.  Some users reported ranks of over 200, others, as we’ve seen already, received a rank of zero.  The mathematics behind the site were reported via a comment in this blog as being “Real Math(tm)” and were comparable in accuracy to Google’s PageRank mechanism.  I’m not a mathematician so I won’t be debunking any formula, algorithm or approaches.  Well, not just yet at least.  For Twitterank to have been useful, it would need to allow us to determine whether our rank was better or worse than other Twitterankers (there it is again, I do apologise).

Twitterank didn’t really try to hide its intentions, however because of the the site’s ease of use, instant gratification and rapid publicity, its uptake was huge (it trended TweetStats and Twitter Search, and at the time of writing, continues to do so – outdoing “Obama” and “James Bond”).  The publicity was part of what made it so popular – it sent out a Tweet announcing your Twitterank, including a link back to the site thus encouraging users to discover their own ranking.  In most cases, this would probably be fine, however spare a thought for the Twitter folks who received a ranking of zero – and there where many of them!  Indeed, many Twitterankers (can I really get away with saying that?  Too late now!) tweeted their dissatisfaction at their ranking. 

Amusingly, Twitterank’s creator (@ryochiji) reported on his Twitter feed that low rankers should try again tomorrow.  Oh, so that’s how it works – everybody’s Twitterank will improve over time, that’ll work, great system, yes?  Further information may be found on the Twitterank blog, assuming WordPress haven’t deemed it necessary to close it down.

It’s not all about gullible users though
This morning, at the time of writing, a few hours after Twitterank was exposed for the social experiment that it probably is (or was), saw me reading Bruce Schneier‘s Read me first column in the Technology section of The Guardian.  Bruce writes a great piece explaining how passwords don’t need to be broken per say, but that they are inherently easy to guess.

Without spoiling the article too much, assuming that you are going to read it, Bruce highlights our password selection techniques.  One such method, and one that is certainly very familiar to this writer in his corporate environment, is the keyword+appendage approach.  Users often take their child’s name, their dog’s name, etc. and add a numeric digit or two after the name, e.g. frank01 or rover12. 

Today’s processing power means that software can intelligently guess huge combinations of keyword+appendage passwords in a relative short and acceptable period of time.  Gone are the days when passwords would take days or weeks to crack.  If you need more convincing, think about how long it takes the average WiFi hacker to crack your wireless router/modem WEP encryption keys.  Or even your WPA encryption?

Bruce makes the suggestion of using a personal sentence as your password.  Not the sentence itself, but an obfuscated version of the sentence.  His example (yes I’m spoiling the original article, sorry) uses “This little piggy went to market” – it creates an obfuscated password of tlpWENT2m.  Such as password would take a significant amount of time to be guessed using processing power alone.  Just in case you were tempted, Bruce rightfully advises that we don’t use tlpWENT2m ourselves…oddly enough.

Increasing security, some options
With the ease at which Twitterank coaxed visitors into typing in their username and password, it seems the days of the password as a single source of authentication are numbered.  We need to be considering more secure alternatives that involve “levels of authentication”.  Usablity is the key to widespread acceptance, any product in this space must be easy to use; its interface must be fundamental such that selection of a secure-level authentication token requires little more effort than offering a basic-level token. 

With Twitterank-like incidents becoming more common, I predict that during 2009 we will see the general acceptance and widespread uptake of such authentication mechanisms such as OpenID, and CardSpace (further reading here and here).  You should familiarise yourself with these mechanisms because major web-sites such as Yahoo are gradually introducing them as part of their login process.  Indeed, even the likes of Facebook, where you can be whoever you want to be, may have to succumb and implement a more secure user registration and identity verification process.

Beyond authentication into verification
Going beyond authentication, we need to consider verification, particularly of identity.  The internet has little in the way of process that can help us confirm an individual’s authenticity and identity – how do you know that the person your are tweeting with or Facebooking is the person they say they are?  Twitter had the great fake Sarah Silverman incident of October 2008.  Facebook has many impersonation cases, a few of which I discuss in elsewhere on this blog

Firms, such as NetIDme are well placed to take advantage of the needs of the authentication and identity verification marketplace.  Identity verification through NetIDme processes involves a combination of stages, if you’re in the UK or US they boast a 95% “automatic verification” rate. The remaining 5%, or if you are a child, requires some form of personal contact with the NetIDme team – whether it is a fax or a phone call.  However, prior to the personal contact, you are invited to provide such things as your Driving Licence Number, National Insurance number, Social Security Number or Passport number in order for third party checks to take place.  Obviously this is much more involved and potentially more invasive than a simple username/password combination. The fact we are now able to authenticate and verify who we are, including how old we are, is a key step forward in the growth and maturity of the Internet.

And finally…
At the time of writing Twitterank is still up and running, whilst there appears to be no malicious intent on the creator’s part, the whole debacle in the social engineering space has left a bitter taste in the mouths of many people.  I am sure that no ill intent was ever on the cards, however Twitterank has proven that everybody needs to think about their own on-line security and the implications of password surrender. 

Just think what might have happened to your Twitter feed? “Ah,” you say, “but it’s just my Twitter feed, I don’t really care if somebody hacks it and owns it.”  That’s fine, but a lot of users have a single password, and that is where the problem stems from.  Identity theft often starts from the smallest thing.  I have a colleague whose identity was stolen simply because she left her name on the door bell of her previous house. The house had been sold to a gentleman who then let / rented the house.  The new tenants used the knowledge of the previous owner’s name to start off the identity theft process.  It is that simple.

I’ll leave you with advice that is mentioned elsewhere in this blog:

  1. Don’t use the same password for social networking sites and services that are more important to you such as your on-line bank or your web-mail.  If your password is harvested, as Twitterank could have done, you may find yourself compromised in more than one way.
  2. Avoid simple passwords such as “password”, “itsasecret” or “letmein”.  Amazingly, during my university days somebody actually told me their password was “itsasecret”.  Indeed it was…I logged in and was later accused of cracking the said password.  A little trouble ensued but it was soon dropped when I explained that i had actually been given the password in the first place! 
  3. Consider “upping” your levels of security your OpenID – there are plenty of providers.  Yahoo, MyOpenID and NetIDme to name just a few.  Any progress in this direction, is good progress. Of course, you could always demand OpenID!

Safe and happy surfing!

Further reading:

Password security – even big names fail
Twitterank – celeb or peon? @t_rank

Twitterank – celeb or peon? @t_rank

my Twitterank is 9999.99 http://twitterawesomeness.com/

Just a short post to remind users to be careful with their online credentials.

Twitterank appears to have grabbed the limelight (tonight, GMT) as one such web application that relies on folks wanting to be popular…or at least find out how popular (or not) they are in comparison to some metric that ranks them over other users.

However it’s basically a user-name and password harvesting mechanism. I have a suspicion that it’s a social experiment and all those passwords that were collected will not be used for anything dodgy. Whatever the truth, in the wrong hands the possibilities are endless – here are a couple to worry you: @blowdart and @camurphy

camurphy: @blowdart @dacort – true evilness would be to post random tweets from random victims…did I just say that out loud?

blowdart: @CAMURPHY @dacort Stuff like “I’m wearing my sister’s panties”. DO IT!

If you have received a Twitterank, my advice to you is that you change your Twitter password immediately. Once you’ve done that, any other places that you use that same password for, change it there too.

A safe parody of the site can be found here, courtesy of @dacort.

There’s more here:
http://blogs.zdnet.com/collaboration/?p=163
http://mashable.com/2008/11/12/twitterrank/
http://www.louisgray.com/live/2008/11/twitterank-can-have-my-password-no.html
http://www.guardian.co.uk/technology/blog/2008/nov/13/twitter-password-security

If you must rank yourself, check out twitter.grader.com – it doesn’t need your password to give you some feel-good factor!

Oh, @t_rank, I’m still waiting for reply to this polite request!

Announce – DDD Scotland 2 – 2nd May 2009

What/When/Where:
Following the success of DDD Scotland in May 2008, I’m pleased to announce that DDD Scotland 2 will be held on the 2nd of May 2009 in Glasgow.

As usual, DDD Scotland will follow the same pattern as the highly successful DDD events held in Reading.

Barry Dorrans wins a prize for the most humourous announcement so far – check out his post over here! Barry’s use of McDDD, whilst possibly stereotypical, has made a few folks laugh over at Twitter! I’m not so sure about JockDDD, but I’m laughing anyway!

Technorati Tags: , , , , ,

Blogging frequency: affected by [business] travel

As some of you may know, I’ve been doing some stats recently – there must be something in the air!

Anyway, as part of another stats gathering exercise, I found myself looking at a list of blog entries that I had made over the past 12 months to October 2008. Looking at the list, it was obvious that there were a couple of significant dips and the odd peak. The dips were typically the result of [business] travel to London. The peaks were the result of a Microsoft product launch and the use of a single post to capture “my week” – largely to document the trials and tribulations of business travel, but occasionally to capture other more interesting events!

WordPresz 2.6.4 – fake?

When I logged into my admin account for my WordPress blog, I was surprised to find this waiting for me in the dashboard:

UPDATE 07/11/2008: Watch a short (less than 60 seconds) video demonstrating the dashboard hijack.

UPDATE 08/11/2008: Cleaning up after the WordPress 2.6.4 incident. Note that I did not install the fake 2.6.4, so it’s not a clean up for that scenario.

Wordpresz.org appears to be a spoof of wordpress.org. With the exception of the download link and one or two others (Facebook link, etc.) all the pages lead back to the front/home page.

I’ve just downloaded the wordpresz 2.6.4 offering to see what’s different. If I find anything, and if time permits, I’ll update this post.

22:26 UPDATE
Just looking at the respective home pages for WordPresz.org vs WordPress.org, a few differences jump out – check out items 1, 2 and 3 below.

Item 1 – the download size is too round and is incorrect, it should be about 1.4mb in this case.

Item 2 – these are randomised over at WordPress.org, but are static at WordPresz.org.

Item 3 – The real WordPress.org has a “Showcase” link included.

Indeed, the source for both home pages reveals that WordPresz.org is simply an earlier snapshot of WordPress.org.

Looking at domain data for WordPresz.org, there are a few holes here. Google hasn’t indexed this site? What about the Alexa ranking?

Whereas, WordPress.org is pretty popular with Google and has an Alexa ranking.

23:59 UPDATE
Via Clayton, this may well be part of the problem. There’s further comment on the WordPress support forum too. I’ve since upgraded to 2.6.3 via the WordPress.org download.

The moral of this story: keep on top of WordPress updates and security fixes.

**

Images grabbed using TechSmith‘s SnagIt – an essential tool for developers and bloggers alike. With thanks to Betsy Weber

Technorati Tags: ,

Open XML – Resources

This post serves as a placeholder for my Open XML links, resources, etc. I will update it from time to time.

History
04/11/2008 – I’ve updated the demo code to include the code used in my screencast demonstrating Word 2007 Content Controls.

03/11/2008 – I’ve updated the demo code to include examination of the customXML file that is populated by the content control example (ContentControl.docx). Demo 5 shows how we can inject our own XML into the content controls.

Demo 6 presents the few lines of code required to extract the XML (as populated by the content controls) into an XmlDocument. Once the customXML is in an XmlDocument we are free to access the nodes as required.

Thus we are now in a position were we can create a document with custom data present, pass it to a user, the user can amend the custom data, save the document and send it back to us. We can then extract that custom data for subsequent processing. I will prepare a short screencast to demonstrate this – watch this space.

28/10/2008 – Posted pre-VBUG Newcastle inaugural delivery of An Introduction to Open XML. Download the slides and Visual Studio 2008 / Open XML SDK 2 CTP1 demo code. It’s likely that I will update this code to reflect further CTP releases.

**

Eric White’s blog entry about the first CTP of the Open XML SDK V2.

Microsoft’s primary Open XML portal, OpenXMLDeveloper.org.
Microsoft’s on-line forum for Open XML

OpenXML Code Snippets (for Visual Studio 2005) (Managing code snippets)

Blogs
Brian Jones
Mauricio Ordonez
Doug Mahugh
Kevin Boske
Erika Ehrli
Gray Knowlton’s OpenXML content

Product/Technology Blogs
XPS
Word
Excel

Videos
Open XML File Formats

Using Word 2007 Content Controls
Matthew Scott: Application Development using the Open XML File Formats
Matthew provides an excellent explanation of Word 2007’s content controls and customXML parts. Before OpenXML you probably found yourself using Word bookmarks to leave placeholders inside a Word document – content controls essentially replace those.

Andrew Coates has some excellent information about using Content Controls in conjunction with Matthew’s Word Content Control Toolkit (available on CodePlex).

Technorati Tags: , , , , , , , , , ,

The Fake Sarah Silverman Show @sarahsilverman @fake_sarah_silv @imKM

The Internet is awash with security issues, none more so than the social networking sites that so many users place considerable amounts of trust and belief. Today, users can sign up on such sites as Facebook and Twitter (to name two that I use) without any form of secondary credential check, i.e. you can sign up and be whoever you want to be. Evidence of this kind of impersonation can be found in my earlier blog entry where I discussed the “celebrities” who appear to be on Facebook.

From social networking to micro-blogging, the impersonation continues. During October the Twitter community was delighted to see Stephen Fry appear in the “Twitterverse”. Our delight continued when Stephen chose to follow a vast horde of us. John Cleese enjoyed similar celebrity status. However, Stephen and John were accepted into the Twitterverse without a second thought regarding their authenticity. It didn’t take long to spot that Stephen and John were standing on the “I am who I say I am” side of the fence. Their writing style is most eloquent and is rather recognisable.

Enter Sarah Silverman…on Twitter:

I read the Twitter stream reasonably carefully, checking a few things along the way. The stream mentioned London as a destination – true – the real Sarah Silverman did a gig at the Hammersmith Apollo last Sunday. A few other things checked out. What caught my eye was the fact that she was riled by the fact that she had lost a follower…so I suggested a web-site that might help her in the future. At that point the fake @sarahsilverman started to follow me, I was 1 of 23 folks she was following. And I remained 1 of 24 folks she was following whilst her followers grew from a handful to over 600 – this is most odd and served as a clue to something fishy.

The clue trail…
There’s not much to report about the profile picture or the user-name. Over the course the period 23/10/2008 to 26/10/2008, @sarahsilverman used at least two profile pictures – these were probably sourced from a variety of on-line photo repositories. If there were any clues to be found in the profile picture, I didn’t spot them.

Next up, the Biography and web-site details:

This is where it gets amusing. Silverman’s TwitterJacker made every effort to make the biography as real as possible. She (or he, more about why I say this shortly) even provided a link back to the real Sarah Silverman’s “Unofficial” web-site: http://sarahsilvermanonline.com/. Ironic, but still nothing hugely obvious there – anybody could obtain this information and set it up as it was here. However, even before I started following @sarahsilverman, I had my doubts about the authenticity of the textual content and writing style. I took the liberty of questioning the authenticity of celebrities in general. This prompted a rapid change in the biography text, previously it didn’t contain the text “and omfg i’m not going to say if i’m real or not”. OK, not really clues, however the use of “i’m” is a small clue. As is the use of “not” twice – the second “not” should really be replaced with “otherwise”.

I took the bait “Leaving for a bit. again! ~ as said ~ you should follow @imKM … see… isn’t that weird.” Prior to that bait finding its way on to the fake @sarahsilverman’s Twitter stream, a request for follow @imKM had arrived via a direct message: “…twitter friend ~ imKM?” What I found interesting about this approach was @imKM’s background image. I can’t be sure, but it does look like Sarah Silverman is in the background of this photograph:

I don’t know, perhaps @imKM happened to be using the cash point ahead of the real Sarah Silverman and decided to grab a photograph? Who knows for sure? Whatever the truth, when I mentioned this to the fake @sarahsilverman in a direct message, she responded “Yes, people say Photoshop but, he corrected me. It is actually faded with “LiveQuartz”. neat huh. say. are you not following my best… “

Connected to the background image challenge, during 25/10/2008, as the truth started to unfold, this tweet was a further clue to feathers being ruffled:

@imKM needs to stop using my photoshoped image. [http://www.youtube.com/videosbykm] he set it as his background.

Still at 24/10/2008, I had confirmed that both the fake @sarahsilverman and @imKM were using Apple Mac’s for their tweets. Both Twitter streams exhibited over-use of the tilde character “~”. Via a direct message, I challenged the fake @sarahsilverman about the use of the tilde – oddly I am unable to lay my hands on that direct message, I can’t see it in my sent items stream. However, the fake @sarahsilverman replied: “or a creative thing”. It’s a small thing to notice, however two people who instant message each other a lot will pick up on each other’s habits. Or, a single person using two Twitter accounts will make the mistake of following the same habits.

On Sunday 26/10/2008, it became evident through a self-confession that @sarahsilverman wasn’t the real Sarah Silverman. Prior to the self-confession, a few blogs picked up on it, here and here. The @sarahsilverman feed vanished and was replaced with @fake_sarah_silv. The first post truthful post announced:

“My name is Sarah Ascher, friend of @imKM; not @imKM. I am sorry. This started as a joke, I guess people can’t take it.”

For a few minutes the @fake_sarah_silv continued to use the same Twitter background. This was probably an oversight as he or she was too busy undoing the web of deceit that had unfolded so rapidly:

Very soon after the confession tweet, @fake_sarah_silv finally changed the background image:

Of course, at the time of writing, it hasn’t been confirmed that Sarah Ascher even exists. As many Twitter users predicted, @fake_sarah_silv and @imKM could be the same person. Whatever the case, it was a shameful cry to drive traffic to @imKM’s content. KM himself (we must assume that it is a he!) eventually wrote a lengthy piece attempting to distance himself from the whole quagmire. Amusingly, @imKM was rather quick to quash any thoughts that he had a crush on the real Sarah Silverman! I must admit, the crush thing was first on my thoughts once the @imKM follow request appeared – that and the fact it appeared to be Sarah Silverman in @imKM’s background image.

Anyway, not surprisingly, it seems @imKM was somewhat disturbed by some of the tweets he was receiving:

I hope your parents have a good lawyer little boy.

heaven forbid your take responsibility for your actions

I don’t imagine that this will go away in a hurry, there’s probably a few more days of fall out to be had whilst bloggers and Twitterer’s around the globe pick up on it. In the meantime, @sarahsilverman is at 23:22 in the UK on 23/10/2008 is strangely still available. If the real Sarah Silverman reads this (hey, it’s possible surely?) perhaps it’s time you grabbed your presence on Twitter before somebody else does this all over again? Other micro-blogging sites are available.

Your take-away…
@imKM was attempting to drive web traffic to his blog and video site by relying on the hard work and goodwill of other folks. Whether you like the real Sarah Silverman or not, it had an effect: 600 followers for the fake @sarahsilverman within a short space of time. @imKM received a few extra followers, however now his reputation has taken a serious beating. Small mistakes, and failing to follow accepted Internet etiquette and Twitterquette led to the downfall being as rapid as it was. If @imKM was patient and exercised some care, he could have kept this charade running for weeks or months.

The moral of this blog post is still the same as it was when I wrote about impersonation last year. There are many places on the Internet where it is necessary to verify who you are and in some way prove that you are who you say you are (authenticity), however very few places actually implement them – even some of the big banks struggle to do this properly.

It’s difficult to offer any guaranteed advice that can help you spot fakes, hopefully this post provided a few things to look out for. In social networking and indeed, in micro-blogging situations, it’s always worth checking out the friends/followers of the person you are about to connect with. Take a look at the people that person connects with, do they look like the kind of people who would connect with each other?

Oh, 23:25 in the UK on 26/10/2008 and http://twitter.com/fake_sarah_silv does not exist!

Finally, it was lovely to write this blog post as if I was on first name terms with Stephen and John. I am, of course, not and I will convey my apologies to Mr Fry and Mr Cleese when I next meet them.

Images grabbed using TechSmith‘s SnagIt – an essential tool for developers and bloggers alike. With thanks to Betsy Weber

Technorati Tags: , , , , , , , ,

Implementing GetEmailAddressFromExchange in C#

As developers we often find ourselves writing small one off applications to perform a specific “here and now” requirement. The task was to produce a list of e-mail addresses from a Microsoft Outlook folder. I’m reasonably happy with my understanding of the Microsoft Outlook object model, well, happy enough that I’ve managed to get it to do what I need it to do. I am by no means an expert, however since I’ve been making reasonable progress with my “duplicate e-mail remover” application, I figured that iterating over an Outlook folder extracting the e-mail address on they way couldn’t be too hard.

Indeed, for SMTP e-mail addresses, it’s fairly straightforward – a mail message in Outlook has a SenderEmailAddress property that holds the e-mail address in the format name@domain.com.

In a corporate environment you may find X400 formatted addresses similar to this one:

/O=/OU=GLOBAL/CN=RECIPIENTS/CN=FBUTCHER76409312

The aforementioned SenderEmailAddress is also used to store this address, so if you were expecting an SMTP address, too bad!

However, mail messages also have a string property SenderEmailType which returns EX for mail items that use Exchange Server addressing. Here’s how you might use it:

               // Catch e-mails sitting on an Exchange Server...
                            if (oMsg.SenderEmailType == "EX")
                            {                                
                                display = GetEmailAddressFromExchange(oMsg.SenderName);
                            }
                            else
                                // Otherwise, assume SMTP addresses
                                display = string.Format("{0}", oMsg.SenderEmailAddress);

The eagle-eyed reader will have noticed the call to GetEmailAddressFromExchange. I really wanted an SMTP address for all the mail items in the folder(s) in question. A little bit of searching revealed this well-written article by Julian Biddle at An Original Idea.

Julian’s article explained how to get an e-mail address from an Exchange Server address using Visual Basic in .NET. I prefer to use C#, so set about converting Julian’s code (which was known to work). There are other flavours of this code floating on the Internet, this one works for me, your mileage may vary.

The entire application can be downloaded here. This little application is crude, but it solved a problem for me at the time of writing. It demonstrates how to iterate over Microsoft Outlook folders (not just the Inbox) building a treeview on the way. It also demonstrates how to save the contents of a ListView control to a CSV file.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
using System.IO;

namespace OutlookEmailAddressExtractor
{
    public partial class frmExtractEmailAddresses : Form
    {
        public frmExtractEmailAddresses()
        {
            InitializeComponent();
        }

        const int S_OK = 0;

        [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi, EntryPoint = "HrGetOneProp@12")]
        private static extern void HrGetOneProp(IntPtr pmp, uint ulPropTag, out IntPtr ppProp);

        [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi, EntryPoint = "HrSetOneProp@8")]
        private static extern void HrSetOneProp(IntPtr pmp, IntPtr pprop);

        [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi, EntryPoint = "MAPIFreeBuffer@4")]
        private static extern void MAPIFreeBuffer(IntPtr lpBuffer);

        [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)]
        private static extern int MAPIInitialize(IntPtr lpMapiInit);

        [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)]
        private static extern void MAPIUninitialize();

        const string IID_IMAPIProp = "00020303-0000-0000-C000-000000000046";
        const uint PR_SMTP_ADDRESS = 972947486;

        struct SPropValue
        {
            public uint ulPropTag;
            public uint dwAlignedPad;
            public long Value;
        }

        Microsoft.Office.Interop.Outlook.Application oApp;
        NameSpace oNS;


        private string GetEmailAddressFromExchange(string emailName)
        {
            MailItem loDummyMsg = (MailItem)oApp.CreateItem(OlItemType.olMailItem);
            Recipient loAddress = loDummyMsg.Recipients.Add(emailName);
            loAddress.Resolve();
            string SMTPAddress = GetMAPIProperty(loAddress.AddressEntry.MAPIOBJECT, PR_SMTP_ADDRESS);

            return SMTPAddress;
        }


        private string GetMAPIProperty(object oMAPIObject, uint uiPropertyTag)
        {
            if (oMAPIObject == null)
            {
                return "";
            }

            string sProperty = "";
            IntPtr pPropValue = IntPtr.Zero;

            IntPtr IUnknown = IntPtr.Zero;
            IntPtr IMAPIProperty = IntPtr.Zero;

            try
            {
                MAPIInitialize(IntPtr.Zero);

                IUnknown = Marshal.GetIUnknownForObject(oMAPIObject);

                Guid guidMAPIProp = new Guid(IID_IMAPIProp);

                if (Marshal.QueryInterface(IUnknown, ref guidMAPIProp, out IMAPIProperty) != S_OK)
                {
                    return "";
                }

                try
                {
                    HrGetOneProp(IMAPIProperty, uiPropertyTag, out pPropValue);

                    if (pPropValue == IntPtr.Zero)
                    {
                        return "";
                    }

                    SPropValue propValue = (SPropValue)Marshal.PtrToStructure(pPropValue, typeof(SPropValue));

                    sProperty = Marshal.PtrToStringAnsi(new IntPtr(propValue.Value));
                }
                catch (System.Exception ex)
                {
                    throw ex;
                }
            }
            finally
            {
                if (pPropValue != IntPtr.Zero)
                {
                    MAPIFreeBuffer(pPropValue);
                }

                if (IMAPIProperty != IntPtr.Zero)
                {
                    Marshal.Release(IMAPIProperty);
                }

                if (IUnknown != IntPtr.Zero)
                {
                    Marshal.Release(IUnknown);
                }

                MAPIUninitialize();
            }

            return sProperty;
        }

        

        void _PopulateFolderList(MAPIFolder oFolder, TreeNode node)
        {
            foreach (MAPIFolder folder in oFolder.Folders)
            {
                string s =String.Format("{0} ({1}) [{2}]", 
                                        folder.Name, 
                                        folder.Folders.Count, 
                                        folder.Items.Count);
                
                TreeNode thisNode = node.Nodes.Add(s);

                thisNode.Tag = folder;

                if (folder.Folders.Count > 0)
                {
                    _PopulateFolderList(folder, thisNode);
                }
            }
        }

        private void btnGetFolders_Click(object sender, EventArgs e)
        {
            oApp = new Microsoft.Office.Interop.Outlook.Application();
            oNS = oApp.GetNamespace("MAPI");

            progressBar.Minimum = 0;
            progressBar.Maximum = oNS.Folders.Count;
            progressBar.Value = 0;

            this.Cursor = Cursors.WaitCursor;

            foreach (MAPIFolder f in oNS.Folders)
            {
                TreeNode node = tvOutlookFolders.Nodes.Add(f.Name);

                if (f.Name != "Public Folders" && f.Name != "Internet Calendars")
                    _PopulateFolderList(f, node);

                progressBar.Value++;
            }

            progressBar.Value = 0;
            this.Cursor = Cursors.Arrow;
        }


         

        private void btnGetEmailAddresses_Click(object sender, EventArgs e)
        {
            TreeNode nodeSelected = tvOutlookFolders.SelectedNode;
            MAPIFolder folder = (MAPIFolder)nodeSelected.Tag;

            this.Cursor = Cursors.WaitCursor;

            lvEMailInSelectedFolder.Items.Clear();

            if (folder != null)
            {
                progressBar.Maximum = folder.Items.Count;
                progressBar.Minimum = 0;
                progressBar.Value = 0;

                string sClassComp = "IPM.Note";

                Items oItems = folder.Items;

                label1.Text = oItems.Count.ToString();

                MailItem oMsg = (MailItem)oItems.GetFirst();

                while (oMsg != null)
                {
                    if (oMsg.MessageClass == sClassComp)
                    {

                        if (oMsg.Body != null)
                        {
                            string display;

                            // Catch e-mails sitting on an Exchange Server...
                            if (oMsg.SenderEmailType == "EX")
                            {                                
                                display = GetEmailAddressFromExchange(oMsg.SenderName);
                            }
                            else
                                // Otherwise, assume SMTP addresses
                                display = string.Format("{0}", oMsg.SenderEmailAddress);

                            bool okToAdd = true;
                                
                            if (cbIgnoreDuplicates.Checked)
                                okToAdd = lvEMailInSelectedFolder.FindItemWithText(display) == null;

                            if (okToAdd)
                            {
                                ListViewItem item;
                                item = lvEMailInSelectedFolder.Items.Add(display);

                                item.SubItems.Add(oMsg.SenderName.ToString());

                                if (oMsg.Subject != null)
                                    item.SubItems.Add(oMsg.Subject.ToString());
                                else
                                    item.SubItems.Add(" ");

                                item.SubItems.Add(oMsg.SenderEmailType);
                            }
                        }
                    }

                    bool exceptionRaised = true;

                    while (exceptionRaised)
                    {
                        try
                        {
                            oMsg = (MailItem)oItems.GetNext();
                            progressBar.Value++;
                            exceptionRaised = false;
                        }
                        catch
                        {
                            exceptionRaised = true;
                        }
                    }
                }

                lvEMailInSelectedFolder.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);

                btnSaveToCSV.Enabled = true;

                progressBar.Value = 0;

                this.Cursor = Cursors.Arrow;
            }
        }

        private void btnSaveToCSV_Click(object sender, EventArgs e)
        {
            StringBuilder listViewContent = new StringBuilder();

            foreach (ListViewItem item in this.lvEMailInSelectedFolder.Items)
            {
                listViewContent.Append("\"");
                listViewContent.Append(item.Text);
                listViewContent.Append("\"");

                listViewContent.Append(",");

                listViewContent.Append("\"");
                listViewContent.Append(item.SubItems[1].Text);
                listViewContent.Append("\"");
               
                listViewContent.Append(Environment.NewLine);
            }

            saveFileDialog.FileName = "e-mail addresses.csv";
            saveFileDialog.Filter = "CSV files (*.csv)|*.csv|All files (*.*)|*.*";
            saveFileDialog.ShowDialog();

            if (saveFileDialog.FileName != "")
            {
                TextWriter tw = new StreamWriter(saveFileDialog.FileName);

                tw.WriteLine(listViewContent.ToString());

                tw.Close();
            }
        }

        private void tvOutlookFolders_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (tvOutlookFolders.SelectedNode != null)
            {
                btnGetEmailAddresses.Enabled = true;
            }
        }
    }
}

Technorati Tags: , , , , , , , , , , , ,