I have the next problem. I've written the solution for MS Outlook 2010 that creates email summary and write it down to an Excel file(.xls) The problem is that on my PC and several others it works correctly but when I sent it to customers, they said that it creates summary only for inbox folder on some PCs and on others it doesn't work at all.
I've also created the possibility to choose the folder to get the emails but the problem left. I'll provide a code snippet of the function choosing folder and getting the list of emails. I save emails in List in private field of my class.
Take a look on this func and please help to get out what is wrong. Thanks.
public void GetTheArrayOfEmails(DateTime startDate, DateTime finishDate)
{
try
{
Outlook.Application oApp = new Outlook.Application();
Outlook.NameSpace oNs = oApp.GetNamespace("mapi");
oNs.Logon(Missing.Value, Missing.Value, false, false);
//Outlook.MAPIFolder folder = oApp.Session.PickFolder();
foreach (Outlook.MailItem oMsg in oApp.Session.PickFolder().Items)
{
if (oMsg.ReceivedTime.ToUniversalTime() > startDate.ToUniversalTime() &&
oMsg.ReceivedTime.ToUniversalTime() < finishDate.ToUniversalTime())
{
MailList.Add(oMsg);
}
}
oNs.Logoff();
releaseObject(oNs);
releaseObject(oApp);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
UPD: Fixed the problem. I missed cast. And tried to cast items which are not of MailItem interface.
Related
I'm trying to fetch attachments from a particular folder in Outlook 2010 in a C# Windows Forms app. I have a class called MailInbox that contains the Outlook namespace, inbox, and message objects.
Here is the code for that class and its methods:
public class mailInbox
{
//declare needed variables for outlook office interop
public Outlook.Application oApp = new Outlook.Application();
//public Outlook.MAPIFolder oInbox;
public Outlook.MAPIFolder idFolder;
public Outlook.NameSpace oNS;
public Outlook.Items oItems;
public Outlook.MailItem oMsg;
public Outlook.MAPIFolder subFolder;
public string subFolderName;
public mailInbox()
{
//read the subfoldername from a text file
using (StreamReader subFolderNameRead = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\SuperVerify\config\subfoldername.txt"))
{
subFolderName = subFolderNameRead.ReadLine().Trim();
}
oNS = oApp.GetNamespace("mapi");
//oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
idFolder = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Folders[subFolderName]; // use the subFolderName string, read from the config text file, to get the folder from outlook
oItems = idFolder.Items;
//oMsg = (Outlook.MailItem)oItems.GetNext();
}
public void FetchEmail() // fetches the next email in the inbox and saves the attachments to the superverify folder
{
oNS.Logon(Missing.Value, Missing.Value, false, true); //login using default profile. This might need to be changed.
oMsg = (Outlook.MailItem) oItems.GetNext(); //fetch the next mail item in the inbox
if(oMsg.Attachments.Count > 0) // make sure message contains attachments **This is where the error occurs**
{
for (int i =0; i< oMsg.Attachments.Count; i++)
{
oMsg.Attachments[i].SaveAsFile(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\SuperVerify\images\" + oMsg.Attachments[i].FileName); //save each attachment to the specified folder
}
} else //if no attachments, display error
{
MessageBox.Show("The inbox folder has no messages.", "TB ID Verification Tool", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
public void changeSubFolderName(string newSubFolderName)
{
subFolderName = newSubFolderName;
}
}
When I click the button that invokes the FetchEmail method, I get the error
System.NullReferenceException: 'Object reference not set to an instance of an object.'
oMsg was null. I thought that
public Outlook.MailItem oMsg;
instantiated the object and that
oMsg = (Outlook.MailItem) oItems.GetNext();
assigned it an Outlook MailItem, but it seems I don't understand what's going on here.
From the documentation which curiously references VB.NET's Nothing instead of null,
It returns Nothing if no next object exists, for example, if already positioned at the end of the collection.To ensure correct operation of the GetFirst, GetLast, GetNext, and GetPrevious methods in a large collection, call GetFirst before calling GetNext on that collection, and call GetLast before calling GetPrevious. To ensure that you are always making the calls on the same collection, create an explicit variable that refers to that collection before entering the loop.
So GetNext will return null if you're at the end of the folder. You'd have to check it for null before attempting to use it.
You can also use oItems.Count to determine that there are no items when you initially access the folder's items. But if Count is one or more you'd still have to check for null, because you're dealing with a collection that can change. Hypothetically someone could remove items from the folder while you're reading it, so you can't get the count up front and then rely on it.
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 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
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...
I'm trying to access an Outlook Mailbox from C# / Winforms. I have two separate mailboxes that my user profile can access. How can i code it so that it only pulls from a certain mailbox?
Here's what I have currently, but it only pulls the info from my default account mailbox.
try
{
OutLook.Application oApp = new OutLook.Application();
OutLook.NameSpace oNS = (OutLook.NameSpace)oApp.GetNamespace("MAPI");
oNS.Logon(Missing.Value, Missing.Value, false, true);
OutLook.MAPIFolder theInbox = oNS.GetDefaultFolder(OutLook.OlDefaultFolders.olFolderInbox);
int count = theInbox.UnReadItemCount;
inboxLabel.Text = inboxLabel.Text + " " + count.ToString();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
I also need to tell it certain folders along with the inbox (like above).
Thanks for the assistance in advance.
I finally figured out how to designate which mailbox I wanted to open. I'll post it here for others to use in the future.
try
{
Outlook.Application oApp = new Outlook.Application();
Outlook.NameSpace oNS = (Outlook.NameSpace)oApp.GetNamespace("MAPI");
oNS.Logon(Missing.Value, Missing.Value, false, true);
Outlook.MAPIFolder theInbox = oNS.Folders["Mailbox - Name Here"].Folders["Inbox"];
....Do you want with that Folder here....
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
Hope this helps anyone else :D