Unable to open mailItem because of outlook interface..! - c#

I have an application where i create a mailItem using Outlook interop.
On some systems the code works without problems.
But on one of the systems this error appears:
Message= Unable to cast COM object of type
'Microsoft.Office.Interop.Outlook.ApplicationClass' to interface type
'Microsoft.Office.Interop.Outlook._Application'. This operation failed because
the QueryInterface call on the COM component for the interface with IID
'{00063001-0000-0000-C000-000000000046}' failed
due to the following error: Interface not registered
I think it has something to do with the register see: Answer on Error accesing COM components
But i need to solve this problem in the code, because i can't acces all the systems with this kind of problem.
using Outlook = Microsoft.Office.Interop.Outlook;
//Create email body with the customers
string mailBody = customers;
//Create the email with the settings
Outlook.Application outlookApp = new Outlook.Application();
Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.Subject = mailSubject;
mailItem.Attachments.Add(totalPath);
mailItem.Body = mailBody;
mailItem.Importance = Outlook.OlImportance.olImportanceNormal;
try
{
//Try to open outlook, set message if its not possible to open outlook
mailItem.Display(true);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
How can i solve this in my code?
P.S. Every system uses the office 2013 version!

Try to use the following code instead:
oApp = Activator.CreateInstance(Type.GetTypeFromProgID("Outlook.Application")) as Microsoft.Office.Interop.Outlook.Application;
It looks like something is wrong with the windows registry records. Take a look at the similar forum thread - Error: Unable to cast COM object of type 'Microsoft.Office.Interop.Outlook.ApplicationClass' to interface type 'Microsoft.Office.Interop.Outlook._Application'..
Do you have the Click2Run edition of Office installed on the PC? See How to: Verify Whether Outlook Is a Click-to-Run Application on a Computer for more information.

Related

Saving html message in Outlook 2019 with .NET C#

Using .NET C# i want to load an Outlook html message from *.msg file, add a recipient and save it to standard draft folder.
I cannot do it properly with Outlook 2019 (not 2016 or 2013), because after saved, it turns the message body format to plain text. This happen with 2019 version only.
In the code example i first create the email and save it to draft. Until the COM Application object is instantiated the format remain html. Right after i had manually opened Outlook.exe the message has been turned to plain text. I check this with the function PrintBodyFormat. Please note this happen with Office 2019 only.
using Debug = System.Diagnostics.Debug;
using Outlook = Microsoft.Office.Interop.Outlook;
static void CreateMail()
{
Outlook.Application app = new Outlook.Application();
Outlook.MailItem mail = app.CreateItemFromTemplate(#"C:\html_message.msg");
mail.Recipients.Add("johndoe#foobar.com");
Debug.WriteLine(mail.BodyFormat.ToString());
//OUTPUT WITH ALL OUTLOOK VERSION: "olFormatHTML"
mail.Save();
mail.Close(Outlook.OlInspectorClose.olDiscard);
System.Runtime.InteropServices.Marshal.ReleaseComObject(mail);
mail = null;
Outlook.NameSpace nms = app.GetNamespace("MAPI");
Outlook.MAPIFolder DraftFolder = nms.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDrafts);
mail = DraftFolder.Items[1];
Debug.WriteLine(mail.BodyFormat.ToString());
//OUTPUT WITH ALL OUTLOOK VERSION: "olFormatHTML"
mail.Close(Outlook.OlInspectorClose.olDiscard);
System.Runtime.InteropServices.Marshal.ReleaseComObject(mail);
mail = null;
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(DraftFolder);
System.Runtime.InteropServices.Marshal.ReleaseComObject(nms);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
}
//Run this after manually opened Outlook.exe
static void PrintBodyFormat()
{
Outlook.Application app = new Outlook.Application();
Outlook.NameSpace nms = app.GetNamespace("MAPI");
Outlook.MAPIFolder DraftFolder = nms.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDrafts);
Outlook.MailItem mail = DraftFolder.Items[1];
Debug.WriteLine(mail.BodyFormat.ToString());
//OUTPUT WITH OUTLOOK 2016 OR EARLIER: "olFormatHTML"
//OUTPUT WITH OUTLOOK 2019: "olFormatPlain"
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(mail);
System.Runtime.InteropServices.Marshal.ReleaseComObject(DraftFolder);
System.Runtime.InteropServices.Marshal.ReleaseComObject(nms);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
}
Do not use mail.Close(Outlook.OlInspectorClose.olDiscard); - you never showed the inspector, so there is no reason to close it.
Also, Marshal.ReleaseComObject won't do much since you never release the Recipients collection and the Recipient object returned by Recipients.Add - both of them keep a reference to the parent message, and you end up with two implicit variables that you never release.
Do not use DraftFolder.Items[1] - save the value of MailItem.EntryID in a variable after calling Save, then use it to reopen the message using Namespace.GetItemFromID.

