How to get folder by path in multiple Accounts Outlook c# - c#

I have 2 accounts added to outlook , two seperate pst files. You will get clear idea with image below :
First i prompt user select folders from the outlook which ones to read, image attached for better understanding:
At the end i have the folderpaths in a list, same as in the image.
Now i want to read emails only from these specific paths and send them replies or delete them, so how can i do that?How can i read the folder based on a path n such way i get the account associated with it so i can also send emails using that accounts.

Use the following code to loop through all the folders then match the path with the ones in the list.
CODE:
OutLook.Application oApp = new OutLook.Application();
OutLook.NameSpace oNS = (OutLook.NameSpace)oApp.GetNamespace("MAPI");
oNS.Logon(Missing.Value, Missing.Value, false, true);
foreach (OutLook.MAPIFolder folder in oNS.Folders)
{
string folderName = folder.Name;
GetFolders(folder);
}
public void GetFolders(MAPIFolder folder)
{
if (folder.Folders.Count == 0)
{
string path = folder.FullFolderPath;
if (foldersTocheck.Contains(path))
{
//GET EMAILS.....
foreach (OutLook.MailItem item in folder.Items)
{
Console.WriteLine(item.SenderEmailAddress + " " + item.Subject + "\n" + item.Body);
}
}
}
else
{
foreach (MAPIFolder subFolder in folder.Folders)
{
GetFolders(subFolder);
}
}
}

Related

C# Outlook Attachment.SaveAsFile fails on .msg file type

