I am developing an Outlook add-in using VSTO that checking spelling of the mail content while composing.
In Reply mails, How can I check only the reply content by excluding the old conversation ?
This is what I am doing now.But I need to know whether there is any proper object or method to get current reply content.
Outlook.MailItem mailItem = inspector.CurrentItem as Outlook.MailItem;
string temp = mailItem.Body;
int target= temp.IndexOf("\r\nFrom:");
string contentToCheck= temp.Substring(0, target);
There is no built in property that signifies the end of the new message and the start of a reply in body text.
What can be done is store common text that marks the end of the new message and check for that when reading the body. Things like ' FROM:', 'Regards,' 'Thanks,'...
Something similar to:
while ((line = bodytext.ReadLine()) != null)
{
foreach(string ending in MYLISTOFCOMMONENDINGS)
{
if (line.StartsWith(ending))
return sb.ToString(); //we are done
//here sb is a string builder consuming new lines
}
//read the line and check spelling
}
Look for the bookmark named "_MailOriginal". The script below inserts text just before the original message begins:
set objDoc = Application.ActiveInspector.WordEditor
If objDoc.Bookmarks.Exists("_MailOriginal") Then
' is there the original email? (_MailOriginal)
set objBkm = objDoc.Bookmarks("_MailOriginal")
Set objSel = objDoc.Application.Selection
objSel.Start = objBkm.Start-2 'give room for the line break before. It includes the line
objSel.End = objSel.Start
objSel.Text = "test"
End If
Related
I am trying to create an outlook add-in in C# which collects header information from new emails in the inbox. Googling it says to use the following code to get the header information for the email.
mailitem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F/")
However when I use this the error Object reference not set to an instance of an object. Click the schema address also says the resource is no longer there is there another way of getting this or do I need to use a different language?
For reference I have added the below.
private void Quarantine()
{
Outlook.MAPIFolder inBox = (Outlook.MAPIFolder)this.Application.
ActiveExplorer().Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items items = (Outlook.Items)inBox.Items;
Outlook.MailItem MailItem = null;
items.Restrict("[UnRead] = true");
var destFolder = inBox.Folders["test"];
string StrRegex = #"(Final Score - [-][0-9] | Final Score - [2][0 - 1] | Final Score - [0 - 1][0-9])";
Regex Reg = new Regex(StrRegex);
foreach (object email in items)
{
MailItem = email as Outlook.MailItem;
String Header= MailItem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F/");
if (!(Reg.IsMatch(Header)))
{
MailItem.Move(destFolder);
}
}
}
}
as operator will return null is the object is not a MailItem. Your code never checks for that. You can have objects other than MailItem in the Inbox folder, such as ReportItem, MeetingItem, etc.
I'm programming an outlook add-in.
I want to modify the mail before it gets sent. Therefore I have registered me for an event before the email gets sent. I can modify it but when I m trying to change the recipient of the mail (so mail.To) it gives me an error (not while my code is running but when outlook tries to sent the mail).
Error says: '...Can not resolve the receivername' (i have translated it so it is not the real error text but close to it)
Here is my code:
void Application_ItemSend(object item, ref bool cancel)
{
if (item is Outlook.MailItem mail)
{
var to = mail.To;
var body = mail.Body;
var editedBody = to + "#" + body;
mail.Body = editedBody;
mail.To = #"<another email>";
}
}
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
//Register the new event
Globals.ThisAddIn.Application.ItemSend += Application_ItemSend;
}
You are resetting all To recipients. Is that what you really want to do? Try to use MailItem.Recipients.Add (retuns Recipient object) followed by Recipient.Resolve.
You are also setting the plain text Body property wiping out all formatting. Consider using HTMLBody instead, just keep in mind that two HTML strings must be merged rather than concatenated to produce valid HTML.
You need to cancel the action by setting the cancel parameter to true and schedule re-sending operation with a new email address. A timer which fires the Tick event on the main thread can help with that task.
Also you may consider making a copy of the email, changing recipients (do any changes on the copy) and submit it. In that case you will have to differentiate such messages and skip them in the ItemSend event handler. To get that working you may use UserProperties.
Got it working:
var to = string.Empty;
mail.Recipients.ResolveAll();
foreach (Outlook.Recipient r in mail.Recipients)
{
to += r.Address + ";";
}
if (to.Length > 0)
to = to.Substring(0, to.Length - 1);
mail.Body = to + "#" + mail.Body;
//Modify receiver
mail.To = string.Empty;
Outlook.Recipient recipient = mail.Recipients.Add("<email>");
recipient.Resolve();
I need to save permanently some custom information inside an Outlook Mailitem and retrieve them back.
My case scenario is the following: I select an email in Outlook 2013 explorer, write inside that email some information, save it on my disk as .msg file, delete the email from the Inbox Outlook folder, open the .msg file as Outlook.MailItem and read that information in order to keep them or change them.
I'm using the Outlook.ItemProperties.Add() method to add a custom ItemProperty inside the selected MailItem.
When I get a MailItem from the .msg I'm not able to find that properties.
I've used OutlookSpy->Miscellaneous->OpenIMsgOnIstg function to check the .msg and I've noted that all properties are in the GetProps tab.
My question is: How can I read the properties?
Here is the code to write the properties and save the mail as .msg:
Outlook.Application outApp= new Outlook.Application();
Outlook.MailItem mail= null;
try { mail = (Outlook.MailItem)outApp.ActiveInspector().CurrentItem; }
catch {
if (outApp.ActiveExplorer().Selection.Count > 0)
mail = (Outlook.MailItem)outApp .ActiveExplorer().Selection[1];
else { // ERROR }
}
Outlook.ItemProperty prop01 = mail.ItemProperties.Add("MyProperty01", Outlook.OlUserPropertyType.olText);
prop01.Value = "hola";
Outlook.ItemProperty prop02 = mail.ItemProperties.Add("MyProperty02", Outlook.OlUserPropertyType.olNumber);
prop02.Value = 23;
mail.Save();
mail.SaveAs(#"C:\WorkSpace\mail.msg", Outlook.OlSaveAsType.olMSG);
if (mail != null) Marshal.ReleaseComObject(mail);
if (outlookObj != null) Marshal.ReleaseComObject(outApp );
Here is my code to read the properties from the .msg after I've deleted the email in Outlook:
Outlook.Application outApp= new Outlook.Application();
Outlook.MailItem msgMail=(Outlook.MailItem)outApp.CreateItem(Outlook.OlItemType.olMailItem);
msgMail = (Outlook.MailItem)outApp.Session.OpenSharedItem(#"C:\WorkSpace\mail.msg");
Outlook.ItemProperties mailProps = msgMail.ItemProperties;
Outlook.ItemProperty pr = mailProps["MyProperty01"]; // pr IS NULL
But OutlookSpy shows the properties are in the .msg file.
I have solved my problem following this bypassing solution.
Use Mailitem.PropertyAccessor.GetProperty and pass the DASL property name shown by OutlookSpy (I am its author).
I am setting the property (for making them As Read and with High Importance) of the mail those are coming to the MS Outlook 2010 inbox using below code -
Microsoft.Office.Interop.Outlook.Application myApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
int i = myInbox.Items.Count;
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[i]).UnRead = false;
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[i]).Importance = OlImportance.olImportanceHigh;
This works fine when only one mail comes at a time (I can see the mail as Read and with High Importance) after the code execution but when three or four mails coming at a time then it set the property of only one mail not for all the three or four mails.
Please suggest.
Remember to save the message after setting any property.
Most importantly, your code uses multiple dot notation - for each ".", you get back a brand new COM object, so you end up setting Importance property on an object different from the one used to set the UnRead property.
int i = myInbox.Items.Count;
MailItem msg = (Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[i];
msg.UnRead = false;
msg.Importance = OlImportance.
msg.Save();
Another problem is that you assume that the last item in the Items collection is the latest one. This is not generally true. As cremor suggested, use Items.ItemAdd event, but still do not forget to save the message.
You can use the ItemAdd event of the Items property of the folder:
Items inboxItems = myInbox.Items;
inboxItems.ItemAdd += HandleItemAdded;
private void HandleItemAdded(object item)
{
MailItem mail = item as MailItem;
if (mail == null) { return; }
mail.UnRead = false;
mail.Importance = OlImportance.olImportanceHigh;
}
I want to be able to reply to an email inline, from within my program, but calling the reply function seems to only fill in the To: and Subject: field for me. I can't seem to find anything online about it and it doesn't seem to have an overload that turns on inline replies.
I found that each MailItem has a Conversation so I'm wondering if I have to manually do the inline reply? (I would really like to avoid that, it would be a pain to iterate through a conversation, some of ours can be hundreds of emails long).
I found that this code helped make this happen;
Document oldDoc = itemToReplyTo.GetInspector.WordEditor;
Document newDoc = newMailItem.GetInspector.WordEditor;
if (oldDoc != null)
{
Microsoft.Office.Interop.Word.Selection oldSelect = oldDoc.Windows[1].Selection;
Microsoft.Office.Interop.Word.Selection newSelect = newDoc.Windows[1].Selection;
oldSelect.Find.Execute("From:");
oldSelect.Collapse(WdCollapseDirection.wdCollapseStart);
oldSelect.MoveEnd(WdUnits.wdStory, 1);
oldSelect.Copy();
newSelect.Move(WdUnits.wdStory, 1);
newSelect.InlineShapes.AddHorizontalLineStandard();
newSelect.Paste();
newSelect.Move(WdUnits.wdStory, -1);
newSelect.InsertAfter("Reply Text here");
newSelect.Find.ClearFormatting();
newSelect.Find.Execute(mailItem.SenderEmailAddress);
}
I tried the below and it worked for me using Outlook 2010.
Outlook.MailItem reply1 = mailItem.Reply();
//prepend text to email
reply1.HTMLBody = "<html><body><strong>Test Body</strong><p><p></body></html>" + reply1.HTMLBody;
reply1.Display(false); //display message or .Send() to send