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).
Related
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());
}
}
The following is an add-in for MS Outlook. One can scan the body of an e-mail and if there is a certain (specific word or pattern) word present, then a MessageBox appears. However, I am wondering if it is possible to change the way a word appears or to edit the text in the body of email, without MessageBox whatsoever. For example, a word (such as the name of the company) can be converted into an hyperlink (i.e. Google to www.google.com or Microsoft to www.microsoft.com) and the user who reads emails on Outlook always sees the hyperlink instead of the word itself.
using System;
using System.IO;
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.Drawing;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace FirstOutlookAddIn
{
public partial class ThisAddIn
{
public static string[] data = new string[10];
public static Stopwatch timer = new Stopwatch();
Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder inbox;
Outlook.Items items;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
timer = Stopwatch.StartNew(); ReadMail();
outlookNameSpace = this.Application.GetNamespace("MAPI");
inbox = outlookNameSpace.GetDefaultFolder(
Microsoft.Office.Interop.Outlook.
OlDefaultFolders.olFolderInbox);
items = inbox.Items;
items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(ReadSingleMail); // Modified method to run for single email
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// Hinweis: Outlook löst dieses Ereignis nicht mehr aus. Wenn Code vorhanden ist, der
// ausgeführt werden muss, wenn Outlook geschlossen wird, informieren Sie sich unter http://go.microsoft.com/fwlink/?LinkId=506785
}
static void ReadSingleMail(dynamic item)
{
string bodyText; // Email body
string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); //Path to My Documents
if (item != null)
{
bodyText = item.Body;
}
else
{
return; // If no e-mail body, exit function.
}
}
static void ReadMail()
{
//Set up OCR
string bodyText;
string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//Get unread emails from Inbox
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items unreadItems = inboxFolder.Items.Restrict("[Unread]=true");
int max_runs;
//Go through each Unread email
if (unreadItems.Count > 10) { max_runs = 10; }
else max_runs = unreadItems.Count;
for (int counter = 1; counter <= max_runs; counter++)
{
//Reinitialize Data array
for (int index = 0; index <= 8; index++)
{
data[index] = "";
}
dynamic item = unreadItems[counter];
bodyText = item.Body;
Match match = Regex.Match(bodyText, "Insert searched pattern here");
if (match.Success)
{
MessageBox.Show(match.Value);
match = match.NextMatch();
}
}
}
#region Von VSTO generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
Creating the function ReadMail() as below replaces text, as I want it.
static void ReadMail(){
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items Items = inboxFolder.Items.Restrict("[LastModificationTime] > '01/1/2003'");
foreach (var item in Items){
var mail = (Outlook.MailItem)item;
mail.Body = mail.Body.Replace("Text to be replaced", "Replacing text");
mail.Save();
}
}
I made it so that you can open a dll and load it onto a listbox as a clickable item when once clicked, the plugin would load and you can execute that plugin.
I added a clear button that is suppose to clear the app of the currently loaded plugins.
It clears everything off the app but when I go to load them again, it loads duplicates.
How do I clear the assembly too so that when i reload a plugin, it will not duplicate??
Code Behind:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using PluginContracts;
using System;
using System.IO;
using Microsoft.Win32;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.Diagnostics;
using System.Linq;
namespace SimplePlugin
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Dictionary<string, IPlugin> _Plugins; // move to class scope
public MainWindow()
{
InitializeComponent();
_Plugins = new Dictionary<string, IPlugin>();
}
private void AssembleComponents(object sender)
{
string selection = "";
if (sender is ListBox)
{
if (((ListBox)sender).SelectedValue != null)
selection = ((ListBox)sender).SelectedValue.ToString();
}
string path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
DirectoryCatalog cat = new DirectoryCatalog(path);
//ICollection<IPlugin> plugins = PluginLoader.LoadPlugins("Plugins");
ICollection<IPlugin> plugins = GenericPluginLoader<IPlugin>.LoadPlugins("Plugins");
foreach (var item in plugins)
{
//add only if not already present
if (!_Plugins.ContainsKey(item.Name))
{
string dllName = GetDLLName(item.Name);
Button b = new Button()
{
Name = dllName.Replace(".", "").ToUpper(),
Content = item.Name,
Visibility = System.Windows.Visibility.Hidden
};
b.Click += b_Click;
PluginGrid.Children.Add(b);
_Plugins.Add(item.Name, item);
// this.PluginGrid.Children.Clear();
//by Vasey
}
}
// make visible the selected plugin button
foreach (var ctl in PluginGrid.Children)
{
if (ctl is Button)
{
Button button = (Button)ctl;
if (button.Name.Equals(selection.Replace(".", "").ToUpper()))
{
button.Visibility = System.Windows.Visibility.Visible;
}
else
{
button.Visibility = System.Windows.Visibility.Hidden;
}
}
}
}
private void b_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
if (b != null)
{
string key = b.Content.ToString();
if (_Plugins.ContainsKey(key))
{
IPlugin plugin = _Plugins[key];
plugin.Do();
}
}
}
private void addPlugin_Click(object sender, RoutedEventArgs e)
{
var fileDialog = new OpenFileDialog();
fileDialog.Multiselect = true;
fileDialog.Filter = "All files (*.*)|*.*|DLL files (*.dll)|*.dll|CS Files (*.cs)|*.cs";
if (fileDialog.ShowDialog() == true)
{
string filename = fileDialog.FileName;
var ext = System.IO.Path.GetExtension(filename);
// ListBox lbFiles = new ListBox();
//this.Controls.Add(lbFiles);
//lbFiles.Size = new System.Drawing.Size(200, 100);
//lbFiles.Location = new System.Drawing.Point(10, 10);
lbFiles.Items.Add(System.IO.Path.GetFileName(filename));
//
CopyToDir(filename);
}
}
private void CopyToDir(string filename)
{
// txtBox.Text = "Hello World";
string path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
Console.WriteLine(path);
//Check the directory exists
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
try
{
FileInfo fi = new FileInfo(filename);
if (!File.Exists(System.IO.Path.Combine(path, fi.Name)))
{
File.Copy(fi.FullName, System.IO.Path.Combine(path, fi.Name));
}
}
catch (Exception ex)
{
throw ex;
}
}
// Get linkage between ListBox's DLL name list and the loaded plugin names
string GetDLLName(string name)
{
string ret = "";
name = name.Replace(" ", ""); // strip spaces
Assembly asm = AppDomain.CurrentDomain.GetAssemblies().
SingleOrDefault(assembly => assembly.GetName().Name == name);
if (asm != null)
{
ret = Path.GetFileName(asm.Location);
}
return ret;
}
private void lbFiles_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
AssembleComponents(sender);
}
private void ClearBtn_Click(object sender, RoutedEventArgs e)
{
lbFiles.Items.Clear();
_Plugins = new Dictionary<string, IPlugin>();
}
}
}
I just had to add this function to the clearBtn method
//Clears the Assembly
this.PluginGrid.Children.Clear();
Before
private void ClearBtn_Click(object sender, RoutedEventArgs e)
{
lbFiles.Items.Clear();
_Plugins = new Dictionary<string, IPlugin>();
}
After
private void ClearBtn_Click(object sender, RoutedEventArgs e)
{
// Clears the ListBox
lbFiles.Items.Clear();
//Clears the Assembly
this.PluginGrid.Children.Clear();
//Loads next Assembly
_Plugins = new Dictionary<string, IPlugin>();
}
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);
}
Hello I want to use FileSystemWatcher in C Sharp to watch for the text files coming in a folder Reading There Text and uploading Their text to a Web Server with a GET Request in C Sharp
but the problem is that when i try it and first time when some file opened it works fine but on second time when a file come to the directory it will show me that the file is already used by another application or the resource is not free its already allocated.
here is the small code for it
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
namespace FileChangeNotifier
{
public partial class frmNotifier : Form
{
private StringBuilder m_Sb;
private bool m_bDirty;
private System.IO.FileSystemWatcher m_Watcher;
private bool m_bIsWatching;
public frmNotifier()
{
InitializeComponent();
m_Sb = new StringBuilder();
m_bDirty = false;
m_bIsWatching = false;
}
private void btnWatchFile_Click(object sender, EventArgs e)
{
if (m_bIsWatching)
{
m_bIsWatching = false;
m_Watcher.EnableRaisingEvents = false;
m_Watcher.Dispose();
btnWatchFile.BackColor = Color.LightSkyBlue;
btnWatchFile.Text = "Start Watching";
}
else
{
m_bIsWatching = true;
btnWatchFile.BackColor = Color.Red;
btnWatchFile.Text = "Stop Watching";
m_Watcher = new System.IO.FileSystemWatcher();
if (rdbDir.Checked)
{
m_Watcher.Filter = "*.*";
m_Watcher.Path = txtFile.Text + "\\";
}
else
{
m_Watcher.Filter = txtFile.Text.Substring(txtFile.Text.LastIndexOf('\\') + 1);
m_Watcher.Path = txtFile.Text.Substring(0, txtFile.Text.Length - m_Watcher.Filter.Length);
}
if (chkSubFolder.Checked)
{
m_Watcher.IncludeSubdirectories = true;
}
m_Watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
m_Watcher.Created += new FileSystemEventHandler(OnChanged);
m_Watcher.EnableRaisingEvents = true;
}
}
private void OnChanged(object sender, FileSystemEventArgs e)
{
if (!m_bDirty)
{
readFile(e.FullPath);
m_Sb.Remove(0, m_Sb.Length);
m_Sb.Append(e.FullPath);
m_Sb.Append(" ");
m_Sb.Append(e.ChangeType.ToString());
m_Sb.Append(" ");
m_Sb.Append(DateTime.Now.ToString());
m_bDirty = true;
}
}
private void readFile(String filename) {
String line = "";
if (File.Exists(filename))
{
try{
StreamReader sr = new StreamReader(filename);
//code for multiline reading but i need only one line so i am going to change he code
/* while ((line = sr.ReadLine()) != null)
{
MessageBox.Show(line);
}
*/
line = sr.ReadLine();
MessageBox.Show(line);
uploadDataToServer(line);
sr.Close();
} catch(IOException e){
MessageBox.Show(e.Message);
}
}
}
private void uploadDataToServer(String data) {
String url = "http://209.90.88.135/~lilprogr/?data="+data;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream resStream = response.GetResponseStream();
}
}
}
To handle multiple change notifications, go here and look for #BaBu's answer.
Also,
If all you need is to read from the file,
Have you tried to open it in Shared Mode?