Gepost op 2004.03.15 |
Geen reacties |
C#
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
For this article I decided to work with Outlook from C#.
I get way too much spam, and not only the commercial kind of spam. But also the jokes crap that 'friends' send you with 40 CC's in.
So here's my idea: We'll write an email gatherer. It'll take a folder and will go trough every mail in it, extract email addresses and save them as a comma delimited file.
Where can we find email addresses in a mail? Well, first of all, the sender. That's one already. Then the recipients of course, all those CC addresses. And lastly the mail itself, all those forwards caused the body to have plenty of addresses as well.
Real usage for this tool? Probably nothing, but you learn to work with Outlook from C# and you can have fun with collecting things, email addresses in this case.
Let's begin. All of this is in a Console App called GatherAddresses.
First we need a reference to Outlook. So add a reference to 'Microsoft Outlook 11.0 Object Library' (or 10.0, if you use 10.0 leave a comment if this source worked for you!)
When you did this you'll have two new reference, just remove the Office Core... so that you have something like this:
Our application has a very simple logic, where the Main controls it all.
[csharp]
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.IO;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace GatherAddresses {
class GatherAddresses {
static void Main(string[] args) {
// TODO
}
} /* GatherAddresses */
} /* GatherAddresses */
[/csharp]
Our goal is to collect all addresses, and we don't know how many there will be, so we store them in an ArrayList.
[csharp]
private static ArrayList emailCollection = new ArrayList();
[/csharp]
First we ask for a folder. This folder is in the form of a path. Starting from Outlook Today (the root in Outlook) to the folder you want. Example: CumpsD\Inbox would give you my Inbox.
[csharp]
Console.Write("Path to mailfolder: ");
string mailFolder = Console.ReadLine();
[/csharp]
Now we create our Outlook 'connection'.
[csharp]
Outlook._Application appOutlook = new Outlook.Application();
Outlook.NameSpace olNS = appOutlook.GetNamespace("MAPI");
olNS.Logon("", null, null, null);
[/csharp]
We navigate to the given folder with the GetFolder method, we will write later on in this article. This method will return a MAPIFolder which we need to read the Items from.
[csharp]
Console.WriteLine("Searching Folder...");
Outlook.MAPIFolder olMailFolder = GetFolder(mailFolder);
Outlook.Items olMailItems = olMailFolder.Items;
[/csharp]
Next is the real collecting part of our application. We take each MailItem in our folder and save the addresses. To get the addresses from the body we use the GetAddresses method we'll also write later on.
[csharp]
Console.WriteLine("Gathering Addresses...");
foreach(Outlook.MailItem olMail in olMailItems) {
AddAddress(olMail.SenderEmailAddress);
foreach(Outlook.Recipient olRecipient in olMail.Recipients) {
AddAddress(olRecipient.Address);
}
string[] emailAddresses = GetAddresses(olMail.Body);
foreach (string emailAddress in emailAddresses) {
AddAddress(emailAddress);
}
}
[/csharp]
After we have done everything we wanted with Outlook we close it and throw it away.
[csharp]
olNS.Logoff();
olMailItems = null;
olMailFolder = null;
olNS = null;
appOutlook = null;
[/csharp]
And lastly we save the collected addresses.
[csharp]
Console.WriteLine("Sorting & Outputting Addresses...");
SaveAddresses();
[/csharp]
Now onto our private methods:
First the GetFolder method. This will get us our folder we specified with a path.
Again we open Outlook. Then we split the path into the corresponding folders and we look for the root folder.
[csharp]
Outlook._Application appOutlook = new Outlook.Application();
Outlook.NameSpace olNS = appOutlook.GetNamespace("MAPI");
olNS.Logon("", null, null, null);
Outlook.MAPIFolder olFolder = null;
folderPath.Replace("/", @"\");
string[] arrFolders = folderPath.Split('\\');
foreach (Outlook.MAPIFolder olTmpFolder in olNS.Folders) {
if (olTmpFolder.Name == arrFolders[0]) {
olFolder = olTmpFolder;
break;
}
}
[/csharp]
When we have found our root folder, we will look for our first folder and when we find it, we replace our parent object by that folder and go looking for the next folder.
[csharp]
if (olFolder != null) {
for (int i = 1; i < arrFolders.Length; i++) {
Outlook.Folders olFolders = olFolder.Folders;
olFolder = null;
foreach (Outlook.MAPIFolder olTmpFolder in olFolders) {
if (olTmpFolder.Name == arrFolders[i]) {
olFolder = olTmpFolder;
break;
}
}
olFolders = null;
}
}
[/csharp]
And in the end we return our found folder after cleaning up.
[csharp]
arrFolders = null;
olNS = null;
appOutlook = null;
return olFolder;
[/csharp]
Next is the GetAddresses method. This method has been created by Rob Windsor in VB.NET and posted here. Permission was granted to convert it to C# and use it for this article. Thanks!
This method uses a regular expression to extract the email addresses out of a string after which they are returned as a string array.
[csharp]
// Converted from http://www.codeproject.com/vb/net/extractemail.asp
private static string[] GetAddresses(string bodyText) {
// Regex expression garnered from www.regexlib.com - thanks guys!
MatchCollection mcEmail = Regex.Matches(bodyText, @"([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})");
string[] emailAddresses = new string[mcEmail.Count];
for (int i = 0; i < mcEmail.Count; i++) {
emailAddresses[i] = mcEmail[i].Value;
}
return emailAddresses;
} /* GetAddresses */
[/csharp]
Adding our addresses is as simple as checking if the ArrayList already Contains it and add it if it doesn't.
[csharp]
private static void AddAddress(string emailAddress) {
emailAddress = emailAddress.Trim();
emailAddress = emailAddress.ToLower();
if (!emailCollection.Contains(emailAddress)) {
emailCollection.Add(emailAddress);
}
} /* AddAddress */
[/csharp]
And to close this article, the SaveAddresses method asks for a filename to write to and writes the addresses there as a delimited list which you can import in other applications.
[csharp]
private static void SaveAddresses() {
Console.Write("Path to save to: ");
string savePath = Console.ReadLine();
if (savePath != "") {
emailCollection.Sort();
using (StreamWriter sw = new StreamWriter(savePath)) {
foreach (string emailAddress in emailCollection) {
sw.WriteLine(String.Format("{0};", emailAddress));
}
}
}
} /* SaveAddresses */
[/csharp]
I tested this on 29 'fun' mails I received, and guess how many addresses came out of there? 1473!! I imported them in a small Access table to test the saved format ;)
As always, I've uploaded the project for you.
I get way too much spam, and not only the commercial kind of spam. But also the jokes crap that 'friends' send you with 40 CC's in.
So here's my idea: We'll write an email gatherer. It'll take a folder and will go trough every mail in it, extract email addresses and save them as a comma delimited file.
Where can we find email addresses in a mail? Well, first of all, the sender. That's one already. Then the recipients of course, all those CC addresses. And lastly the mail itself, all those forwards caused the body to have plenty of addresses as well.
Real usage for this tool? Probably nothing, but you learn to work with Outlook from C# and you can have fun with collecting things, email addresses in this case.
Let's begin. All of this is in a Console App called GatherAddresses.
First we need a reference to Outlook. So add a reference to 'Microsoft Outlook 11.0 Object Library' (or 10.0, if you use 10.0 leave a comment if this source worked for you!)
When you did this you'll have two new reference, just remove the Office Core... so that you have something like this:
Our application has a very simple logic, where the Main controls it all.
[csharp]
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.IO;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace GatherAddresses {
class GatherAddresses {
static void Main(string[] args) {
// TODO
}
} /* GatherAddresses */
} /* GatherAddresses */
[/csharp]
Our goal is to collect all addresses, and we don't know how many there will be, so we store them in an ArrayList.
[csharp]
private static ArrayList emailCollection = new ArrayList();
[/csharp]
First we ask for a folder. This folder is in the form of a path. Starting from Outlook Today (the root in Outlook) to the folder you want. Example: CumpsD\Inbox would give you my Inbox.
[csharp]
Console.Write("Path to mailfolder: ");
string mailFolder = Console.ReadLine();
[/csharp]
Now we create our Outlook 'connection'.
[csharp]
Outlook._Application appOutlook = new Outlook.Application();
Outlook.NameSpace olNS = appOutlook.GetNamespace("MAPI");
olNS.Logon("", null, null, null);
[/csharp]
We navigate to the given folder with the GetFolder method, we will write later on in this article. This method will return a MAPIFolder which we need to read the Items from.
[csharp]
Console.WriteLine("Searching Folder...");
Outlook.MAPIFolder olMailFolder = GetFolder(mailFolder);
Outlook.Items olMailItems = olMailFolder.Items;
[/csharp]
Next is the real collecting part of our application. We take each MailItem in our folder and save the addresses. To get the addresses from the body we use the GetAddresses method we'll also write later on.
[csharp]
Console.WriteLine("Gathering Addresses...");
foreach(Outlook.MailItem olMail in olMailItems) {
AddAddress(olMail.SenderEmailAddress);
foreach(Outlook.Recipient olRecipient in olMail.Recipients) {
AddAddress(olRecipient.Address);
}
string[] emailAddresses = GetAddresses(olMail.Body);
foreach (string emailAddress in emailAddresses) {
AddAddress(emailAddress);
}
}
[/csharp]
After we have done everything we wanted with Outlook we close it and throw it away.
[csharp]
olNS.Logoff();
olMailItems = null;
olMailFolder = null;
olNS = null;
appOutlook = null;
[/csharp]
And lastly we save the collected addresses.
[csharp]
Console.WriteLine("Sorting & Outputting Addresses...");
SaveAddresses();
[/csharp]
Now onto our private methods:
First the GetFolder method. This will get us our folder we specified with a path.
Again we open Outlook. Then we split the path into the corresponding folders and we look for the root folder.
[csharp]
Outlook._Application appOutlook = new Outlook.Application();
Outlook.NameSpace olNS = appOutlook.GetNamespace("MAPI");
olNS.Logon("", null, null, null);
Outlook.MAPIFolder olFolder = null;
folderPath.Replace("/", @"\");
string[] arrFolders = folderPath.Split('\\');
foreach (Outlook.MAPIFolder olTmpFolder in olNS.Folders) {
if (olTmpFolder.Name == arrFolders[0]) {
olFolder = olTmpFolder;
break;
}
}
[/csharp]
When we have found our root folder, we will look for our first folder and when we find it, we replace our parent object by that folder and go looking for the next folder.
[csharp]
if (olFolder != null) {
for (int i = 1; i < arrFolders.Length; i++) {
Outlook.Folders olFolders = olFolder.Folders;
olFolder = null;
foreach (Outlook.MAPIFolder olTmpFolder in olFolders) {
if (olTmpFolder.Name == arrFolders[i]) {
olFolder = olTmpFolder;
break;
}
}
olFolders = null;
}
}
[/csharp]
And in the end we return our found folder after cleaning up.
[csharp]
arrFolders = null;
olNS = null;
appOutlook = null;
return olFolder;
[/csharp]
Next is the GetAddresses method. This method has been created by Rob Windsor in VB.NET and posted here. Permission was granted to convert it to C# and use it for this article. Thanks!
This method uses a regular expression to extract the email addresses out of a string after which they are returned as a string array.
[csharp]
// Converted from http://www.codeproject.com/vb/net/extractemail.asp
private static string[] GetAddresses(string bodyText) {
// Regex expression garnered from www.regexlib.com - thanks guys!
MatchCollection mcEmail = Regex.Matches(bodyText, @"([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})");
string[] emailAddresses = new string[mcEmail.Count];
for (int i = 0; i < mcEmail.Count; i++) {
emailAddresses[i] = mcEmail[i].Value;
}
return emailAddresses;
} /* GetAddresses */
[/csharp]
Adding our addresses is as simple as checking if the ArrayList already Contains it and add it if it doesn't.
[csharp]
private static void AddAddress(string emailAddress) {
emailAddress = emailAddress.Trim();
emailAddress = emailAddress.ToLower();
if (!emailCollection.Contains(emailAddress)) {
emailCollection.Add(emailAddress);
}
} /* AddAddress */
[/csharp]
And to close this article, the SaveAddresses method asks for a filename to write to and writes the addresses there as a delimited list which you can import in other applications.
[csharp]
private static void SaveAddresses() {
Console.Write("Path to save to: ");
string savePath = Console.ReadLine();
if (savePath != "") {
emailCollection.Sort();
using (StreamWriter sw = new StreamWriter(savePath)) {
foreach (string emailAddress in emailCollection) {
sw.WriteLine(String.Format("{0};", emailAddress));
}
}
}
} /* SaveAddresses */
[/csharp]
I tested this on 29 'fun' mails I received, and guess how many addresses came out of there? 1473!! I imported them in a small Access table to test the saved format ;)
As always, I've uploaded the project for you.