So I have the following code, which extracts all attachments from a Contact item (residing in a shared folder):
Outlook._Application objOutlook; //declare Outlook application
objOutlook = new Outlook.Application(); //create it
Outlook._NameSpace objNS = objOutlook.Session; //create new session
Outlook.MAPIFolder oAllPublicFolders; //what it says on the tin
Outlook.MAPIFolder oPublicFolders; // as above
Outlook.MAPIFolder objContacts; //as above
Outlook.Items itmsFiltered; //the filtered items list
oPublicFolders = objNS.Folders["Public Folders"];
oAllPublicFolders = oPublicFolders.Folders["All Public Folders"];
objContacts = oAllPublicFolders.Folders["Global Contacts"];
itmsFiltered = objContacts.Items.Restrict(strFilter);//restrict the search to our filter terms
for (int i = 1; i <= itmsFiltered.Count; i++) //loop through filtered items
{
var item = itmsFiltered[i];
Contact ctctNew = new Contact(); //create new contact
foreach (Outlook.Attachment oa in item.Attachments)
{ ctctNew.ImportedAttachments.Add(oa); }
lstContacts.Add(ctctNew); // add to the list that will be displayed in the OLV
}
return lstContacts;
This seems to work fine.
I then try and save these to a file thus:
if (!System.IO.Directory.Exists(strPath))
{ System.IO.Directory.CreateDirectory(strPath); }
foreach (Outlook.Attachment o in ctLoaded.ImportedAttachments)
{
string strFilePath = strPath + #"\" + o.FileName;
if (!File.Exists(strFilePath))
{
o.SaveAsFile(strPath + #"\" + o.FileName); //exception here
}
}
This last bit works fine for filetypes that are NOT .msg - i.e. it works fine for .pdf files etc; if it's an .msg file then I get the following exception:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in Event Management System.exe
Additional information: Cannot save the attachment. Could not complete the operation. One or more parameter values are not valid.
Can anyone shed any light?
Thanks
UPDATE: I've discovered that it's only some of the .msg files that fail to save; some of them work fine. It seems that files attached by certain users seem to work, and files by other users don't; I'm guessing it might be to do with how they attach them?
Also it appears that the code DOES save the file (despite throwing the exception), but it appears to be corrupted - a 3Kb .msg file appears in the relevant folder. Outlook won't open it, I just get a "Unable to read the item." messagebox from Outlook if I try to open the file.
Just as a guess, what is the value of o.FileName for a msg attachment? It is possibly not a valid file name.

The Outlook data file (.pst) failed to load for this session

i am using Microsoft.Office.Interop.Outlook Version 12.0.0.0 to read my outlook pst file but when compiler reaches this code outlookNs.AddStore(pstFilePath); it gives exception that
"The Outlook data file (.pst) failed to load for this session." i have tried outlookNs.AddStoreEx(pstFilePath); also but the error was same ....any sugession ??
using System;
using System.Collections.Generic;
using Microsoft.Office.Interop.Outlook;
namespace PSTReader {
class Program {
static void Main () {
try {
IEnumerable<MailItem> mailItems = readPst(#"C:\temp\PST\Test.pst", "Test PST");
foreach (MailItem mailItem in mailItems) {
Console.WriteLine(mailItem.SenderName + " - " + mailItem.Subject);
}
} catch (System.Exception ex) {
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
private static IEnumerable<MailItem> readPst(string pstFilePath, string pstName) {
List<MailItem> mailItems = new List<MailItem>();
Application app = new Application();
NameSpace outlookNs = app.GetNamespace("MAPI");
// Add PST file (Outlook Data File) to Default Profile
outlookNs.AddStore(pstFilePath);
MAPIFolder rootFolder = outlookNs.Stores[pstName].GetRootFolder();
// Traverse through all folders in the PST file
// TODO: This is not recursive, refactor
Folders subFolders = rootFolder.Folders;
foreach (Folder folder in subFolders) {
Items items = folder.Items;
foreach (object item in items) {
if (item is MailItem) {
MailItem mailItem = item as MailItem;
mailItems.Add(mailItem);
}
}
}
// Remove PST file from Default Profile
outlookNs.RemoveStore(rootFolder);
return mailItems;
}
}
}
I got the same issue, and the below is what I did.
When you are saying outlookNs.AddStore, you have to give path and the file name.
and then in the outlookNs.Stores, the variable pstName should have any extension as .pst, you have to remove it.
Below is the sample on how I got it worked.
public class Mail
{
public MailItem mailItem { get; set; }
public String path { get; set; }
}
public static class Mails
{
public static List<Mail> readPst(string pstFilePath, string pstName)
{
List<Mail> mail = new List<Mail>();
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
NameSpace outlookNs = app.GetNamespace("MAPI");
// Add PST file (Outlook Data File) to Default Profile
outlookNs.AddStore(pstFilePath + pstName);
string storeInfo = null;
foreach (Store store in outlookNs.Stores)
{
storeInfo = store.DisplayName;
storeInfo = store.FilePath;
storeInfo = store.StoreID;
}
MAPIFolder rootFolder = outlookNs.Stores[pstName.Substring(0,pstName.Length-4)].GetRootFolder();
// Traverse through all folders in the PST file
Folders subFolders = rootFolder.Folders;
foreach (Folder folder in subFolders)
{
ExtractItems(mail, folder);
}
// Remove PST file from Default Profile
outlookNs.RemoveStore(rootFolder);
return mail;
}
private static void ExtractItems(List<Mail> mailItems, Folder folder)
{
Items items = folder.Items;
int itemcount = items.Count;
foreach (object item in items)
{
if (item is MailItem)
{
MailItem mailItem = item as MailItem;
Mail mail = new Mail();
mail.mailItem = mailItem;
mail.path = folder.FolderPath + folder.Name;
mailItems.Add(mail);
}
}
foreach (Folder subfolder in folder.Folders)
{
ExtractItems(mailItems, subfolder);
}
}
}
Is it possible the PST is read only or already open in a another process? Outlook needs readwrite permissions to the PST file, regardless of what you intend to do with it.
I ran into this problem today! Searched high and low for an answer without success.
Eventually, we figured out that my user login credentials had read-permissions to the folder structure containing the PST file, while another user in my organization did not. She received the above error until we changed the permissions on the directory to allow read access, and the problem disappeared.
In my case, neither credentials were the issue nor that the PST file was opened in another process. I could not figure out what caused this but ...
... solution for me was to open Outlook->New Items->More Items->Outlook Data File...
In the popup, select Outlook data file (.pst) and hit OK
This will open Windows Expolorer, navigate to the location where your PST used to be created, name your PST file the way you used to name it and save it to that location. Make sure you save as type Outlook Data File (*.pst).
Restart Outlook
This should restart outlook and your PST should be loaded now. After this, I was also able to delete all from the location where my PST was located (including PST) and restarting outlook would not create it without any issues.

How to create directory and subdirectory if it does not exist in sharepoint Document Library

I have a user input as D:\Test1\Test2\Test3\Test4\a\b\c\d\file.jpg as per the user input i need to check if folder and sub folder exist in a Document Library.
i.e
DocLib>>Test1>>Test2....d i want to replicate the folder structure in Document Library, if it exist than directly read and save the file else create directory and than subdirectory and upto the level wherin file should be saved.
Can anyone help me to understand how can i go with this? I tried with creating files in local system on hard drive
static void CopyFolder(string sourceFolder, string destFolder)
{
if (!Directory.Exists(sourceFolder))
Directory.CreateDirectory(destFolder);
string[] files = Directory.GetFiles(sourceFolder);
foreach (string file in files)
{
string name = Path.GetFileName(file);
string dest = Path.Combine(destFolder, name);
File.Copy(file, dest);
}
//check folder in the source destination
string[] folders = Directory.GetDirectories(sourceFolder);
foreach (string folder in folders)
{
string name = Path.GetFileName(folder);
string dest = Path.Combine(destFolder, name);
System.IO.Directory.CreateDirectory(dest);
CopyFolder(folder, dest);
}
}
No idea how to check if directory exist and than check for subdirectory in sharepoint. i.e add a file by retaining the folder structure specified. Kindly help
To do this you will need to createthe structure of the tree path one by one: here is a short code how it can be done on the root site with UserDocument folder as a root folder:
// This will contain all information about the path
DirectoryInfo infoDir = new DirectoryInfo(#"C:\Users\Administrator\Pictures2\WallPaperHD - 078.jpg");
// Root folder passed => Default in SharePoint
if (infoDir.Parent != null)
{
// All folders are stored here
List<string> folders = new List<string>();
// Set current folder to parent
DirectoryInfo currentDir = infoDir.Parent;
do
{
// Add its name to array
folders.Add(currentDir.Name);
// Set parent of current as current if available
if (currentDir.Parent != null)
currentDir = currentDir.Parent;
}
while (currentDir.Parent != null);
// Add SP structure)
using (SPSite site = new SPSite("http://testsite.dev"))
{
SPWeb web = site.RootWeb;
// Get doc library
SPList documentLibrary = web.GetList("/UserDocuments");
// If library root exists
if (documentLibrary != null)
{
string folderUrl = "/UserDocuments/";
for (int i = folders.Count - 1; i >= 0; i--)
{
string folder = folders[i];
SPFolder newFolder = site.RootWeb.GetFolder(folderUrl + folder);
if (!newFolder.Exists)
{
site.RootWeb.Folders.Add(folderUrl + folder);
// Save changes
site.RootWeb.Update();
folderUrl += folder + "/";
}
}
}
}
}
This will create the same structure of folders on the SharePoint side as it was specified in the path passed by user.
After this all you need is to save file in the specified folder.
Hope it helps,
Andrew

Copy Calendar Items from Shared Calendar to Personal Calendar with Outlook API

I am in the process of writing an app that will use the Outlook API to copy Calendar Items from a shared calendar to my personal calendar. Here is what I have so far...
using Outlook = Microsoft.Office.Interop.Outlook;
public Outlook.Items GetPublicEntries(string calendar)
{
Microsoft.Office.Interop.Outlook.Items CalendarFolderItems = null;
Outlook.Application oApp;
oApp = new Outlook.Application();
Outlook.NameSpace oNS = oApp.GetNamespace("MAPI");
//oNS.Logon(Missing.Value, Missing.Value, true, true);
Outlook.Recipient oRecip = (Outlook.Recipient)oNS.CreateRecipient(calendar);
Outlook.MAPIFolder usersCalendarFolder = (Outlook.MAPIFolder)oNS.GetSharedDefaultFolder(oRecip, Outlook.OlDefaultFolders.olFolderCalendar);
CalendarFolderItems = usersCalendarFolder.Items;
return CalendarFolderItems;
}
static void Main(string[] args)
{
String[] Cals = { "Appointments","Deadlines","Hearings"};
foreach (string cal in Cals)
{
CalendarItems calobj = new CalendarItems();
Outlook.Items calobjs = calobj.GetPublicEntries(cal);
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in calobjs)
{
try
{
Console.WriteLine(item.Subject + " -> " + item.Start.ToLongDateString() + " - " + item.GlobalAppointmentID);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Console.ReadKey();
}
}
I am able to return a list of items from the three calendars, but now I need to copy them to my personal calendar and that is where I am stuck. Anyone know how to go about doing this?
Thanks!
Tony
Outlook will not let you copy directly to a specified folder (unlike AppointmentItem.Move() which takes a MAPIFolder object as a parameter) - use AppointmentItem.Copy, followed by AppointmentItem.Move:
AppointmentItem copiedItem = Item.Copy();
AppointmentItem newItem = copiedItem.Move(YourDestinationFolder);
newItem.Save();
Beware that Outlook will wipe out the global appointment id when you call Copy() - this means message updates, even if they come directly to your Inbox, will not find the appointment.
You can avoid the intermediary step if you use Redemption (I am its author) - its RDOAppointmentItem (derived from the RDOMail object) lets you pass the target folder when calling CopyTo().

How to get all folder AND items from a sharepoint list?

I have a list containing folders and items. The folders are a specific content type based on folder, but with properties.
A folder can contain subfolders and subitems. A subfolder can contain sub-subfolders and so on. I already managed to get all items and folders using this way:
void TraverseList(SPList list)
{
Trace.WriteLine("Traversing list: " + list.Title);
Trace.WriteLine("Base type: " + list.BaseType.ToString());
TraverseListFolder(list.RootFolder);
}
void TraverseListFolder(SPFolder folder)
{
SPQuery qry = new SPQuery();
qry.Folder = folder;
Trace.WriteLine("Foldername: " + folder.Name);
SPWeb web = null;
try
{
web = folder.ParentWeb;
SPListItemCollection ic = web.Lists[folder.ParentListId].GetItems(qry);
foreach (SPListItem subitem in ic)
{
SPFieldLookupValue temp = new SPFieldLookupValue(subitem["TargetPage"].ToString());
Trace.WriteLine("TargetPage: " + temp);
Trace.WriteLine("ItemName: " + subitem.Name);
if (subitem.Folder != null)
{
TraverseListFolder(subitem.Folder);
}
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw;
}
finally
{
if (web != null)
{
web.Dispose();
}
}
}
The problem in this solution is that I have to send a new query for every folder, which is getting imperformant when the list is growing. Is there a way to get the whole list with one call, without loosing the folder/item structure?
Thank you for reading this!
Edit: It's not a requirement to use CAML. But there is a restriction I forgot: I'm not able to use webservices, due to customer restrictions.
Fetch the root and use
qry.ViewAttributes = "Scope='RecursiveAll'";
See also: Query to get all items in a list including items in the sub folders in SharePoint
And: http://www.ktskumar.com/blog/2009/07/retrieve-all-folders-from-list/
HTH
Alex
query.ViewAttributes="Scope='RecursiveAll'";

Categories