Get attachment from current email - c#

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);
}

Related

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.

Outlook 2010 addins for automatic email-attachment extraction

Outlook 2010 add in for auto extraction of attachment from the configured email ids on outlook 2010.For each configured email ids there will be a separate folder in which it's attachments will be saved automatically.I don't want to click any button or reload it all the times.If a mail arrives in the inbox folder,if it's unread, it's attachments will be extracted and saved in its respective folder.
My problem is that i haven't been able to extract the attachments of non-default email ids on outlook 2010 and also my process is not automatically extracting the attachment.
How can i make the unread mail's attachment extraction and saving automatic for multiple configured email ids on outlook 2010? Here i'm attaching the code which i have tried....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
using System.IO;
namespace ITAPOutlookAddIn
{
public partial class ThisAddIn
{
public void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.NewMail += new Microsoft.Office.Interop.Outlook
.ApplicationEvents_11_NewMailEventHandler(ThisApplication_NewMail);
this.Application.NewMail += new Microsoft.Office.Interop.Outlook
.ApplicationEvents_11_NewMailEventHandler(ThisApplication_NewMailStatus);
}
public void ThisApplication_NewMail()
{
const string destinationDirectory = #"C:\TestFileSave";
const string destinationDirectory2 = #"C:\TestFileForm";
if (!Directory.Exists(destinationDirectory))
{
Directory.CreateDirectory(destinationDirectory);
}
if (!Directory.Exists(destinationDirectory2))
{
Directory.CreateDirectory(destinationDirectory2);
}
Outlook.MAPIFolder inBox = this.Application.ActiveExplorer()
.Session.GetDefaultFolder(Outlook
.OlDefaultFolders.olFolderInbox);
Outlook.Items inBoxItems = inBox.Items;
Outlook.MailItem newEmail = null;
inBoxItems = inBoxItems.Restrict("[Unread] = true");
try
{
foreach (object collectionItem in inBoxItems)
{
newEmail = collectionItem as Outlook.MailItem;
if (newEmail == null)
continue;
if (newEmail != null)
{
if (newEmail.ReceivedByName == "Sumit Ray")
{
if (newEmail.Attachments.Count > 0)
{
for (int i = 1; i <= newEmail
.Attachments.Count; i++)
{
string filepath = Path.Combine(destinationDirectory, newEmail.Attachments[i].FileName);
string Sname = newEmail.SentOnBehalfOfName;
string timestamp = newEmail.ReceivedTime.ToString("MMddyyyy.HHmmss");
string result = filepath + Sname + timestamp + ".docx";
newEmail.Attachments[i].SaveAsFile(result);
// newEmail.Attachments[i].SaveAsFile
// (#"C:\TestFileSave\" +
// newEmail.Attachments[i].FileName);
}
}
} //end of inner-if
} //end of outer-if
} //end of for-each
}//end of try
catch (Exception ex)
{
Console.WriteLine(ex);
string errorInfo = (string)ex.Message
.Substring(0, 11);
if (errorInfo == "Cannot save" && newEmail.SenderName == "Sumit Ray")
{
MessageBox.Show(#"Create Folder C:\TestFileSave");
}
} //end of catch void ThisApplication_NewMailStatus()
{
Outlook.NameSpace outlookNameSpace = this.Application.GetNamespace("MAPI");
Outlook.MAPIFolder inbox = outlookNameSpace.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderInbox);
// Mark each unread message from Jeff Hay with a yellow flag icon.
Outlook.Items unreadMailItems =
inbox.Items.Restrict("[Unread]= true");
// if (Convert.ToBoolean(unreadMailItems)
if(unreadMailItems.Equals(true))
{
ThisApplication_NewMail();
}
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
Do you mean you need to read unread messages from a non-default store? Instead of using outlookNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox), loop through the Namespace.Stores collection and call Store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).

Failed to access mail object MAPI from calling function

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);

Categories