Similar to this question,
Open Specific MailItem in Outlook from C# , In a C# VSTO application I'm trying to open an email in a new outlook window/inspector using the method GetFolderFromID and passing it's EntryID and StoreID.
Full code below:
Outlook.Application myApp = new Outlook.ApplicationClass();
Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Outlook.MAPIFolder mySentBox = mapiNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail);
Outlook.MailItem myMail = ((Outlook.MailItem)mySentBox.Items[1]);
string guid = myMail.EntryID;
string folderStoreID = mySentBox.StoreID;
Outlook.MailItem getItem = (Outlook.MailItem)mapiNameSpace.GetItemFromID(guid, folderStoreID);
getItem.Display();
The below code only opens up the requested email in a new window when the email is already selected within outlook.
getItem.Display();
If not selected, the following error returns.
System.Runtime.InteropServices.ComException: 'A dialog box is open. Close it and try again'.
I've also attempted adding a new inspector & activating/displaying the email object via it with no success.
Kind regards
The error simply means a dialog box is open. Make sure there are no modal windows displayed and make sure you ever call MailItem.Display(true) to display items modally.
Related
I am trying to search for specific emails that have a particulary subject.
Outlook.Folder inbox = new Outlook.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items items = inbox.Items;
Outlook.MailItem mailItem = null;
object folderItem;
string subjectName = string.Empty;
string filter = "[Subject] > 's' And [Subject] <'u'";
folderItem = items.Find(filter);
while (folderItem != null)
{
mailItem = folderItem as Outlook.MailItem;
if (mailItem != null)
{
subjectName += "\n" + mailItem.Subject;
}
folderItem = items.FindNext();
}
subjectName = "The follow e-mail messages were found: " + subjectName;
MessageBox.Show(subjectName);
I am getting an error :
"Severity Code Description Project File Line Suppression State
Error CS0426 The type name 'ActiveExplorer' does not exist in the type 'Application'"
You need to create a new Application instance first if you develop a standalone application where Outlook is automated or use the built-in property if you develop a VSTO based add-in instead of the following code:
Outlook.Folder inbox = new Outlook.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
A standalone application should create a new Outlook instance:
Outlook.Application app = new Outlook.Application();
Outlook.Explorer explorer = app.ActiveExplorer();
Outlook.Namespace ns = app.GetNamespace("MAPI");
Outlook.Folder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
In case of VSTO add-in you can use the Application property of the ThisAddin class:
Outlook.Explorer explorer = Application.ActiveExplorer();
Outlook.Namespace ns = app.GetNamespace("MAPI");
Outlook.Folder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
You can read more about the Find/FindNext or Restrict methods of the Items class in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
Also you may find the AdvancedSearch method helpful. The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
I am not sure why you are even accessing ActiveExplorer - you are not using it, and if Outlook was not running prior, there won't be any open explorers (and inspectors), so ActiveExplorer will return null anyway.
Also keep in mind that Application.Session will be null unless Outlook is already running - you need to log in first.
Thirdly, you are not calling a constructor - that would be new Outlook.Application().Blah (note ()).
Change your code to
Outlook.Application app = new Outlook.Application();
Outlook.Namespace session = app.GetNamespace("MAPI");
session.Logon();
Outlook.Folder inbox = session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
Looking a bit of advise or direction in regards to VSTO Ribbons with Outlook in C#.
So far I’ve built an Outlook 2010 Ribbon (using TabMail), this Ribbon opens a WinForms window which allows my users to select contacts from a Custom Built Address Book from a SQL database, via a DataGridView.
The users basically select from a datagridview who they want to email, which then gets added to a toLine list.
Application app = new Microsoft.Office.Interop.Outlook.Application();
Mail item item = app.CreateItem((OlItemType.olMailItem));
item.To = toLine;
Item.Display();
This.close();
The downside of using this approach is the user has to build their To List before they actually compose their email.
I’m now trying to make use of TabMailNewMessage. This should allow the user to compose their email, then click the Ribbon icon within the new message and add to their To List from there.
I’ve got the icon showing okay in the TabMailNewMessage, and I’ve got it to open a 2nd Win Form [currently as a test].
I’m a little unsure how to add to the To List of an already open existing mailItem.
At present all I have on the 2nd Win Form is a button, can someone explain how I can click that button and simply add someone to the To List [of this already composed email]. (I don’t have any code behind the button click as I’m not sure what to do)
I also need to make sure that it doesn’t send the email, but simply adds the user to the To List.
Currently using Office 2010, and VS 2013 (with C#).
Hopefully I’m making some sense here.
Thanks
EDIT:
Not sure if its a simple as
Application app = Globals.ThisAddIn.Application;
MailItem mi = (Outlook.MailItem)app.ActiveInspector().CurrentItem;
Mi.Recipients.Add(“joe#email.com”);
This.Close();
The MailItem.Recipients.Add method allows creating a new recipient in the Recipients collection. The name of the recipient can be a string representing the display name, the alias, or the full SMTP email address of the recipient.
using System.Runtime.InteropServices;
// ...
private bool AddRecipients(Outlook.MailItem mail)
{
bool retValue = false;
Outlook.Recipients recipients = null;
Outlook.Recipient recipientTo = null;
Outlook.Recipient recipientCC = null;
Outlook.Recipient recipientBCC = null;
try
{
recipients = mail.Recipients;
// first, we remove all the recipients of the e-mail
while(recipients.Count != 0)
{
recipients.Remove(1);
}
// now we add new recipietns to the e-mail
recipientTo = recipients.Add("Eugene Astafiev");
recipientTo.Type = (int)Outlook.OlMailRecipientType.olTo;
recipientCC = recipients.Add("Somebody");
recipientCC.Type = (int)Outlook.OlMailRecipientType.olCC;
recipientBCC = recipients.Add("eugene.astafiev#somedomain.com");
recipientBCC.Type = (int)Outlook.OlMailRecipientType.olBCC;
retValue = recipients.ResolveAll();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
if (recipientBCC != null) Marshal.ReleaseComObject(recipientBCC);
if (recipientCC != null) Marshal.ReleaseComObject(recipientCC);
if (recipientTo != null) Marshal.ReleaseComObject(recipientTo);
if (recipients != null) Marshal.ReleaseComObject(recipients);
}
return retValue;
}
You may find the following articles helpful:
How To: Fill TO,CC and BCC fields in Outlook programmatically
How To: Create and send an Outlook message programmatically
Also, I'd suggest developing an Outlook form region which can be displayed on the same window instead of using a standalone window, see Create Outlook form regions for more information.
Yes, it is as simple as using Application.ActiveInspector.CurrentItem. But you can do better than that - your ribbon button event handler takes IRibbonControl object as a parameter. Cast the IRibbonControl.Context property to Inspector or Explorer (depending on where the button is hosted).
Also keep in mind that in a COM addin there is no reason to create a new instance of the Outlook.Application object (it will be crippled with the security prompts anyway) - use Globals.ThisAddIn.Application
I'm developing a C# program where you enter an Outlook category name and it opens an Outlook window, which shows all the mails received with that category tag.
For example:
The user enters the Category-Tag "Work" and it launches Outlook and shows all the mails he received and tagged with the Category "Work".
I was able to open the "Send Email" window, but that was not my intention:D
The code:
Outlook.Application outlookApp = new Outlook.Application();
Outlook._NameSpace clientNameSpace = (Outlook._NameSpace)outlookApp.GetNamespace("MAPI");
Outlook.PostItem postitem = (Outlook.PostItem) outlookApp.CreateItem(Outlook.OlItemType.olPostItem);
postitem.Display(true);
I assume by "Send Email" you mean opening a draft message that you can send? You need MailItem object, not PostItem:
Outlook.Application outlookApp = new Outlook.Application();
Outlook._NameSpace clientNameSpace = (Outlook._NameSpace)outlookApp.GetNamespace("MAPI");
Outlook.MailItem mailitem = (Outlook.MailItemItem) outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
mailitem.Subject = "My test message";
mailitem.Display(true);
You can create different types of items in Outlook using the CreateItem method.
The type of project you create depends on the parameters of CreateItem.
For item type, please see the following link::OlItemType Enum
I have user myuser that logged in in windows and I open the program with otheruser.
I need that then I open new mail in outlook it will open it with myuser. The code that I'm using is:
Outlook.Application App = new Outlook.Application();
Outlook._MailItem MailItem = (Outlook._MailItem)App.CreateItem(Outlook.OlItemType.olMailItem);
MailItem.To = BossName.Text;
MailItem.CC = ClientName.Text;
MailItem.Display(true);
Start your application in the context of the desired user, or
you may use Impersonation:
WindowsIdentity.Impersonate Method
Be sure that outlook doesn't run in your session already. Outlook can only run once in a session - so it's not possible to logon with different Outlook-MAPI-Sessions in one Windows-Session at the same time. You Always have to reopen outlook.
Multible Outlook-Profiles
Another way is to configure multible Outlook profiles and start outlook via .net and pass the Profilename. But this can be a little bit tricky, because you always have to check if outlook isnt already running in a different profilecontext - because the Profile-Parameter will be ignored if outlook has already been opened.
class Sample
{
Outlook.Application GetApplicationObject()
{
Outlook.Application application = null;
// Check whether there is an Outlook process running.
if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
{
// If so, use the GetActiveObject method to obtain the process and cast it to an Application object. Or close Outlook to open a new instance with a desired profile
application = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
//!! Check if the application is using the right profile - close & reopen if necessary
}
else
{
// If not, create a new instance of Outlook and log on to the default profile.;
application = new Outlook.Application();
Outlook.NameSpace nameSpace = application.GetNamespace("MAPI");
nameSpace.Logon("profilename", "", Missing.Value, Missing.Value);
nameSpace = null;
}
// Return the Outlook Application object.
return application;
}
}
If possible use EWS
Another approach would be to use EWS-API (Exchange WebServices-API) but this presupposes to have an Exchange or Office365 account. And is only usefull if you want to deal with outlook-items in the background (.Display() is not possible)
If you are using an Exchange-Account (Office365) i would prefer to do it that way...
Get started with EWS Managed API client applications
I am using Outlook.Application and Outlook.MailItem object for opening Outlook in my C# desktop application. My outlook doesn't display attachments although when I send the mail to myself, I receive mail with attachments. But it is not showing before sending mail (when outlook is open). I am using Outlook 2007. Below is my code:
Outlook.Application oApp = new Outlook.Application();
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
// Log on by using a dialog box to choose the profile.
oNS.Logon(Missing.Value, Missing.Value, true, true);
// Create a new mail item.
Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
......
//Check if we need to add attachments
if (_files.Count > 0)
{
foreach (string attachment in _files)
{
oMsg.Attachments.Add(attachment,Outlook.OlAttachmentType.olByValue,null,null);
}
}
oMsg.Save();
oMsg.Display(false);
Of course, Type.Missing is used to omit the parameter and use the default value in COM add-ins.
Also I'd suggest breaking the chain of calls and declaring each property or method call on a separate line of code. It will allow to release each underlying COM object instantly.
Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. You can read more about that in the Systematically Releasing Objects article in MSDN.