Extracting/Scanning emails from Outlook using C#

1

I'm trying to make a windows form application that can be "hidden" in the taskbar (like WiFi and so on), equipped with a timer, and that every 10 seconds it scans my email inbox in Outlook.

The first part works fine, but I can't get the scan to work. At first i just want to extract the names of email subjects and put them into a text file, just to test the code. But in the end i'd like to scan one particular inbox (i have several on my outlook, like 5 or 6, with different mail address associeted, and i can't find anything on the internet to target one of them) and make a popup or something when particular email are received.

Anyway, this is the code i have so far:

    public static bool isRunning = false;

    public Form1()
    {
        InitializeComponent();

        System.Timers.Timer timer = new System.Timers.Timer(10000);
        timer.Elapsed += OnTimedEvent;
        timer.Enabled = true;
    }


    private void Hide_Click(object sender, EventArgs e)
    {
        this.Hide();
        notifyIcon1.Visible = true;
    }

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
    {
        this.Show();
        notifyIcon1.Visible = false;
    }

    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Outlook.Application app = null;
        Outlook.MAPIFolder inbox = null;
        Outlook._NameSpace ns = null;

        if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
        {
            try
            {
                app = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
                inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
                ns = app.GetNamespace("MAPI");
                List<Outlook.MailItem> ReceivedEmail = new List<Outlook.MailItem>();
                List<string> titles = new List<string>();

                foreach (Outlook.MailItem mail in inbox.Items)
                {
                    ReceivedEmail.Add(mail);
                }

                foreach (Outlook.MailItem mail in ReceivedEmail)
                {
                    titles.Add(mail.Subject.ToString());
                }

                File.WriteAllLines("C://Users/A222946/Desktop/allMails.txt", titles);

            }
            catch (System.Runtime.InteropServices.COMException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        else
        {
            MessageBox.Show("Please, start outlook..");
        }

    }
}

The error i find when i'm running this is the following:

Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE)

I tried with and without administrator rights, same error.

Update

So after some changes it looks like this now:

private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Outlook.Application app = new Outlook.Application();
        Outlook.MAPIFolder inbox = null;
        Outlook._NameSpace ns = null;
        Outlook.Items items = null;

        if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
        {
            try
            {
                app = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
                ns = app.GetNamespace("MAPI");
                inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
                items = inbox.Items;
                List<Outlook.MailItem> ReceivedEmail = new List<Outlook.MailItem>();
                List<string> titles = new List<string>();

                foreach (Object obj in items)
                {
                    if (obj is Outlook.MailItem)
                    {
                        ReceivedEmail.Add((Outlook.MailItem)obj);
                    } 
                }

                foreach (Outlook.MailItem mail in ReceivedEmail)
                {
                    titles.Add(mail.Subject.ToString());
                }

                File.WriteAllLines("C://Users/A222946/Desktop/allMails.txt", titles);

            }
            catch (COMException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        else
        {
            MessageBox.Show("Please, start outlook..");
        }

    }

But i still have this error:

object reference not set to an instance of an object

Also, do you have any idea how i could target one particular mailbox? Example: "abcdefg@blabla.com"

c#
visual-studio
email
outlook
asked on Stack Overflow Sep 1, 2016 by RomainG • edited Jan 23, 2018 by dbc

2 Answers

0

I think the COM components are not accessible. COM components are used by some of the Windows components(like MS Office).You need to make use of STAThreadAttribute.

[STAThread]
static void Main(string[] args)
{
    // etc..
}

I think this should fix the issue.

answered on Stack Overflow Sep 1, 2016 by Nikhil Kumar
0

Firstly, this really needs to be an Outlook COM addin (which runs when Outlook runs), not a separate exe that detects when Outlook is running.

That being said, you are using Namespace.GetDefaultFolder. What you need to be using is Store.GetDefaultFolder (where Store is retrieved from the Namespace.Stores collection) if the store is already opened in the profile. Or Namespace.CreateRecipient / Namespace.GetSharedDefaultFolder if the store is not already opened in the profile.


User contributions licensed under CC BY-SA 3.0