C# start Outlook in different security context

We have a WPF application need to display a new Outlook item, allow user to edit before send. The application start with administrator privileges, so if user's Outlook opened already, then there's an error when getting Outlook instance. How to solve it? Please help me, thanks.
You can't automate Outlook if it is run under different security context. But you can detect such cases trying to get an Outlook instance using the Marshal.GetActiveObject method which obtains a running instance of the specified object from the running object table (ROT). For example:
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.
application = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
if(application == null)
MessageBox.Show("You need to run Outlook under the same security context");
}
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("", "", Missing.Value, Missing.Value);
nameSpace = null;
}
// Return the Outlook Application object.
return application;
}
So, when the Outlook.exe process exists and you can't get the object all you can do is to ask users to run the application under the same security context.
There isn't much you can do short of starting your app in the same security context.

Retrieving the COM class factory for component failed. Access is denied. HRESULT: 0x80070005 E_ACCESSDENIED

While trying to open Outlook for attachment in mail, via IIS asp.net website got this error. Assign IIS USR and Network with full permissions in DCOMCnfg to Microsoft OutLook component but nothing work.
Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
using System;
using Outlook = Microsoft.Office.Interop.Outlook;
// Create the Outlook application.
Outlook.Application oApp = new Outlook.Application();
// Create a new mail item.
Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
// Set HTMLBody.
//add the body of the email
oMsg.HTMLBody = "Hello, This is test for sending pdf attachment using OutLook";
//Add an attachment.
String sDisplayName = "MyAttachment";
int iPosition = (int)oMsg.Body.Length + 1;
int iAttachType = (int)Outlook.OlAttachmentType.olByValue;
//now attached the file
Outlook.Attachment oAttach = oMsg.Attachments.Add(Server.MapPath("~/TestSendFile.pdf"), iAttachType, iPosition, sDisplayName);
//Subject line
oMsg.Subject = "Your Subject will go here.";
// Add a recipient.
Outlook.Recipients oRecips = (Outlook.Recipients)oMsg.Recipients;
// Change the recipient in the next line if necessary.
Outlook.Recipient oRecip = (Outlook.Recipient)oRecips.Add("user1#comecompany.com");
oRecip.Resolve();
// Send.
oMsg.Display();
Outlook Object Model (just like any other Office app) cannot be used from a service (such as IIS).
More than that, you are attempting to display a message on the server side where nobody will ever see it.
You can use either
Exchange Web Services (in case of an Exchange mailbox)
Extended MAPI (C++ or Delphi only)
Redemption (I am its author) - it wraps Extended MAPI and its RDO family of objects can be used from a service. It can be used from any language, including C#.
If you are attempting to display a message on the client side, your choices are
mailto url - does not allow HTML or attachments
Use Outlook Object Model from the client side Java Script. Your site must be trusted and you can ony use COM in IE.
Generate an EML (MIME) file and provide a link to it - Outlook will be happy to open from the browser and display it.

