How does one get the inbox folder and item count? - c#

I finally managed to work out how to create item counts of the inbox, sent items, calendar & contacts but I'm having problems with the folder count.
Let say I have 5 folders created in my mailbox and 2 sub folders in each folder. When I run this code, it counts 5 folders instead of all folders and sub folders which would equal 15 folder.
I'm guessing a foreach statement or something but I still a newb :-)
#region Run Item Count
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
private void btnRunItemCount_Click(object sender, EventArgs e)
{
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
MAPIFolder oInbox = this.ns.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
tbInboxItemCount.Text = oInbox.Items.Count.ToString();
MAPIFolder oSentItems = this.ns.GetDefaultFolder(OlDefaultFolders.olFolderSentMail);
tbSentMailItemCount.Text = oSentItems.Items.Count.ToString();
MAPIFolder oCalendar = this.ns.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
tbCalendarItemCount.Text = oCalendar.Items.Count.ToString();
MAPIFolder oContacts = this.ns.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
tbContactsItemCount.Text = oContacts.Items.Count.ToString();
MAPIFolder oFolder = this.ns.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
tbFolderItemCount.Text = oInbox.Folders.Count.ToString();
}
#endregion
Thanks for any help received! Dan

You will need to recursively process all folders starting with Namespace.Folders.
Off the top of my head:
int allitems = CountFolders(ns.Folders);
...
private int CountFolders(Folders folders)
{
int c = folders.count;
foreach (MAPIFolder folder in folders)
{
c += CountFolders(folder.Folders);
}
return c;
}

Related

Connecting Outlook into Visual Studio

