I have been trying to find a way to add a folder to a pst file from c#
I have tried a whole bunch of code to try and get this to work and this is the one that seems to be most likly to be correct (as it is whats on the MSDN) but still does not work
Main {
Outlook._Application OutlookObject = new Outlook.Application();
Outlook.Store NewPst = null;
// create the pst file
string pstlocation = "C:\\Users\\Test\\Desktop\\PST\\Test.pst";
try
{
OutlookObject.Session.AddStore(pstlocation);
foreach (Outlook.Store store in OutlookObject.Session.Stores)
{
if (store.FilePath == pstlocation)
{
// now have a referance to the new pst file
NewPst = store;
Console.WriteLine("The Pst has been created");
}
}
}
catch
{ }
// create a folder or subfoler in pst
Outlook.MAPIFolder NewFolder;
NewFolder = NewPst.Session.Folders.Add("New Test Folder", Type.Missing);
}
This code creates a new PST File and then trys to add a folder to it however the last line of code:
New NewFolder = NewPst.Session.Folders.Add("New Test Folder", Type.Missing);
Gets the error "The operation failed." and "Invalid Cast Exception" can some one point out what i am doing wrong
Thanks in advance
You need to use Store.GetRootFolder() to get a handle to the root folder of that store (not Store.Session). So you would use:
// create a folder or subfolder in pst
Outlook.MAPIFolder pstRootFolder = NewPst.GetRootFolder();
Outlook.MAPIFolder NewFolder = pstRootFolder.Folders.Add("New Test Folder");
I recommend bookmarking both of the following: The PIA documentation isn't always complete, so it's worth checking out the COM documentation as well for complete class and member info.
(.NET): Outlook 2007 Primary Interop Assembly Reference
(COM): Outlook Object Model Reference
Related
I'm currently working on a project where I need to get Information from shared contacts (name, mailadress, etc) to compare multiple shared folders and find duplicate entries.
I'm coding in Visual Studio 2015. The program is just a console Application that creates an excel sheet, where the duplicate contacts are marked.
The Exchange Server is 2010 SP1.
The contacts are shared via E-Mail.
I have no problem to get acces to my own contacts. But I can't get to the folders that are shared to me.
I tried to follow this Guide.
But unfortunately this line gives me a nullpointer exception.
NameResolutionCollection ncCol = service.ResolveName(lnLegDN, ResolveNameSearchLocation.DirectoryOnly, true);
if (ncCol.Count > 0)
And further on I don't really understand what this part is supposed to to anyways, so I can't really fix it. It's my first time working with the EWS Managed API.
After changing the code I am able to get acces to the contacts folder from another mailbox. But that is not the folder that is shared to me.
So my question is, how can I get a contactsfolder that is named "CheckForDuplicates" for example. Is there a way?
Here is the code I changed in the above example. I'm getting the name of the mail box owner and than look for their contacts. After that I call a routine that gets the needed information from all contacts within that folder.
foreach (Item itItem in fiResults.Items)
{
object WlinkStoreEntryId = null;
if (itItem.TryGetProperty(PidTagWlinkStoreEntryId, out WlinkStoreEntryId))
{
string lookup = itItem.Subject;
string[] lookupArr = lookup.Trim().Split(new Char[] {'-'});
NameResolutionCollection ncCol = service.ResolveName(lookupArr[0], ResolveNameSearchLocation.DirectoryOnly, true);
if (ncCol.Count > 0)
{
try
{
Console.WriteLine(itItem.Subject);
FolderId SharedContactsId = new FolderId(WellKnownFolderName.Contacts, ncCol[0].Mailbox.Address);
Folder SharedContactFolder = Folder.Bind(service, SharedContactsId);
rtList.Add(ncCol[0].Mailbox.Address, SharedContactFolder);
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
}
I found the solution.
And it's way easier than expected.
I realized that I should look for Folders in the WellKnownFolderName.Root and not in WellKnownFolderName.Contacts.
Because the WellKnownFolderName.Contacts is reserved for the Contacts-Folder. And not like I thought for all contactfolders.
FolderId sharedRootFolderid = new FolderId(WellKnownFolderName.Root, ncCol[0].Mailbox.Address);
FolderView sharedFolderView = new FolderView(1000);
sharedFolderView .PropertySet = new PropertySet(BasePropertySet.IdOnly);
sharedFolderView .PropertySet.Add(FolderSchema.DisplayName);
sharedFolderView .Traversal = FolderTraversal.Deep;
SearchFilter testSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "CheckForDuplicates");
FindFoldersResults sharedContacts = service.FindFolders(sharedRootFolderid , testSearchFilter, sharedFolderView);
And that's already it.
When I Use OutlookSpy to get the EntryIDs from MailItems in a particular folder and supply them to the following code:
Outlook.Application myApp = new Outlook.ApplicationClass();
Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
try
{
object obj = mapiNameSpace.GetItemFromID(sEntryID);
if (obj is Outlook.MailItem)
{
var getItem = (Outlook.MailItem)mapiNameSpace.GetItemFromID(sEntryID);
getItem.Display();
}
}
catch (Exception Ex)
{
Global.Common.LogError("Error accessing MailItem", Ex, "EntryID " + sEntryID + " not found in " + sFolder, "Warning");
}
I get unknown messaging errors for some EntryID values and successful display of the messages in Outlook with others. Can anyone suggest what attributes the MailItems might have which will affect whether I can display them successfully using GetItemFromID or any other method of displaying all messages by EntryID reliably?
Was the message store where the message resides touched in the active Outlook session? The way MAPI providers work, when a provider is loaded by MAPI, it registers the set of entry id guids (bytes 5-20 in the entry id) that it will handle. If the particular PST store has not been touched in the current session, MAPI does not know anything about its entry ids.
You can either access all the stores in the current session first (to make sure MAPI knows about their entry ids) or use the store entry id (second parameter, optional) when calling GetItemFromId - this way Outlook will open the store first, then ask the store to open the item. You can also call Namespace.AddStore / AddStoreEx to load the given PST file if it is not already in the current profile.
You might also want to log the exception details (Ex.Message) in your exception handler.
Thanks to all the respondents - this explains why sometimes particular messages would open and sometimes they would not. By getting the StoreId using the following code:
Outlook.Application myApp = new Outlook.ApplicationClass();
Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Object oStoreID = Common.GetFolder(myApp, sFolder).StoreID;
try
{
object obj = mapiNameSpace.GetItemFromID(sEntryID,oStoreID);
if (obj is Outlook.MailItem)
{
Outlook.MailItem getItem = (Outlook.MailItem)mapiNameSpace.GetItemFromID(sEntryID,oStoreID);
getItem.Display();
}
}
Where
public static Outlook.Folder GetFolder(Outlook.Application App, string folderPath)
{
Outlook.Folder folder;
string backslash = #"\";
try
{
if (folderPath.StartsWith(#"\\"))
{
folderPath = folderPath.Remove(0, 2);
}
String[] folders =
folderPath.Split(backslash.ToCharArray());
folder =
App.Session.Folders[folders[0]]
as Outlook.Folder;
if (folder != null)
{
for (int i = 1; i <= folders.GetUpperBound(0); i++)
{
Outlook.Folders subFolders = folder.Folders;
folder = subFolders[folders[i]]
as Outlook.Folder;
if (folder == null)
{
return null;
}
}
}
return folder;
}
catch { return null; }
}
All MailItems now display in Outlook.
I'll just throw this in here for posterity-- Outlook 2002 requires that the entry ID supplied to GetItemFromID use upper-case hex characters.
My application is supposed to send some emails to some destination. After that operation I would like to automatically move sent mails to specific folder ( based on the document type that is in the mail attachment ). If the folder doesn't exist then the program has to create it and then move the mail to the newly created folder. The issue is that after I create a new folder and succcesfully move the mail to it for the first time, then when i sent anothe mails that are supposed to be moved to the said folder the program doesn't see the folder. In fact the Folders method doesn't return any folders at all.
frankly, im out of ideas whats wrong.
when checking in the debugger it says that parentFolder.Folders "Enumeration yielded no results"
I am not sure if I should do anything more after creating the folder in the method createFolder ( ie. something like, update folders list... )
here is my code:
public void moveEmails(string itemType, Boolean itemSent, Outlook.MailItem objMail)
{
Outlook.MAPIFolder folderParent = objMail.Parent as Outlook.MAPIFolder;
Outlook.Folders folders;
Boolean notMoved = true;
objMail.UserProperties.Add("TransferredBy", Outlook.OlUserPropertyType.olText, true, Outlook.OlUserPropertyType.olText);
objMail.UserProperties["TransferredBy"].Value = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
objMail.Save();
if (folderParent.Name != "Inbox")
folderParent = digForInbox(folderParent);
folders = folderParent.Folders;
if (!itemSent)
itemType = "NOT DELIVERED";
foreach (Outlook.MAPIFolder folder in folders)
{
if (folder.Name == itemType)
{
objMail.Move(folder);
notMoved = false;
}
}
if (notMoved)
createFolder(itemType,objMail, folderParent);
}
public void createFolder(string itemType, Outlook.MailItem objMail, Outlook.MAPIFolder folderParent)
{
Outlook.MAPIFolder folderNew;
folderNew = folderParent.Folders.Add( itemType, Outlook.OlDefaultFolders.olFolderInbox ) as Outlook.MAPIFolder;
objMail.Move(folderNew);
}
private Outlook.MAPIFolder digForInbox(Outlook.MAPIFolder folder)
{
Boolean isNotInbox = true;
while(isNotInbox)
{
if(folder.Name != "Inbox")
{
folder = folder.Parent as Outlook.MAPIFolder;
}
else
{
isNotInbox = false;
}
}
return folder;
}
I have found the answer to my question:
https://social.msdn.microsoft.com/forums/windows/en-us/180c000c-524a-45dd-88fe-88b470be3597/accessing-subfolders-within-shared-mailbox?forum=outlookdev
the issue was similar to the one in the link. I didnt imagine that because my mailboxes are mainly shared ones that would affect it in any other way than performance (due to connecting to the exchange server )
Posting this as an answer
I'd suggest using the SaveSentMessageFolder property of the MailItem class. It allows to set a Folder object that represents the folder in which a copy of the e-mail message will be saved after being sent. Also you may find the following articles helpful:
How To: Change an Outlook e-mail message before sending using C# or VB.NET
How To: Create a new folder in Outlook
i´m currently working on a programm which updates templates on our companies Team Foundation Server. I am having those new templates locally on my disk and want to replace the existing ones on the server. I was trying different approaches and this is my newest version. The problem is that either
the new file is "in use" when accessing it through coding in c#(while not in use when i try to replace it in runtime using the normal explorer).
the replacement is not appearing in the pending changes, the pendingChanges array is initial.
using (var tfs = TeamFoundationServerFactory.GetServer("myserver"))
{
var versionControlServer = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;
// Create a new workspace for the currently authenticated user.
var workspace = versionControlServer.CreateWorkspace("Temporary Workspace", versionControlServer.AuthorizedUser);
try
{
// Check if a mapping already exists.
var workingFolder = new WorkingFolder("$serverpath", #"c:\tempFolder");
// Create the mapping (if it exists already, it just overides it, that is fine).
workspace.CreateMapping(workingFolder);
workspace.Get(VersionSpec.Latest, GetOptions.GetAll);
string[] paths = new string[1];
paths[0] = "test.pdf";
workspace.PendEdit(paths, RecursionType.Full, null, LockLevel.None);
// Go through the folder structure defined and create it locally, then check in the changes.
CreateFolderStructure(workspace, workingFolder.LocalItem);
// Check in the changes made.
int a = workspace.CheckIn(workspace.GetPendingChanges(), "This is my comment");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Cleanup the workspace.
workspace.Delete();
// Remove the temp folder used.
Directory.Delete(#"C:\tempFolder", true);
}
}
}
static void CreateFolderStructure(Workspace workspace, string initialPath)
{
workspace.PendDelete("$serverpath/test.pdf", RecursionType.None);
File.Copy(#"C:\test\testnew.pdf", #"C:\tempfolder\test", true);
workspace.PendAdd(#"C:\tempfolder\test.pdf");
}
I found a solution to the problem. The workspace which was used by "authorizedUser" was obviously not enough.. I found out that a need a TeamFoundationIdentity to do it. Here is a guide on how to fix the issue.
http://blogs.msdn.com/b/taylaf/archive/2010/03/29/using-tfs-impersonation-with-the-version-control-client-apis.aspx
Hello I'd like to create a Outlook.MailItem ( I believe ) from an existing one located on disk. I have the path stored in a string, and would like to access to save the body and attachments from it.
I can't seem to figure out how to open it in c# and access it.
currently I have something along the lines of
where fl evaluates out to something like "C:\users\msgs\email.msg"
Thanks for the time
Outlook.Application app = new Outlook.Application();
try
{
foreach (String fl in Directory.GetFiles(docInfo.LocalPath + _preprocessorDirectory))
{
if (Regex.IsMatch(fl.Trim(), _regex, RegexOptions.IgnoreCase))
{
Outlook.MailItem email = new Outlook.MailItem(fl);
SaveAttachments(email);
SaveBody(email);
}
}
}
catch (Exception ex)
{
logger.Error("Error in Process for document " + docInfo.OriginalPath, ex);
callback.Invoke(docInfo, false);
}
return false;
To open an item in outlook try:
var email = (Outlook.MailItem)app.Session.OpenSharedItem(fl)
From there, you can access the Attachments property and Body property as well.
Also, as I mentioned in my comment if the Regex.IsMatch is to determing the file extension, use Path.GetExtension() instead
I used this NuGet package: https://www.nuget.org/packages/MSGReader/
Seems to work fine. I prefer it to the MS OutlookApi library because it doesn't require Outlook to be installed.
I appreciate that it won't create instances of MailItem, as you have asked for in your question - but it will enable you to extract save the individual attachments and the body...