I am writing an Outlook 2010/2013 plugin with C#. My abridged code looks like this:
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.ItemSend += Application_ItemSend;
}
void Application_ItemSend(object Item, ref bool Cancel)
{
Outlook.MailItem mailItem = Item as Outlook.MailItem;
// Scan for keywords before the user sends the email.
}
}
When the user hits the Send button on an email, the Application_ItemSend event handler executes. At that point, I want to scan the message body for certain keywords. However, I want to exclude older/original messages in that scan. I only want to scan the message that the user has just typed... mailItem.Body and mailItem.HTMLBody contain not only the message that the user is sending, but they also include all the previous messages in the entire thread/conversation. How can I filter those out?
I've not tested this myself yet, but this is on my todo list for our Addin as well. I haven't been able to find much documentation on this, but the OOXML of the mail (as well as the HTML) - at least in 2013 - contain something like the following:
OOXML:
<w:bookmarkStart w:id="0" w:name="_MailOriginal"/>
HTML:
<span style='mso-bookmark:_MailOriginal'>
This bookmark should allow you to find the point where you can cut off the message - as far as I know there is no other option in the API.
See here on how to get the OOXML of the mail:
Word.Document document = mailItem.GetInspector.WordEditor;
string xml = document.WordOpenXML;
Related
I've a problem with my VSTO application for Outlook. I want to process the email body from a selected e-mail.
For selected e-mails out of the "default" list this code works fine:
Object selItem = Globals.ThisAddIn.Application.ActiveExplorer().Selection[1];
Outlook.MailItem mailItem = (Outlook.MailItem)selItem;
return mailItem.Body;
But if a user opens an email from the list with a double click, the email is displayed in a new window. If the addin is executed in this window (over the ribbon), the email from the list is still used (which is now in the background).
Is there a way to find out if the plugin was started in a separate window and then get the email body from it?
Regards,
Florian
Coincidentally, I just dealt with something similar to this. My situation isn't identical, but since I could easily piece together what it seems like you're looking for see below. I haven't tested this, and obviously you'll have to handle passing the correct reference to your Outlook Application, but since i had this immediately available I figured it would pass it along with the hope that you'll find it helpful.
private static void ribbonButton_Click(object sender, RibbonControlEventArgs e)
{
Outlook.Application application = new Outlook.Application();
Outlook.Inspector inspector = application.ActiveInspector();
if (application.ActiveExplorer().Selection[1] is Outlook.MailItem explorerMailItem)
{
// Write code to handle message if sourced from explorer (i.e., Reading Pane)
}
else if (inspector.CurrentItem is Outlook.MailItem inspectorMailItem)
{
// Write code to hanlde message if sourced from inspector
// (i.e., openened (double-clicked) message
}
}
When you double click on email item you open an inspector window and you can access it by using Application.ActiveInspector() method. The Inspector object has CurrentItem property which represents the opened item.
Also, you should avoid using multiple dots in expressions and properly release COM objects.
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);
}
following this link - change outlook MailItem icon
I managed to change my inbox icons.
Here's what I did step by step.
1) Created a custom message class for new mail that arrives from the Internet
The class is IPM.Note.Internet
Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder inbox;
Outlook.Items items;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
outlookNameSpace = this.Application.GetNamespace("MAPI");
inbox = outlookNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
items = inbox.Items;
items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
void items_ItemAdd(object Item)
{
Outlook.MailItem mailitem = (Outlook.MailItem)Item;
String EmailHeader = mailitem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001E");
if (Item != null && EmailHeader.Contains("Look for a string in the headers here that we set for incomming mail") == true)
{
if (mailitem.MessageClass == "IPM.Note")
{
mailitem.MessageClass = "IPM.Note.Internet";
mailitem.Save();
}
}
}
2) Created a replacement Outlook Form Region matching the MessageClass. In this case I used IPM.Note.Internet
3) Assign the Icons in the Properties Pane of the Form Region Designer.
4) Debugged project and the next message that arrived from the internet was stamped with my custom icons after the message class was updated.
My issue now is that I can't preview or open the messages where I changed the message class. Similar to this post that's unanswered - Change Inbox-icons in Outlook at runtime
I think the issue is that my replacement Outlook Form Region is blank so the message is not able to be previewed.
If this is true than here's my question. What is the best way to export the standard IPM.Note message class template into visual Studio. I thing I need to overwrite my IPM.Note.Internet Outlook Form Region design.
There is an option when creating an Outlook Form Region-
To import an ".OFS" file. I was attempting to figure out how to export the file from the Outlook 2010 Client (Developer Tools) but I can't find a way to save the templates to that specific format. I can save to OFT (office template) but not .OFS
Thanks in advance for any help!
Rather then adding a form region and changing the message class I just ended up adding the PR_ICON_INDEX property and setting it's value. As outlined here in option #2 by Dmitry Link
There are many icons to choose from here. I couldn't locate a list with the integer values so I just entered random numbers for the PR_ICON_INDEX property in Outlook Spy changing the value till located the icon I wanted. There are many icons to choose from. Many from the 600-700 and 1000 and up range.
Here's the line I used to set the PR_ICON_INDEX property on the message-
mailitem.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x10800003", 4); // change the 4 to something like 600,601...etc to experiment
I wonder if it's possible with the .net framework or Microsoft.Office.Interop.Outlook to load an email message (*.msg), do a search and replace and send it from C#.
It's all happening on the server so Outlook cannot be installed.
What I've tried
the Redemption library but somehow it loses the images inlined in the template and can't figure out to remedy this
Using Microsoft.Office.Interop.Outlook
Application objOutlook = new Application();
objOutlook.CreateItemFromTemplate("c:\temp\..",)
But it expects as it second parameter an outlook folder, I can't give it a file path where it will save to
I'm thinking to switch to regular txt files instead of C# but maybe someone did this already
Update 1
This is the redemption code I tried. The problem is that the formatting and image (of a signature is not preserved)
using Interop.Redemption;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Replace(#"mailnonunicode.msg");
Replace(#"mailunicode.msg");
Replace(#"mailtemplate.oft");
}
static void Replace(string cTestharnessKmailMsg)
{
RDOSession rdoSession = new RDOSession();
RDOMail messageFromMsgFile = rdoSession.GetMessageFromMsgFile(cTestharnessKmailMsg);
messageFromMsgFile.Body = messageFromMsgFile.Body.Replace("abc",
"xyz");
messageFromMsgFile.Save();
}
}
}
Update 2 / Solution
If you want to preserve the formatting, you need to work with HTMLBody or RTFBody properties, not with the plain text Body.
What is your existing Redemption code?
If the message needs to be sent, it must be created in one of the Outlook folders - a standalone MSG file cannot be sent.