Failed to access mail object MAPI from calling function - c#

I'm going to access Outlook MAPI folder and get mail address.Here is my method
public static string GetSenderEmailAddress(Microsoft.Office.Interop.Outlook.MailItem mapiObject)
{
Microsoft.Office.Interop.Outlook.PropertyAccessor oPA;
string propName = "http://schemas.microsoft.com/mapi/proptag/0x0065001F";
oPA = mapiObject.PropertyAccessor;
string email = oPA.GetProperty(propName).ToString();
return email;
}
When button click event called,i need to fire that method and retrieve mail address.
Button click event is here.
private void button3_Click(object sender, RibbonControlEventArgs e)
{
string mailadd = ThisAddIn.GetSenderEmailAddress(Microsoft.Office.Interop.Outlook.MailItem);
System.Windows.Forms.MessageBox.Show(mailadd);
}
Error goes here
Microsoft.Office.Interop.Outlook.MailItem is a 'type'which is not valid in the given context
This is my first addin,Does anyone know how to achieve this result?

You can use the RibbonControlEventArgs to access the Context which will provide you the MailItem instance.
private Outlook.MailItem GetMailItem(RibbonControlEventArgs e)
{
// Inspector Window
if (e.Control.Context is Outlook.Inspector)
{
Outlook.Inspector inspector = e.Control.Context as Outlook.Inspector;
if (inspector == null) return null;
if (inspector.CurrentItem is Outlook.MailItem)
return inspector.CurrentItem as Outlook.MailItem;
}
// Explorer Window
if (e.Control.Context is Outlook.Explorer)
{
Outlook.Explorer explorer = e.Control.Context as Outlook.Explorer;
if (explorer == null) return null;
Outlook.Selection selectedItems = explorer.Selection;
if (selectedItems.Count != 1) return null;
if (selectedItems[1] is Outlook.MailItem)
return selectedItems[1] as Outlook.MailItem;
}
return null;
}
You can add this method and then make use of it like so...
string mailAddress = string.Empty;
Outlook.MailItem mailItem = GetMailItem(e);
if (mailItem != null)
mailAddress = ThisAddIn.GetSenderEmailAddress(mailItem);

Related

VSTO Outlook Plugin - SelectionChangeEventHandler only fire on startup

I plan to retrieve the mail item of the selected email on every chance of selected outlook email, but the event handle only gets triggered on startup, and sometimes properly. I can't seem to find what's causing the issue, most forums leads to a dead end, hence this post.
Anyway, here's a snippet of my Startup method:
private void Main_Startup(object sender, System.EventArgs e)
{
this.Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
Outlook.Explorer currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
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);
}
and here's a snippet of my CurrentExplorer_Event method:
private void CurrentExplorer_Event()
{
newSelectedEmail = new Email();
Outlook.MAPIFolder selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
Object selObject = this.Application.ActiveExplorer().Selection[1];
if (selObject is Outlook.MailItem)
{
Outlook.MailItem mailItem = (selObject as Outlook.MailItem);
GetEmailInfoFromOutlookEmail(mailItem);
}
}
}
catch (Exception ex)
{
Operations.SaveLogToFile(LogType.Error, "Main - CurrentExplorer_Event", ex.Message, ex.StackTrace);
}
}
Any help is greatly appreciated. Thank you!
The variable raising the events (currentExplorer) is a local variable. As soon as it goes out of scope, it becomes eligible to be released by the Garbage Collector. As soon as that happens, no events are raised.
Move the declaration of that variable to the class level.

Prevent MailItem.Reply from opening Inspector window in Outlook 2016

