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.
Related
Environment: I have a windows console application and I am running the exe from command line.
Below is my code:
static void Main(string[] args)
{
CreatePSTUsingRedemption(args[0], args[1]);
}
private static void CreatePSTUsingRedemption(string messageFilePath, string pstPath)
{
RDOSession pstSession = new RDOSession();
RDOPstStore store = null;
store = pstSession.LogonPstStore(pstPath, 1, "combinedPST");
//actually there is a loop here to loop through each message files.
RDOMail rdo_Mail = pstSession.GetMessageFromMsgFile(messageFilePath);
rdo_Mail.CopyTo(store.IPMRootFolder);
rdo_Mail.Save();
store.Save();
completedCount++;
Console.WriteLine("FILES_PROCESSED:" + completedCount);
pstSession.Logoff();
}
Main purpose of this code is to create a single pst file combining email message(.msg) files.
Now when I run the exe, a pst file is created in the given location and its size keeps increasing as the code runs. After all the message files are processed application exists. There is no any error. Now, when I try to load this pst file in Outlook 2013. Pst is empty and its size is also reduced to 265KB every time. I don't think any process is using this pst because I can copy and move it anywhere I want. What might be the issue? Any suggestion, please?
UPDATE 1
private static void CreatePSTUsingRedemption(XmlNodeList nodelist, string pstPath)
{
System.Diagnostics.Debugger.Launch();
RDOSession pstSession = null;
RDOPstStore store = null;
RDOFolder folder = null;
RDOMail rdo_Mail = null;
try
{
pstSession = new RDOSession();
store = pstSession.LogonPstStore(pstPath, 1, Path.GetFileNameWithoutExtension(pstPath));
var enumerator = store.IPMRootFolder.Folders.GetEnumerator(); //DELETE DEFAULT FOLDERS
while (enumerator.MoveNext())
{
var defaultFolders = enumerator.Current as RDOFolder;
defaultFolders.Delete();
}
int completedCount = 0;
folder = store.IPMRootFolder;
foreach (XmlNode node in nodelist)
{
rdo_Mail = pstSession.GetMessageFromMsgFile(node["FullPath"].InnerText);
rdo_Mail.CopyTo(folder);
rdo_Mail.Save();
store.Save();
completedCount++;
Console.WriteLine("FILES_PROCESSED:" + completedCount);
}
}
finally
{
Marshal.ReleaseComObject(rdo_Mail);
Marshal.ReleaseComObject(folder);
Marshal.ReleaseComObject(store);
}
pstSession.Logoff();
Marshal.ReleaseComObject(pstSession);
GC.Collect();
}
Above is my code for the actual loop. I am loading all the email messages file path from an xml file. I still encounter same issue as above.
This is an indication that the PST store is not fully flushed to the disk and Outlook "fixes' the PST file by resetting it.
Try to explicitly release all Redemption objects first before logging off and call GC.Collect(). If you have a loop processing multiple files, release the message on each step of the loop.
private static void CreatePSTUsingRedemption(string messageFilePath, string pstPath)
{
RDOSession pstSession;
try
{
RDOPstStore store;
RDOFolder folder;
RDOMail rdo_Mail;
pstSession = new RDOSession();
store = pstSession.LogonPstStore(pstPath, 1, "combinedPST");
//actually there is a loop here to loop through each message files.
rdo_Mail = pstSession.GetMessageFromMsgFile(messageFilePath);
folder = store.IPMRootFolder;
rdo_Mail.CopyTo(folder);
rdo_Mail.Save();
store.Save();
completedCount++;
Console.WriteLine("FILES_PROCESSED:" + completedCount);
}
finally
{
Marshal.ReleaseComObject(rdo_Mail);
Marshal.ReleaseComObject(folder);
Marshal.ReleaseComObject(store);
}
pstSession.Logoff();
Marshal.ReleaseComObject(pstSession);
GC.Collect();
}
I am trying to simply read and print the contents of emails from a specific folder and another inbox in Outlook using C# (not my default inbox). I'm finding it difficult to find examples of this on the web and have failed on my own. I know how to print the emails of the default account as well, just not additional ones.
My code here simply iterates over a list of all the inboxes and prints their names out. The one I want to read is the first element in the collection. I appreciate any help with this issue. Thanks.
using System;
using System.Collections;
using Microsoft.Office.Interop.Outlook;
public class StorageReplies {
public static void Main() {
Application app = new Microsoft.Office.Interop.Outlook.Application();
_NameSpace ns = app.GetNamespace("MAPI");
Folders folders = ns.Folders;
foreach(MAPIFolder f in folders) {
Console.WriteLine(f.Name);
}
}
}
You could obtain the Store for each folder, and then call GetDefaultFolder method to obtain the inbox folder for the corresponding store like this:
foreach (MAPIFolder f in folders)
{
MAPIFolder inbox_folder = f.Store.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
foreach (MailItem item in inbox_folder.Items)
{
//Access item here
}
}
However, instead of doing that, it makes sense to loop through the Stores property directly like this:
Stores stores = ns.Stores;
foreach (Store store in stores)
{
MAPIFolder inbox_folder = store.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
foreach (MailItem item in inbox_folder.Items)
{
//Access item here
}
}
I develop an outlook add-in using Visual studio 2013 and Add-in express v.7.7.4087.
I have to deal with multiple email accounts (stores). Please see following snapshot and code
private void timerSendFromDraftsFolder_Tick(object sender, EventArgs e)
{
Outlook.Stores stores = null; // CC and OL accounts,
Outlook.Store store = null;
Outlook.MAPIFolder rootFolder = null;
Outlook.Folders rootFolderFolders = null;
Outlook.MAPIFolder draftsFolder = null;
Outlook.Items items = null;
Outlook.MailItem mailItem = null;
bool itemSent = true;
bool allMailItemsSent = true;
try
{
if (Helper.IsOnline())
{
Debug.DebugMessage(3, "AddinModule : timerSendFromSaleswingsFolder_Tick : Fired");
string version = OutlookApp.Version;
if (String.Compare(version, "13") > 0)
{
stores = Globals.ObjNS.Stores;
for (int i = 1; i <= stores.Count; i++)
{
try
{
store = stores[i];
string storeName = store.DisplayName;
if (store.ExchangeStoreType != Outlook.OlExchangeStoreType.olExchangePublicFolder)
{
rootFolder = store.GetRootFolder();
rootFolderFolders = rootFolder.Folders;
if (rootFolderFolders != null)
{
try
{
draftsFolder = rootFolderFolders["drafts"]; // not working for "xxxxxxx#outlook.com" type email accounts
}
catch (Exception )
{
Debug.DebugMessage(3, "AddinModule : timerSendFromSaleswingsFolder_Tick : Excep");
draftsFolder = rootFolderFolders["Drafts (This computer only)"];
}
}
I need to access the drafts folder of each mail account, but the email account of “xxxxxxx#outlook.com“ shows drafts folder as "Drafts (This computer only)" instead of "drafts".
I works fine for me. But I don’t like to introduce this to the production version. Becaues I think this will not work for non-English environments.
Can you please suggest me a solution for that
In redemption (http://www.dimastr.com/redemption/home.htm), is there a solution for that?
P.S
I have used this code in some of my projects
oFolder = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDrafts);
But it gives the drafts folder of primary mail account. In my code there is no such method for the “store” object here.
Use the GetDefaultFolder method of the Store class instead. It allows to get a Folder object that represents the default folder in the store and that is of the type specified by the FolderType argument.
This method is similar to the GetDefaultFolder method of the NameSpace object. The difference is that this method gets the default folder on the delivery store that is associated with the account, whereas NameSpace.GetDefaultFolder returns the default folder on the default store for the current profile.
The Redemption library provides the GetDefaultFolder method of the RDOStore class.
GetSharedDefaultFolder is the way to go - call Namespace.CreateRecipient / Recipient.Resolve / Namespace.GetSharedDefaultFolder.
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);
}
}
}
I am creating a pst file in Outlook using C#, and Addin express.
The new pst file ("My Inbox") should have Inbox,Sent Items, Outbox.
Outlook.Folders olFolders = olNamespace.Folders;
foreach (Outlook.MAPIFolder olTmpFolder in (IEnumerable) olFolders)
{
if(olTmpFolder.Name == "My Inbox")
{
olTmpFolder.Folders.Add("Inbox", Outlook.OlDefaultFolders.olFolderInbox);
olTmpFolder.Folders.Add("Sent", Outlook.OlDefaultFolders.olFolderSentMail);
olTmpFolder.Folders.Add("Outbox", Outlook.OlDefaultFolders.olFolderOutbox);
}
}
But I can only see the Inbox folder .
If there are better ways please let me know.
Thanks
Sujay
Try this and let me know if it works:
Outlook.Folders olFolders = olNamespace.Folders;
foreach (Outlook.MAPIFolder olTmpFolder in (IEnumerable) olFolders)
{
if(olTmpFolder.Name == "My Inbox")
{
olTmpFolder.Folders.Add("Inbox", missing) as Outlook.Folder;
olTmpFolder.Folders.Add("Sent", missing) as Outlook.Folder
olTmpFolder.Folders.Add("Outbox", missing) as Outlook.Folder
}
}