Open Outlook with same credentials as running application - c#

I'm writing a program that needs to open up Microsoft Outlook and create a mail item for the user when they click on a button. However, when I do so, I get the following error:
Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000- 000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
After researching this error I found out that my program and MS Outlook must both be run as administrator or as normal privilege level.
So here's my question... How do I open MS Outlook through the C# code by using the same privilege level as my current running program. I need to get the current privilege level, then open Outlook with that privilege level. I've had no luck in my research with this so far. Any help is appreciated!
Here's my code (currently) for opening MS Outlook and how I use it:
Application outlookApp = new Application();
MailItem mailItem = outlookApp.CreateItem(OlItemType.olMailItem);
mailItem.Subject = "Blah";
mailItem.HTMLBody= #"Various HTML stuff";
foreach (string documentPath in this.documentPaths)
{
mailItem.Attachments.Add(documentPath, 1, 1, documentPath);
}
mailItem.Display(true);
I am using Microsoft.Office.Interop.Outlook.
If outlook is already running with administrator. Then I don't get any error.
Please suggest.

I am using SimpleMAPI.NET to open the standard email application and send an email. I have even tuned it to open a specific email application, different from the one configured in windows. Works great with MS Outlook so far and can even be used with other email software.
SimpleMAPI.NET can be obtained from here:
http://www.codeproject.com/Articles/2048/Simple-MAPI-NET
If you deem this approach workable for you, just leave a comment and I will extend my answer by some code examples and my modifications to SimpleMAPI.NET regarding Outlook (there are some issues with the original version above).
I am proposing this here, because my team initially was using Outlook via COM (as you do, at the moment), faced several issues with this and then opted for my MAPI solution. It has proven to be much more stable an versatile, if one "only" wants to send an email via an external application...

