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.
Related
I am creating outlook add ons. I want when mail come inbox then change
the label, i use Outlook.ItemsEvents_ItemAddEventHandler(callBack)
method but in work only when outlook web app open. I want
Outlook.ItemsEvents_ItemAddEventHandler(callBack) call everytime
when mail comes in Inbox.
If there is ant Outlook Rest Api available for that problem.
private void Phishing_Load(object sender, RibbonUIEventArgs e)
{
outlookApp = new Outlook.Application();
inboxFolder = outlookApp.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
deleterFolder = outlookApp.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderJunk);
mailItems = inboxFolder.Items;//.Restrict("[Unread]=true");
mailItems.Sort("[ReceivedTime]", true);
inboxFolder.Items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(CallFunction);
}
private void CallFunction(object data)
{
MessageBox.Show("call function");
}
Outlook add-in can work only when Outlook application is running. It seems you can't get what you wish using an Outlook add-in - find an alternative way. If you run Outlook against on-site Exchange server try to create a so called transport agent for Exchange.
Is there an easy way to programatically create a reply message in a VSTO Outlook addin that includes the original message, with the same look that occurs when clicking on the built-in reply button in Outlook? Or does one need to write code to retrieve the original email properties & text, and format it such that it looks as if the reply was composed by Outlook?
How about:
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
private void Reply(Outlook._MailItem mailItem)
{
Outlook.Actions actions = mailItem.Actions;
Outlook.Action action = actions["Reply"];
Marshal.ReleaseComObject(actions);
action.ReplyStyle = Outlook.OlActionReplyStyle.olIncludeOriginalText;
Outlook._MailItem response = action.Execute() as Outlook.MailItem;
Marshal.ReleaseComObject(action);
response.Display();
Marshal.ReleaseComObject(response);
}
I have a task which i need to create a program that converts outlook email to pdf.
this is my code
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
NameSpace outlookNs = app.GetNamespace("MAPI");
MAPIFolder rootFolder = outlookNs.Stores["Blah"].GetRootFolder();
List<MailItem> mailItems = new List<MailItem>();
Folders subFolders = rootFolder.Folders;
foreach (Folder folder in subFolders)
{
if (folder.Name == "Inbox")
{
Items items = folder.Items;
foreach (object item in items)
{
if (item is MailItem)
{
MailItem mailItem = item as MailItem;
string fileName = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "New folder", mailItem.EntryID + mailItem.SenderName.Replace("/", "") + ".msg");
mailItem.SaveAs(fileName, Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG);
}
}
}
}
the code is working but the outlook contains thousands of email. The outlook prompt a message every 10 minutes similar to the screenshot below
is there a way to avoid getting the message? Programatically or a setting will do?
Basically, it's not related to the programming instead of it's related the outlook security settings.
For every version of outlook you can find the settings for this pop-up just follow the instruction on this blog.
You can do a setting in your out look.
Mine is outlook 2013.
File->options : a window opens
In the window select Trust Center
You can see a button Trust center Settings
Options in window changes. Select Programmatic access
UnCheck the radio button Never warn me about suspicious activity (not recommended)
Through program, you can change below registry settings:
Go to "HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\15.0\outlook\security"
Change below settings programatically:
PromptSimpleMAPISend -- 2
PromptSimpleMAPINameResolve -- 2
PromptSimpleMAPIOpenMessage -- 2
By default when outlook is installed, the above values comes with zero value. What I do in my program is, I turn them to "2" programatically just before sending the email and turn them back to zero later point of time.
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 :) .
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).