New to programming and trying to create this project for work. I have a text file inputted that has a list of usernames. I want the code to take the usernames from the text file and look them up in Outlook to give me a "true" or "false" if there is a match for the user in the system. How do I connect Outlook to the code with MAPI or an API? The code I have so far is below.
namespace QC_OUTLOOK
{
internal class Program
{
private static object MessageBox;
private static object objFile;
private static int i;
private static object Strings;
private static object response;
static int Main(string[] args)
{
string filePath = #"C:\Users\Documents\QC\User_list.txt";
// string[] lines = File.ReadAllLines(filePath);
List<string> lines = new List<string>();
lines = File.ReadAllLines(filePath).ToList();
using (StreamWriter streamWriter = File.CreateText(filePath));
foreach (String line in lines)
{
Console.WriteLine(line);
}
Console.ReadLine();
{
Outlook._Application oApp = new OutLook.Application();
//Get MAPI namespace
Outlook.AddressLists oNS = oNS.AddressLists;
Outlook.AddressList oGal = oALs.Item("Global Address List");
//Get all entries
Outlook.AddressEntries oEntries = oGal.AddressEntries;
// Get first user found
Outlook.AddressEntry oEntry = oEntries.GetFirst();
Outlook_UserName_Output = "";
response = sa.GetAllUsers;
Console.WriteLine(response);
//
UserCount = 0;
UsersFound = 0;
LastNameMatches = 0;
InactiveUser_Count = 0;
Inconsistent_EmailAddrs = 0;
GIS_UserCount = 0;
TodaysDate = DateTime.Today;
object value = objFile.WriteLine("Date:" + TodaysDate);
object value1 = objFile.WriteLine("QC_UserID, QC_FullName, OutLook_Last_Name, OutLook_First_Name");
for (i = 1; i <= Strings.Len(response) ; i++);
Outlook.Application oApp = new Outlook.Application();
// Get the MAPI namespace.
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
oNS.Logon(Missing.Value, Missing.Value, false, true);
Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
}
DataTable dt = new DataTable();
dt.Columns.Add("FirstName");
dt.Columns.Add("LastName");
Microsoft.Office.Interop.Outlook.Items OutlookItems;
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MAPIFolder Folder_Contacts = (MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
OutlookItems = Folder_Contacts.Items;
foreach (var item in OutlookItems)
{
var contact = item as ContactItem;
if (contact != null)
{
DataRow dr = dt.NewRow();
dr["FirstName"] = contact.FirstName;
dr["LastName"] = contact.LastName;
dt.Rows.Add(dr);
}
First of all, creating a new Outlook Application instance multiple times in the code is not the best way to go:
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Outlook is a singleton. You can't run two instances of Outlook on the system at the same time. So, I'd suggest keeping the application object and re-use it where possible.
Iterating over all items in the Outlook folder is not really a good idea. Instead, use the Find/FindNext or Restrict methods of the Items class. Read more about these methods in the following articles:
How To: Retrieve Outlook Contact items using Restrict method
How To: Use Find and FindNext to retrieve Outlook Contact items
But better is to use the NameSpace.CreateRecipient method which creates a Recipient object and can be used to verify a given name against an address book. The Recipient.Resolve method attempts to resolve a created Recipient object against the Address Book. That's exactly what you are looking for!

Processing a Outlook calendars own formula items

I have to process Outlook calendar items in a C# application. My Problem: I have a self constructed Formula for Outlook Appointments and I whant to access to the data of this own Formula Region (created in the developer tab/Formulas).
Here my code without using the own fields:
Microsoft.Office.Interop.Outlook.Application oApp = null;
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;
oApp = new Microsoft.Office.Interop.Outlook.Application[];
mapiNamespace = oApp.GetNamespace("MAPI");
CalendarFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
outlookCalendarItems = CalendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true;
oApp = new Microsoft.Office.Interop.Outlook.Application[];
mapiNamespace = oApp.GetNamespace("MAPI");
foreach (Folder fold in mapiNamespace.Folders) {
if (folder.DefaultItemType == OlItemType.olAppointmentItem) {
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in folder.Items) {
//Do stuff with the item (Subject, Location, Start, End, Categories)
//Also whant to access to item fields defined in own Formular here
}
}
}
The code works fine, but I don't know how to access the data of my selfconstructed formula fields.
Any ideas or different solutions?
Ok, found the property containing the Information:
For Each p As Microsoft.Office.Interop.Outlook.ItemProperty In item.ItemProperties
Try
MsgBox(p.Name & " " & p.Value.ToString())
'One of thousends of attributes
Catch e As System.Exception
End Try
Next

Loading items like calendar and contacts from public folder

I've searched around looking for a way to load a calendar/contacts item from the public folder. Through Outlook it's simple, you go to the public folders and just drag-n-drop it in. I've gotten to the point accessing the calendar, but I'm not sure how to load it into Outlook through C#.
private void AddCalendar()
{
Outlook._NameSpace session = null;
Outlook.MAPIFolder publicFolders = null;
OUtlook.MAPIFolder allPublicFolders = null;
Outlook.MAPIFolder seCalendar = null;
try
{
session = _thisApp.GetNamespace("MAPI");
publicFolders = session.Folders["Public Folders"];
allPublicFolders = publicFolders.Folders["All Public Folders"];
seCalendar = allPublicFolders.Folders["SE Calendar"];
// ????
// profit
}
finally
{
//Release Items
}
}
Below is a picture of what I'm trying to do. You normally just start with your own calendar, I'm trying to load a company calendar that is in the public folders.
Loop through the items in the MAPIFolder.Items collection. In your particular case, the items will be AppointmentItem, ContactItem, and DistListItem.
Outlook.Items items = seCalendar.Items;
for (int i = 1; i <= items.Count; i++)
{
object item = items[i];
Outlook.AppointmentItem appt = item as Outlook.AppointmentItem;
if (apt != null)
{
MessageBox.Show(appt.Subject);
Marshal.ReleaseComObject(appt);
}
Marshal.ReleaseComObject(item);
}

Collect Directory and Sub Directories with mapping and index in a List<>

I want to collect the directory listing in a collection(a List<> perhaps)
my directory structure is like :
MainFolder\ParentFolder1\SubFolder1
\SubFolder2
\SubFolder3
MainFolder\ParentFolder2\SubFolder1
\SubFolder2
\SubFolder3
I want to list all the subfolders mapped to their parent directories.
Also, the records will have index of ParentFolder 0-n in MainFolder and index of SubFolder 0-n in each ParentFolder.
I did tried below but not yet achieved
lstParents = (from f in Directory.GetDirectories(MainFolder)
select Data
{
parent =f
}).ToList();
var lstSubDir = (from f in lstParents.Select(m => Directory.GetDirectories(m.parent).ToList());
You can use this overload of the GetDirectories method to find all subdirectories recursively:
var mainDirectory = new DirectoryInfo(#"C:\temp\MainFolder");
var subDirectories = mainDirectory.GetDirectories("*", SearchOption.AllDirectories);
Then you can map them into pairs of directory/parent like this:
var mappedDirectories = subDirectories.Select(sd => new { Parent=sd.Parent, Child=sd });
If you want to exclude the first level of subdirectories (ParentFolder1 and ParentFolder2, in your case) you can filter them like this:
var mappedDirectories = subDirectories
.Where(sd => sd.Parent.FullName != mainDirectory.FullName)
.Select(sd => new { Parent=sd.Parent, Child=sd });
EDIT after you've asked for indices:
You stated, that you'll always only have a nesting level of 2, the following piece of code will not work for deeper directory structures.
var mainDirectory = new DirectoryInfo(#"C:\temp\MainFolder");
var firstLevelDirectories = mainDirectory.GetDirectories().Select((f1,i) => new {
Parent = f1,
ParentIndex = i
});
var secondLevelDirectories = firstLevelDirectories
.SelectMany(f1 => f1.Parent.GetDirectories().Select((f2,i) => new {
f1.Parent,
f1.ParentIndex,
Child = f2,
ChildIndex = i
} ));
This will give you a list of records, each containing
the parent directory,
the parent directory index,
the child directory and
the child directory index within its parent.
Try this recursive algorithm.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Folders folders = new Folders(#"c:\temp", null);
Console.ReadLine();
}
}
public class Folders
{
public string path { get; set; }
List<string> files = new List<string>();
List<Folders> folders = new List<Folders>();
Folders parent = null;
public Folders(string path, Folders parent)
{
this.parent = parent;
this.path = path;
foreach (string folderPath in Directory.GetDirectories(path))
{
Folders newFolder = new Folders(folderPath, this);
folders.Add(newFolder);
}
files = Directory.GetFiles(path).ToList();
int pathlength = path.Length;
Boolean first = true;
Console.Write(path);
if (files.Count == 0) Console.WriteLine();
foreach (string file in files)
{
string shortname = file.Substring(file.LastIndexOf("\\") + 1);
if (first)
{
Console.WriteLine("\\" + shortname);
first = false;
}
else
{
Console.WriteLine(new string(' ', pathlength + 1) + shortname);
}
}
}
}
}
​

EWS - Access All Shared Calendars

I've got the following code:
private void ListCalendarFolders(ref List<EBCalendar> items, int offset)
{
var pageSize = 100;
var view = new FolderView(pageSize, offset, OffsetBasePoint.Beginning);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(FolderSchema.DisplayName);
view.PropertySet.Add(FolderSchema.EffectiveRights);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot, view);
foreach (Folder myFolder in findFolderResults.Folders)
{
if (myFolder is CalendarFolder)
{
var folder = myFolder as CalendarFolder;
items.Add(EBCalendar.FromEWSFolder(folder));
}
}
if (findFolderResults.MoreAvailable)
{
offset = offset + pageSize;
ListCalendarFolders(ref items, offset);
}
}
Where service is an ExchangeService instance. Unfortunately, it still lists folders that have been deleted, and it doesn't list shared calendars.
How can I get it to list all the shared calendars, and how can I get it to not include the folders that have been deleted?
By Shared Calendars do you mean the calendars under the other calendars node in Outlook ?
If so these Items are NavLinks that are stored in the Common Views folder in a Mailbox which is under the NonIPMSubtree (root) see http://msdn.microsoft.com/en-us/library/ee157359(v=exchg.80).aspx. You can use EWS to get the NavLinks from a Mailbox and use the PidTagWlinkAddressBookEID extended property to get the X500 address of the Mailbox these Links refer to and then use Resolve Name to resolve that to a SMTP Address. Then all you need to do is Bind to that folder eg
static Dictionary<string, Folder> GetSharedCalendarFolders(ExchangeService service, String mbMailboxname)
{
Dictionary<String, Folder> rtList = new System.Collections.Generic.Dictionary<string, Folder>();
FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Root, mbMailboxname);
FolderView fvFolderView = new FolderView(1000);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Common Views");
FindFoldersResults ffoldres = service.FindFolders(rfRootFolderid, sfSearchFilter, fvFolderView);
if (ffoldres.Folders.Count == 1)
{
PropertySet psPropset = new PropertySet(BasePropertySet.FirstClassProperties);
ExtendedPropertyDefinition PidTagWlinkAddressBookEID = new ExtendedPropertyDefinition(0x6854, MapiPropertyType.Binary);
ExtendedPropertyDefinition PidTagWlinkGroupName = new ExtendedPropertyDefinition(0x6851, MapiPropertyType.String);
psPropset.Add(PidTagWlinkAddressBookEID);
ItemView iv = new ItemView(1000);
iv.PropertySet = psPropset;
iv.Traversal = ItemTraversal.Associated;
SearchFilter cntSearch = new SearchFilter.IsEqualTo(PidTagWlinkGroupName, "Other Calendars");
// Can also find this using PidTagWlinkType = wblSharedFolder
FindItemsResults<Item> fiResults = ffoldres.Folders[0].FindItems(cntSearch, iv);
foreach (Item itItem in fiResults.Items)
{
try
{
object GroupName = null;
object WlinkAddressBookEID = null;
// This property will only be there in Outlook 2010 and beyond
//https://msdn.microsoft.com/en-us/library/ee220131(v=exchg.80).aspx#Appendix_A_30
if (itItem.TryGetProperty(PidTagWlinkAddressBookEID, out WlinkAddressBookEID))
{
byte[] ssStoreID = (byte[])WlinkAddressBookEID;
int leLegDnStart = 0;
// Can also extract the DN by getting the 28th(or 30th?) byte to the second to last byte
//https://msdn.microsoft.com/en-us/library/ee237564(v=exchg.80).aspx
//https://msdn.microsoft.com/en-us/library/hh354838(v=exchg.80).aspx
String lnLegDN = "";
for (int ssArraynum = (ssStoreID.Length - 2); ssArraynum != 0; ssArraynum--)
{
if (ssStoreID[ssArraynum] == 0)
{
leLegDnStart = ssArraynum;
lnLegDN = System.Text.ASCIIEncoding.ASCII.GetString(ssStoreID, leLegDnStart + 1, (ssStoreID.Length - (leLegDnStart + 2)));
ssArraynum = 1;
}
}
NameResolutionCollection ncCol = service.ResolveName(lnLegDN, ResolveNameSearchLocation.DirectoryOnly, false);
if (ncCol.Count > 0)
{
FolderId SharedCalendarId = new FolderId(WellKnownFolderName.Calendar, ncCol[0].Mailbox.Address);
Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
rtList.Add(ncCol[0].Mailbox.Address, SharedCalendaFolder);
}
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
return rtList;
}
Cheers
Glen
You need to specify a searchfilter.
this is described here, though im not sure which Schema is the correct one, my guess would be Archieved.
So you would do something like this:
SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.Archieved, false);
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot,searchFilter, view);
Glen post is perfect but binding folder gives error. However i solved this. Instead of this line:
Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
use the following line for shared folder binding
CalendarFolder calendar = CalendarFolder.Bind(service, new FolderId(WellKnownFolderName.Calendar, OwnerEmailAddress), new PropertySet());
Here OwnerEmailAddress is Email Address of Owner or you can write ncCol[0].Mailbox.Address if using Glen's code.

Categories