Outlook 地址收集器
从 Outlook 提取电子邮件收件人
引言
这个应用程序使用 Outlook 提取电子邮件中的收件人电子邮件地址。 如果您使用 Outlook(例如,在 Windows 域中),TO 和 CC 字段将显示名称或电子邮件地址,而不是名称。 有时,收集信件中的所有电子邮件地址非常有用。 该应用程序适用于 Office2003,未在较新版本上测试过。
此解决方案解决了什么问题?
几周前,我想通过一个知名的邮件群组提供商创建一个邮件群组。 原因是我们大约与 30 个用户互相通信。 有时 Outlook 中的 TO 字段比消息体大,并且信件的大小不必要地很大。 所以我创建了一个邮件群组,但我必须收集电子邮件地址。 邮件群组提供商仅使用电子邮件地址。 我发现了一个大问题。 Outlook 有时显示带有超链接的昵称,有时显示电子邮件地址。 就像这样
收件人:John Smith; george@anyaddress.com
当然,您可以逐步提取电子邮件地址,但这需要很长时间(单击、Outlook 属性、复制-粘贴等)。 这就是我编写这个程序的原因。
这如何帮助其他人? - 有什么启发?
通过这个简单的应用程序,我演示了如何使用 Outlook Interop 包,如何通过此提供程序访问 Outlook 中的邮件项目,然后我展示了如何迭代邮件项目以及如何获取附件。 在 Active Directory 环境中,Outlook 中的收件人可以是简单的联系人或域用户。 收件人项目包含带有联系人的电子邮件地址,但包含域用户的 legacyexchangedn
LDAP 字段。 最后,我展示了一个简单的方法,如何通过简单的 LDAP 查询将 lagacyexchangedn
字段“转换”为电子邮件地址。 最后但并非最不重要的一点是,该应用程序将通过简单的 WMI 查询识别登录的域。
关键词
- 使用 Microsoft Office Interop 包在 Outlook 中获取电子邮件
- 获取附件和收件人项目
- 使用 LDAP 查询
- 使用 WMI 查询
Using the Code
首先要解决的任务是如何从 Outlook 收件箱获取电子邮件对象。 这是一组 MailItems
,我们必须提取其属性。 使用此方法访问默认收件箱
//attach Outlook application to myApp object
Microsoft.Office.Interop.Outlook.Application myApp =
new Microsoft.Office.Interop.Outlook.ApplicationClass();
//get mapi Namespace
Microsoft.Office.Interop.Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
//Last to reach the default mailbox
Microsoft.Office.Interop.Outlook.MAPIFolder myinbox =
mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.
Outlook.OlDefaultFolders.olFolderInbox);
然后获取一个 MailItem
并获取其属性。 收件人是一个集合。 使用索引从 myinbox 集合中选择一个电子邮件项目。
// Gets email properties
// Get the mailitem's body
richTextBox1.Text =
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[index]).Body;
// Get the mailitem's sender name
textBox3.Text =
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[index]).SenderName;
// Get the mailitem's sender email address
sendermail =
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[index]).SenderEmailAddress;
// Get all recipients
Microsoft.Office.Interop.Outlook.Recipients recipients =
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[index]).Recipients;
// Iterate recipient from recipients collection
foreach (Microsoft.Office.Interop.Outlook.Recipient item in recipients)
{
.....
textBox7.Text = textBox7.Text + item.Address + Environment.NewLine;
}
我们感兴趣的第二个问题是电子邮件地址。 如果用户是 Active Directory 用户,那么 recipientitem.address
将如下所示:/o=organizationg/ou=exchange administrative group /cn=recipients/cn=xxxxxxxxxx。
这是用户 LDAP 属性之一,名为 legacyexchangedn
。
因此,如果 recipinetitem.address
包含“CN=
”,那么必须从 LDAP 服务器获取电子邮件地址。 如果我们已登录到域,则 ldapuser
和 ldapserver
字段可以为空。 这是一个基本的简单 LDAP 查询。 您会在很多很多页面上遇到类似的情况。
private static string getLDAPvalue(string ldapserver, string
legacyexchangedn, string ldapuser, string ldappasword)
{
//default LDAP path is the root of LDAP tree
string strLDAPPath = "";
string x = "";
// The result of the LDAP search will be a Directory Entry
DirectoryEntry objSearchRoot;
try
{
//Using the LDAP protocol. Set the default path to the root.
//The LDAP server is one of domain controllers,
//but better using the fullname of Windows domain.
//i.e. ldapserver = windowsdomainname.organization.any
strLDAPPath = "LDAP://" + ldapserver;
//If You are logged into a Windows domain,
//the LDAP user, and password can be empty.
//Windows will use the default logged in user account.
if (ldapuser == "")
{
objSearchRoot = new DirectoryEntry(strLDAPPath);
}
else
{
//When You not logged into a domain
objSearchRoot = new DirectoryEntry(strLDAPPath, ldapuser,
ldappasword, AuthenticationTypes.ReadonlyServer);
}
//First create a directorysearcher object
DirectorySearcher objDirectorySearcher = new DirectorySearcher(objSearchRoot);
// Use filter for legacyexchangedn in this example.
//When You wants to filter for username then use this:
// objDirectorySearcher.Filter =
// "(&(objectClass=person)(samaccountname=" + username + "))
objDirectorySearcher.Filter =
"(&(objectClass=person)(legacyexchangedn=" + legacyexchangedn + "))";
//We want to get the email =>in LDAP this is the mail property.
objDirectorySearcher.PropertiesToLoad.Add("mail");
SearchResult objSearchResult;
//We will get only one result, because the legacyexchangedn
//is unique. If You filter for field has many results
//You have to use objDirectorySearcher.FindAll();
objSearchResult = objDirectorySearcher.FindOne();
//If we have valid result... This is not necessary.
//If recipient item contains legacyexchangedn field, then impossible
//the empty objSearchResult object.
if (!(objSearchResult == null))
{
ResultPropertyValueCollection objValueCollection;
objValueCollection = objSearchResult.Properties["mail"];
//It is not necessary as well.. The objSearchResult
//has only one "mail" property
foreach (object objPropertyValue in objValueCollection)
{
x = x + objPropertyValue.ToString();
}
}
else
{
x = "No hits";
}
//Dispose, and close LDAP query
objDirectorySearcher.CacheResults = false;
objDirectorySearcher.Dispose();
}
//When something is wrong. The common problem,
//when LDAP server is unreachable, in time of query.
catch (Exception ex)
{
x = "";
MessageBox.Show(ex.Message);
}
return x;
}
最后,这是从 WMI 获取默认域的简单查询。 我多年前在某个地方找到了这段代码片段。
private string getdomain()
{
string domain = "";
//to make the Query object
SelectQuery query = new SelectQuery("Win32_ComputerSystem");
//Make the searcher object
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
//To get the name of the logged in domain.
foreach (ManagementObject mo in searcher.Get())
{
if ((bool)mo["partofdomain"] == true)
domain = String.Format("{0}", mo["domain"]);
}
return domain;
}
完整代码
using System;
using System.Windows.Forms;
using System.IO;
using System.DirectoryServices;
using System.Management;
namespace OutlookAddressCollector
{
public partial class Form1 : Form
{
//global variables NOT ELEGANT!!!!!!
Microsoft.Office.Interop.Outlook.Application myApp ;
Microsoft.Office.Interop.Outlook.NameSpace mapiNameSpace;
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox;
int st;
public Form1()
{
InitializeComponent();
}
// Gets users email address, when recipient
// is a member of an Active Directory (i.e. in a company)
private static string getLDAPvalue(string ldapserver,
string legacyexchangedn, string ldapuser, string ldappasword)
{
string strLDAPPath = "";
string x = "";
DirectoryEntry objSearchRoot;
try
{
strLDAPPath = "LDAP://" + ldapserver;
if (ldapuser == "")
{
objSearchRoot = new DirectoryEntry(strLDAPPath);
}
else
{
objSearchRoot = new DirectoryEntry(strLDAPPath, ldapuser,
ldappasword, AuthenticationTypes.ReadonlyServer);
}
DirectorySearcher objDirectorySearcher =
new DirectorySearcher(objSearchRoot);
objDirectorySearcher.Filter =
"(&(objectClass=person)(legacyexchangedn=" +
legacyexchangedn + "))";
objDirectorySearcher.PropertiesToLoad.Add("mail");
SearchResult objSearchResult;
objSearchResult = objDirectorySearcher.FindOne();
if (!(objSearchResult == null))
{
ResultPropertyValueCollection objValueCollection;
objValueCollection = objSearchResult.Properties["mail"];
foreach (object objPropertyValue in objValueCollection)
{
x = x + objPropertyValue.ToString();
}
}
else
{
x = "No hits";
}
objDirectorySearcher.CacheResults = false;
objDirectorySearcher.Dispose();
}
catch (Exception ex)
{
x = "";
MessageBox.Show(ex.Message);
}
return x;
}
//Refresh datagrid
private void Refresh(int start)
{
try
{
if (myInbox.Items.Count == 0)
{
throw new System.Exception("There are no emails in your Inbox.");
}
int db = 10;
if (start - 10 < 0) db = start;
if (start > myInbox.Items.Count) start = myInbox.Items.Count;
dataGridView1.Rows.Clear();
int x = 0;
for (int i = start; i > start - db; i--)
{
x = dataGridView1.Rows.Add();
dataGridView1.Rows[x].Cells[0].Value = i.ToString();
dataGridView1.Rows[x].Cells[1].Value =
((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[i]).SenderName;
dataGridView1.Rows[x].Cells[2].Value =
((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[i]).Subject;
dataGridView1.Rows[x].Cells[3].Value =
String.Format("{0:yyyy.MM.dd HH:mm:ss}",
((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[i]).ReceivedTime);
x++;
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button2_Click(object sender, EventArgs e)
{
Refresh(st);
}
// Gets computers domain
private string getdomain()
{
string domain = "";
SelectQuery query = new SelectQuery("Win32_ComputerSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject mo in searcher.Get())
{
if ((bool)mo["partofdomain"] == true)
domain = String.Format("{0}", mo["domain"]);
}
return domain;
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
textBox2.Text = getdomain();
myApp = new Microsoft.Office.Interop.Outlook.ApplicationClass();
mapiNameSpace = myApp.GetNamespace("MAPI");
myInbox = mapiNameSpace.GetDefaultFolder(
Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
st = myInbox.Items.Count;
Refresh(st);
dataGridView1_CellClick(sender, null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button3_Click(object sender, EventArgs e)
{
st = st - 10;
if (st < 10) st = 10;
Refresh(st);
dataGridView1_CellClick(sender, null);
}
public void button4_Click(object sender, EventArgs e)
{
st = st + 10;
if (st > myInbox.Items.Count) st = myInbox.Items.Count;
Refresh(st);
dataGridView1_CellClick(sender, null);
}
private void button5_Click(object sender, EventArgs e)
{
st = myInbox.Items.Count;
Refresh(st);
dataGridView1_CellClick(sender, null);
}
private void button6_Click(object sender, EventArgs e)
{
st = 10;
Refresh(st);
dataGridView1_CellClick(sender, null);
}
//Saves attachments
private void button1_Click(object sender, EventArgs e)
{
int rownum = dataGridView1.CurrentCell.RowIndex;
int index = Convert.ToInt32(dataGridView1.Rows[rownum].Cells[0].Value);
try
{
if (((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[1]).Attachments.Count == 0)
{
throw new System.Exception("There aren't any attachment");
}
string foldername = "";
DialogResult result = this.folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
foldername = this.folderBrowserDialog1.SelectedPath;
}
if (foldername == "")
{
throw new System.Exception("Folder name is empty");
}
foreach (Microsoft.Office.Interop.Outlook.Attachment item in
((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[1]).Attachments)
{
string filename = Path.Combine(foldername, item.FileName);
item.SaveAsFile(filename);
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// When You click on a datagrid cell.
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
int rownum = dataGridView1.CurrentCell.RowIndex;
int index = Convert.ToInt32(dataGridView1.Rows[rownum].Cells[0].Value);
string sendermail = "";
textBox1.Text = ((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).Subject;
richTextBox1.Text = ((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).Body;
textBox3.Text = ((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).SenderName;
sendermail = ((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).SenderEmailAddress;
if (sendermail.Contains("CN="))
{
textBox4.Text = getLDAPvalue
(textBox2.Text, sendermail, textBox8.Text, textBox9.Text);
}
else
{
textBox4.Text = sendermail;
}
textBox5.Text = ((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).To;
textBox6.Text = ((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).CC;
Microsoft.Office.Interop.Outlook.Recipients recipients =
((Microsoft.Office.Interop.Outlook.MailItem)
myInbox.Items[index]).Recipients;
textBox7.Text = "";
foreach (Microsoft.Office.Interop.Outlook.Recipient item in recipients)
{
if (item.Address.Contains("CN="))
{
textBox7.Text = textBox7.Text +getLDAPvalue(textBox2.Text,
item.Address, textBox8.Text, textBox9.Text) + Environment.NewLine;
}
else
{
textBox7.Text = textBox7.Text + item.Address + Environment.NewLine;
}
}
}
}
}
历史
- 版本 1.0