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
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 need to open several Outlook windows previously populated with ticulo and email body for later user to inform the senders. I need to open several windows (I walk a grid to know how many windows).
I'm trying to do this with threads but an error message occurs saying: Outlook can not do this because the dialog box is open. Please close it and try again "
How to open multiple competing windows?
Test Call
private void button2_Click(object sender, EventArgs e)
{
int qtdEventos = dgvDescEvento.RowCount;
Thread[] Threads = new Thread[qtdEventos];
try
{
cEmail testeEmail = new cEmail();
for (int i = 0; i < qtdEventos; i++)
{
Threads[i] = new Thread(new ThreadStart(new cEmail().Monta));
}
foreach (Thread t in Threads)
{
t.Start();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace NavEventos.Class
{
class cEmail
{
private Outlook.Application outlookApp;
public cEmail()
{
outlookApp = new Outlook.Application();
}
public void Monta()
{
string pTitulo = "Title";
string pAssunto = "Body test";
Outlook._MailItem oMailItem = (Outlook._MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.Inspector oInspector = oMailItem.GetInspector;
Outlook.Recipients oRecips = (Outlook.Recipients)oMailItem.Recipients;
#region MONTA ASSUNTO
oMailItem.Subject = pTitulo;
#endregion
#region MONTA CORPO DO E-MAIL
oMailItem.Body = pAssunto;
#endregion
oMailItem.Display(true);
}
}
}
You may not like this... but you shouldn't try. ;(
As you can see the Outlook COM interface is trying very hard to prevent you from doing this, it is one of the limitations of the outlook automation libraries that displaying a mail item is done in a modal kind of way.
There is good reason for this, your user is in your LOB application, then your code wants them to read an email in outlook, which you have done using the COM automation libraries for outlook. Now their outlook icon in the toolbar is flashing because a new email modal window has opened up, but this dialog may have opened up behind your current LOB app.
Now the user will need to switch context into Outlook to see the dialog and read the email.
If you can review your need to open these emails all at the same time then you and outlook com automation will get along just fine :)
Otherwise consider writing a plugin for Outlook and moving your email management routines into outlook itself. In there you can be very creative, sounds like you really need just a master - detail style of interface, like the main outlook browser, so you have a list of these emails and as the user clicks on them they are displayed in the preview inspector.
Maybe the solution is to use your logic to move these messages into a
specific folder in outlook, then use Outlook automation to make this
folder the current active window in outlook, then the user can decide
which emails they want to action or not.
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.
Okay, I have no problem identifying the .PST file using the Outlook Interop assemblies in a C# app. But as soon as I hit a password protected file, I am prompted for a password.
We are in the process of disabling the use of PSTs in our organization and one of the steps is to unload the PST files from the users' Outlook profile.
I need to have this app run silently and not prompt the user. Any ideas? Is there a way to create the Outlook.Application object with no UI and then just try to catch an Exception on password protected files?
// create the app and namespace
Application olApp = new Application();
NameSpace olMAPI = olApp.GetNamespace("MAPI");
// get the storeID of the default inbox
string rootStoreID = olMAPI.GetDefaultFolder(OlDefaultFolders.olFolderInbox).StoreID;
// loop thru each of the folders
foreach (MAPIFolder fo in olMAPI.Folders)
{
// compare the first 75 chars of the storeid
// to prevent removing the Inbox folder.
string s1 = rootStoreID.Substring(1, 75);
string s2 = fo.StoreID.Substring(1, 75);
if (s1 != s2)
{
// unload the folder
olMAPI.RemoveStore(fo);
}
}
olApp.Quit();
Yes you can automate outlook from another app.
There is a Logon method on the NameSpace object so that you can logon to the profile then you can do anything that you want. But I think that it will just pop up the prompt again as it automation but ..There is a 3rd libray that may help you as well to do this as it does it via mapi instead. checkout profman.dll in the redemption libray