Outlook is a singleton, so to make sure it is running on the same trust level as your app, your app must be the one that starts it.
You can try to kill Outlook first (not very nice and the user won't appreciate it) before restarting it from your app.
You can use Extended MAPI (C++ or Delphi) or Redemption (I am its author - it wraps Extended MAPI and can be used from any language) - MAPI is loaded in-proc, so it will work even if Outlook is already running. But you will not be able to display the items: outlook.exe is the one that ends up displaying messages even if you use MAPI, so you are back where you started.
Why do your app and Outlook end up running in different security contexts?

Related

How to read Outlook mailbox using PowerShell with runtime user account

I want to read an Outlook mailbox using PowerShell. I can access the Outlook mailbox using a MAPI API call, but I can only connect with an existing/preconfigured Outlook ID/profile on the machine. My requirement is, I need to connect to Outlook mailbox during runtime.
I am using PowerShell version 5.
importing assembly files
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -comobject Outlook.Application
mapping Namespace
$namespace = $Outlook.GetNameSpace("MAPI")
accessing inbox
$OutlookInbox = $Outlook.Session.GetDefaultFolder(6)
$OutlookFolders = ($Outlook.Session.Folders.Item(1).Folders.Item(2)).FullFolderPath
Firstly, this is not MAPI: you just pass string "MAPI" to the Application.GetNamespace call - this is Outlook Object Model. It only allows you to access a mailbox in a preconfigured local profile. If there are multiple local profiles and Outlook is not running, you can pass the name of the profile (as shown in Control Panel | Mail | Show Profiles) to Namespace.Logon. If Outlook is already running, Namespace.Logon won't do anything. If the primary mailbox in the profile has the right to access other mailboxes in the same Exchange org, you can use Namespace.CreateRecipient / Namespace.GetSharedDefaultFolder to access the default folders of other mailboxes.
If you want truly dynamic access to an arbitrary mailbox without an existing Outlook profile, you can either:
Use EWS library - it is accessible from PS: see https://blogs.msdn.microsoft.com/webdav_101/2018/06/19/about-using-ews-and-powershell/
A temporary profile can be created and configured using Extended MAPI (see https://blogs.msdn.microsoft.com/dvespa/2015/10/28/how-to-configure-an-outlook-2016-profile-using-mfcmapi/), but Extended MAPI can only be accessed from C++ or Delphi.
You can use Redemption (I am its author) - it exposes RDOSession.LogonHostedExchangeMailbox method (RDOSession object roughly corresponds to the Namespace object in the Outlook Object Model). LogonHostedExchangeMailbox creates (and then deletes) a temporary profile that points to the specified mailbox.
Currently, you are dealing with the Outlook object model, not MAPI.
Outlook is a singleton, you can't run two instances on the system at the same time. So, when you create a new Application instance you will be linked to the already running instance. Be aware, you need to run both applications under the same security context.
Note, Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. Read more about that in the Considerations for server-side Automation of Office article.
As a workaround, you may consider using Open XML SDK if you deal only with Exchange accounts, see Start using web services in Exchange for more information.

How to disable outlook security warning while sending emails programmatically through C# windows application without using 3rd party tools

I have developed a Windows application in C# that sends bulk mail using Microsoft Office interop. Mails are sent properly but I want to disable the security warning from Microsoft Outlook that pops up before sending each mail. I want to disable it through code and not using any 3rd party application by changing in registry.
Got this resolved by going back to the code and changed the way it had been coded previously.
This link helped me in order to write the code which is trusted by Outlook.
https://learn.microsoft.com/en-us/visualstudio/vsto/specific-security-considerations-for-office-solutions?redirectedfrom=MSDN&view=vs-2019
You get a standard security prompt in Outlook.
There are several ways for suppressing such prompts:
Use a third-party components for suppressing Outlook security warnings. See Security Manager for Microsoft Outlook for more information.
Use a low-level API instead of OOM. Or any other third-party wrappers around that API, for example, Redemption.
Develop a COM add-in which has access to the trusted Application object.
Use group policy objects for setting up machines.
You can read more about all these ways on the Outlook "Object Model Guard" Security Issues for Developers page.

Creating and showing e-mail on Windows with maximal e-mail client compatibility

I need to create an executable that can be called from the command line which will create an e-mail, attach files to the e-mail and show the e-mail to the user so that they can complete the e-mail and send it. This should be done in the e-mail client that the user has configured as their default.
This needs to work for as many e-mail clients as possible. The ones I'm aware of that are used most are Outlook 2007-2010, Outlook Express, Windows Live Mail and Thunderbird. I'll target .NET 2.0 so that it does not require a newer .NET to be installed if the user is using Vista.
Simple MAPI is capable of doing the above, but Outlook 2007+ does not support it. All the other mail clients on the list do support Simple MAPI. I get the impression that Outlook is the only client that uses Extended MAPI and that Extended MAPI is tricky to use, so it's better to just use the Outlook COM API instead of Extended MAPI.
First the program will look for Outlook and use the Outlook COM API to perform the above if Outlook is available. I'll implement this component in VB and use late binding so that I'm not compiling against a specific version of Outlook. Then, if Outlook is not found it will fall back to Simple MAPI and attempt to use it.
Because of all this decision-making in the code I'll make this program log its activity so that we can debug what is happening on the user's machine when it doesn't work.
Will this approach work? Do you know a better approach? My goal is to maximize compatibility.
EDIT
It looks like Outlook 2007+ does support Simple MAPI, but if you're running the 64 bit version then a 32 bit executable can't call it. I'll stick with the above plan for that reason.
Outlook 2007 supports Simple MAPI just fine.

Error with Excel and C# when logged off the server

I have written a Windows Service in C#. My service is meant to open an Excel macro-enabled workbook (this is in Excel 2010). I have installed this service on our server which is running Windows Server 2008 64-bit. My service seems to have a problem launching Excel when no one is logged on the server, does anyone have a solution to this?
I get the following error:
System.Runtime.InteropServices.COMException (0x8000401A): Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046} failed due to the following error: 8000401a.
Excel is installed on the server, the service works fine when I am logged on the server but once all users have logged off, I get the above error. I would like the service to launch my Excel workbook regardless of an open session on the server or not.
My service seems to have a problem launching Excel when no one is logged on the server, does anyone have a solution to this.
Of course it has a problem. Windows Services cannot show a user interface, so how would you expect it to launch a GUI application like Microsoft Excel when there is no user logged in?
The specific COM error code that you receive means:
8000401a: The server process could not be started because the configured identity is incorrect. Check the username and password.
In other words, Excel is trying to start as an interactive user, which refers to the user that is currently logged on directly to the server console. Since no user is logged on, no interactive user exists, and the application fails when it tries to assume this identity.
The design was broken anyway: Excel was not designed to be run from a Windows Service. Create a standard Windows application instead. If you need it to run in the background without a UI of its own, don't create a window.
Basically, Cody Gray's answer is right. In the past I had a need to launch Excel from a Windows Service in order to print the file.
We were able to get past that kind of errors by setting the service to run as a specific user account and from time to time, log on as that user account and try to launch the files that failed to see the error messages popped up by Excel.
In your case, it is possibly because Excel is started for the first time and it asks you for something like your initials.
Are you using Office Automation to start Excel? Sorry, but Office Automation is not supported in service processes. It is designed to work only in an interactive process.
If you're lucky, Using Office Automation from a service process won't work. If you're not lucky, it will appear to work, and you'll actually put your application into production. You'll then start finding random bugs which are very difficult to reproduce, and even more difficult to fix without breaking something else.
That will be due to the fact that the real bug is a design bug - you used Office Automation from a service process.
Take it from the Voice of Experience...

How do I access Outlook mails with ASP.NET?

I'm trying to write an asp.net (using c#) app that accesses my Outlook mailbox and display the messages. I searched on google but couldn't find useful info, any help is appreciated?
You must be aware of the fact that outlook is running on user local machine, and your ASP.NET application is running on some server and there is no way that your server side ASP.NET code can use Outlook local data.
AFAIK only way to do something like that would be creating outlook addin that will export all mails to ASP.NET application
If you are using Exchange then you can use Exchange Web Services to read emails.
Please see here
Be very careful that you do not attempt to access Outlook on the server side by using the Automation interfaces. All of the Microsoft Office desktop applications are written to be run by an interactive user in a process with a message pump, with all synchronization happening via the UI. When you run them in a multi-threaded environment like ASP.NET, horrible things will happen. If you're lucky, the application will simply crash.
If you're not lucky, you can suffer from data corruption, random crashes in unrelated code, and all the other things that happen when an application corrupts memory.
You may also violate your license if the people accessing the Office application through your web site are not individually licensed to use the application on their desktop.
You can't connect to Outlook via C# (ASP.NET), but you can connect to your mailserver via POP3/IMAP to read the mail.
IMAP Client library using C#

Categories