I am building a addin for Outlookto add custom signature in outlook email, when the user click on "Reply" button.
As soon as user click on reply button in explorer, a new inspector opens and i close the inspector with code (which s#cks). There may be a way to totally disable the reply inspector from opening.
private Microsoft.Office.Tools.CustomTaskPane CustomTaskPane;
UserDetail usr = null;
Outlook.Explorer currentExplorer = null;
Outlook.MailItem mailItem;
private Inspector replyInspector;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange +=
new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
if (this.Application.ActiveExplorer().Selection.Count == 1
&& this.Application.ActiveExplorer().Selection[1] is Outlook.MailItem)
{
if (mailItem != null)
{
// when the reply button is clicked
((Outlook.ItemEvents_10_Event)mailItem).Reply -= new Outlook.ItemEvents_10_ReplyEventHandler(MailItem_Reply);
// When an item is selected
Outlook.Selection mySelection = this.Application.ActiveExplorer().Selection;
Outlook.MailItem mailitem = null;
foreach (Object obj in mySelection)
{
if (obj is Outlook.MailItem)
{
mailitem = (Outlook.MailItem)obj;
if (mailitem != null)
{
if (mailitem.Sent)
{
else
{
// Compose
}
}
}
}
}
mailItem = this.Application.ActiveExplorer().Selection[1];
((Outlook.ItemEvents_10_Event)mailItem).Reply += new
Outlook.ItemEvents_10_ReplyEventHandler(MailItem_Reply);
// Close Inspector
replyInspector.Close(OlInspectorClose.olDiscard);
}
else
{
}
}
void MailItem_Reply(Object response, ref bool cancel)
{
try
{
MailItem mitem = (Outlook.MailItem)response;
replyInspector = (mitem).GetInspector;
replyInspector.Activate();
(mitem).HTMLBody = tempSignature + ((Outlook.MailItem)response).HTMLBody;
}
catch (System.Exception e)
{
MessageBox.Show(e.ToString());
}
}
Firstly, why would you want to close the inspector if you are opening it anyway? Why not insert the signature when the inspector is opened?
Secondly, you cannot concatenate two HTML strings and expect the resulting string to be valid HTML, The two needs to be merged. Or, better yet, use Word Object Model (Word.Document is returned from Inspector.WordEditor) to insert any text anywhere in the message body.

Outlook 2010 Addin - change phrase to link without altering email body

I've created simple addin for Outlook 2010 that replace specific phrase with link, for example I want to replace ABC12345 with http://www.example.com?id=123456
I'm using this code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}
void Inspectors_NewInspector(Outlook.Inspector Inspector)
{
var mailItem = Inspector.CurrentItem as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID != null)
{
string pattern = #"ABC(?<number>\d{1,6})";
var match = Regex.Match(mailItem.HTMLBody, pattern);
if (match.Success)
{
var replaced = Regex.Replace(mailItem.HTMLBody, pattern, m => "ABC"+ m.Groups["number"].Value+"");
mailItem.HTMLBody = replaced;
}
}
}
}
However I have two issues:
I must double click email in mailbox to have my event fired. I want to display that link when previewing emails (moving up and down in mailbox)
My code is replacing content, so Outlook "thinks" I've made some changes and when I want to close window it asks if I want to save those changes.
I don't want to alter body of email, I want to change phrase ABC123456 into link.
EDIT1:
I've tried using ActiveExplorer, this allows me to access email in preview window, but when I change email body those changes are saved. My intention is to change how specific text is displayed (change it to link), but not to alter email body on serwer.
I want those changes to be visible in my instance of Outlook, not saved on server (mailItem.HTMLBody.Replace does that).
Can I access view that displays email and alter that view?
This is the code:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
var selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
var selObject = this.Application.ActiveExplorer().Selection[1];
if (selObject is Outlook.MailItem)
{
Outlook.MailItem mailItem = (selObject as Outlook.MailItem);
mailItem.HTMLBody = mailItem.HTMLBody.Replace("ABC", "DEF");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
EDIT2
I'm able to get WordEditor inside Outlook, but I can't add hyperlink.
Last think I want now is to find specific phrases in email and add hyperlink to them. Here is my current code:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
var selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
var selectedObject = this.Application.ActiveExplorer().Selection[1];
if (selectedObject is Outlook.MailItem)
{
var mail = (selectedObject as Outlook.MailItem);
var inspector = mail.GetInspector;
if (inspector.IsWordMail())
{
var document = (Document)inspector.WordEditor;
if (document != null)
{
var app = document.Application;
var find = document.Range().Find;
find.Text = "ABC";
while (find.Execute())
{
var rng = find.Parent as Range;
rng.Hyperlinks.Add(rng, "http://example.com/?query=" + rng.Text );
rng.Collapse(WdCollapseDirection.wdCollapseEnd);
}
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}

Outlook VSTO in ItemAdd event handler creating new mailitem always has null wordeditor

I'm trying to create an Outlook add-in that processes a certain MailItem and forwards the result on to another group of people. In order to do the processing, I believe I need to use the WordEditor in order to get the proper formatting, but when I try to access that object, it returns null. I'm able to send the mail properly when I don't access the WordEditor, so it's probably something simple I've overlooked. How can I access the WordEditor for this new MailItem?
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)
{
string filter = "Filter";
if (Item is Outlook.MailItem)
{
Outlook.MailItem mail = (Outlook.MailItem)Item;
if (Item != null)
{
if (mail.MessageClass == "IPM.Note" &&
mail.Subject.ToUpper().Contains(filter.ToUpper())
&& mail.Attachments.Count == 1)
{
Outlook.Attachments attachments = mail.Attachments;
if (attachments != null)
{
Outlook.Attachment file = attachments[1];
//Process attachment...
Outlook.MailItem newMail = this.Application.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.Inspector insp = newMail.GetInspector;
insp.Activate();
newMail.Subject = "Subject";
newMail.To = "email#example.com";
Word.Document emailBody = insp.WordEditor as Word.Document;
//emailBody is always null
newMail.Send();
System.Runtime.InteropServices.Marshal.ReleaseComObject(newMail);
System.Runtime.InteropServices.Marshal.ReleaseComObject(file);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(attachments);
}
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(mail);
}
}
Set the MailIten.HTMLBody appropriately without using the Inspector object and the Word Object Model.

Get attachment from current email

I am creating a outlook 2013 add-on with C# and Visual Studio 2012 and I want to get the attachment file from the current (open) mail window when a button clicked and save it to a local directory.
Is there any example for this action?
Thank you.
First you would need to get the object of the current mail item. After that you can just loop through the .Attachments of the mail item and save them with .SaveAsFile(filePath).
var _thisApp = this.Application;
Outlook.MailItem _email;
// Get current email
if(_thisApp.ActiveWindow() is Outlook.Inspector)
{
Outlook.Inspector insp = _thisApp.ActiveWindow() as Outlook.Inspector;
_email = insp.CurrentItem as Outlook.MailItem;
}
else if(_thisApp.AcitveWindow() is Outlook.Explorer)
{
Outlook.Explorer exp = _thisApp.ActiveExplorer();
if(exp.Selection.Count > 0)
_email = exp.Selection[1] as Outlook.MailItem;
}
// Loop through the attachments
foreach(Outlook.Attachment attachment in _email.Attachments)
{
// Some other stuff
string filePath = #"C:\Saved Attachments\" + attachment.FileName;
attachment.SaveAsFile(filePath);
}
EDIT: Sample to retrieve this.Application
private Outlook.Application _thisApp;
private Outlook.Inspectors _inspectors;
// Function in ThisAddin.cs
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
_thisApp = this.Application;
_inspectors = _thisApp.Inspectors;
_inspectors.NewInspector +=
new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}

Categories