Create outlook .msg file in C#

I am trying to create outlook .msg format file using my C# code.
I have used below 2 code:
Method 1 :
Microsoft.Office.Interop.Outlook.Application objOutlook = new Microsoft.Office.Interop.Outlook.Application();
// Creating a new Outlook message from the Outlook Application instance
Microsoft.Office.Interop.Outlook.MailItem msgInterop = (Microsoft.Office.Interop.Outlook.MailItem)(objOutlook.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem));
// Set recipient information
msgInterop.To = "neha1#gmail.com";
msgInterop.CC = "neha#gmail.com";
// Set the message subject
msgInterop.Subject = "Subject";
// Set some HTML text in the HTML body
msgInterop.HTMLBody = "<h3>HTML Heading 3</h3> <u>This is underlined text</u>";
// Save the MSG file in local disk
string strMsg = #"c:\\temp\TestInterop.msg";
msgInterop.SaveAs(strMsg, Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG);
Second method :
Redemption.RDOSession Session = new RDOSession();
Redemption.RDOMail Msg = Session.CreateMessageFromMsgFile(#"c:\temp\YourMsgFile.msg");
Msg.Sent = true;
Msg.Subject = "test";
Msg.Body = "test body";
Msg.Recipients.AddEx("the user", "user#domain.demo", "SMTP", rdoMailRecipientType.olTo);
Msg.Save();
Both method gives error on executing as below :
System.Runtime.InteropServices.COMException (0x8004010F): Creating an
instance of the COM component with CLSID
{29AB7A12-B531-450E-8F7A-EA94C2F3C05F} from the IClassFactory failed
due to the following error: 8004010f Exception from HRESULT:
0x8004010F.
I have researched and found some compatibility issue with platform. I tried to change the platform from 32-bit to x64. Still it did not resolve my problem.
Is outlook installed and in a runnable state on the machine you are doing this from? The error is that the com component isn't registered, which usually would mean you just copied dlls from another machine which didn't register the com ones.
So either install outlook, or install this
https://www.microsoft.com/en-us/download/details.aspx?id=1004
I installed Outlook on my system. And the code I had posted above (Microsoft.Office.Interop.Outlook.Application) works like a charm :) .

EWS - Outlook Interop Synchronize

I'm using ExchangeServer 2010 SP2
and Outlook 2013
First I'm saving a Mail to the Draft folder using EWS
EmailMessage.Save()
After that I'm trying to open the mail via Interop
but I'm getting a COMException that the item doesn't exist
Outlook.Application app = new Outlook.Application();
Outlook.NameSpace mapi = app.GetNamespace("MAPI");
Outlook.MAPIFolder draftFolder = mapi.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDrafts);
//Custom function to get EntryID
string entryId = GetMessageId(email,IdFormat.HexEntryId);
string storeId = draftFolder.StoreID;
MailItem item = null;
try
{
item = mapi.GetItemFromID(entryId, storeId);
}
catch (COMException)
{
//Item not found
}
Is there any way to force Outlook to sync the Draft folder with the Exchange server?
I have used
Session.SendAndRecieve(true)
but it doesn't show any effect and I can't find any other Interop functions doing the desired thing.
EDIT: When disabling Cache-Mode everything runs fine but as soon as I turn it on I have no clue how to force it to get the Message
Thank you very much!
You can either
wait until the sync finishes - use Namespace.SyncObjects collection, retrieve the first SyncObject object, call SyncObject.Start and wait for the SyncObject.SyncEnd event to fire.
On the Extended MAPI level (C++ or Delphi) or Redemption (I am its author, it wraps Extended MAPI and can be used in any language), open the message in the online mode by using the MAPI_NO_CACHE (0x200) flag (IMsgStore::OpenEntry in Extended MAPI or RDOStore.GetMessageFromID in Redemption).

Categories

Resources