I am developing an addin using c#. I am able to receive notifications whenever i get any item in my inbox.
this.Application.NewMailEx += new Outlook.ApplicationEvents_11_NewMailExEventHandler(olApp_NewMail);
private void olApp_NewMail(String itemCollection)
{
string [] strNewItems;
strNewItems = itemCollection.Split(',');
foreach (string newItem in strNewItems)
{
Outlook.MailItem mail = (Outlook.MailItem)Application.Session.GetItemFromID(newItem, Type.Missing);
string old_subj = mail.Subject;
string old_body = mail.Body;
MessageBox.Show(old_subj);
}
}
but the problem is in the event handler i am not able to distinguish whether it is mail item or meeting item. How should i do it?
thanks in advance.
Regards,
Jeeva
Can you not do something like:
object item = Application.Session.GetItemFromID(newItem, Type.Missing);
Outlook.MailItem mailItem = item as Outlook.MailItem;
if (mailItem != null)
{
...
}
else
{
Outlook.MeetingItem meetingItem = item as Outlook.MeetingItem;
if (meetingItem != null)
{
...
}
}
Related
I have created a custom VSTO plugin in Outlook 2016 that asks the user to attach a file, the file is then added to an e-mail reply and automatically sent.
public void Attachment_Click(Office.IRibbonControl control)
{
Outlook.Explorer explorer = Globals.ThisAddIn.Application.ActiveExplorer();
if (explorer != null)
{
Outlook.Selection selection = explorer.Selection;
if (selection.Count >= 1)
{
Outlook.MailItem mailItem = selection[1] as Outlook.MailItem;
OpenFileDialog attachment = new OpenFileDialog();
attachment.Title = "Add your file";
attachment.ShowDialog();
if (mailItem != null) //could be something other than MailItem
{
Outlook.MailItem response = mailItem.ReplyAll();
bool retValue = false;
response.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
response.HTMLBody = "<p>MESSAGE</p>" + response.HTMLBody;
response.Attachments.Add(attachment.FileName, Outlook.OlAttachmentType.olByValue, 1,"Attachment.pdf");
response.Send();
mailItem.Delete();
}
}
}
}
I am attempting to tweak the code so it automatically adds a different attachment depending on the user logged in to Outlook, e.g. if user=user1#company.com add '\fileshare\file1.pdf', if user=user2#company.com add '\fileshare\file2.pdf'
Is this possible?
I am attempting to convert the current user address to string using the below but not had any success:
{
return
Globals.ThisAddIn.Application.ActiveExplorer().Session.CurrentUser.AddressEntry.GetExchangeUser().PrimarySmtpAddress.ToString();
}
Your code will fail if there is no active explorer, but you really do not need it.
Off the top of my head:
AddressEntry cu = Globals.ThisAddIn.Application.Session.CurrentUser.AddressEntry;
ExchangeUser eu = cu.GetExchangeUser();
return (eu == null) ? cu.Address : eu.PrimarySmtpAddress;
I have following requirement :
Allow the user to drag & drop an email from outlook to a datagrid
Prepare a reply mail, and show it so the user can review and send
After sending, also fetch the send mail and put it into the datagrid
The drag/drop I have working
Preparing the replay email and showing it to the user I also have working, with this code :
MailItem mail = GetMailBySubject(dateReceived, subject);
if (mail != null)
{
MailItem mailReply = mail.ReplyAll();
// add text and stuff to mailReply...
mailReply.Display();
}
This will open a window in outlook, as if the user clicked reply in outlook.
Now I am stuck with the 3th requirement,
after the user send the reply email, I need somehow to find this email in outlook to add it to my datagrid.
But I have no clue on how to do that.
All I have is the original mail that is been used to prepare the reply.
Is there a way to find the reply with only this, or is this maybe a complete wrong approach ?
To make it more difficult is that I have to show the reply email NON Modal, so I have no trigger when the user clicked on send in outlook.
for reference, here is the code for GetMailBySubject
private MailItem GetMailBySubject(DateTime dateReceived, string subject)
{
MailItem Result = null;
Microsoft.Office.Interop.Outlook.Application OutlookIns = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace olNamespace = OutlookIns.GetNamespace("MAPI");
MAPIFolder myInbox = olNamespace.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Items items = myInbox.Items;
int count = items.Count;
MailItem mail = null;
int i = 1; //DO NOT START ON 0
while ((i < count) && (Result == null))
{
if (items[i] is MailItem)
{
mail = (MailItem)items[i];
if ((mail.ReceivedTime.ToString("yyyyMMdd hh:mm:ss") == dateReceived.ToString("yyyyMMdd hh:mm:ss")) && (mail.Subject == subject))
{
Result = mail;
}
}
i++;
}
return Result;
}
EDIT
I tried this code as suggested, but the Items.ItemAdd event is not firing.
So I must still be doing something wrong but I cant see it
this is my code now
MailItem mail = GetMailBySubject((DateTime)sentOn, msg.Subject);
if (mail != null)
{
MailItem mailReply = mail.ReplyAll();
mailReply.HTMLBody = GetDefaultReplyText() + Environment.NewLine + mailReply.HTMLBody;
Guid guid = Guid.NewGuid();
UserProperties mailUserProperties = null;
UserProperty mailUserProperty = null;
mailUserProperties = mailReply.UserProperties;
mailUserProperty = mailUserProperties.Add("myproperty", OlUserPropertyType.olText);
mailUserProperty.Value = guid.ToString(); ;
// the code below gives error "The property cannot be parsed or has an invalid format"
//mailReply.PropertyAccessor.SetProperty("myproperty", guid.ToString());
mailReply.Display();
}
private MailItem GetMailBySubject(DateTime dateReceived, string subject)
{
MailItem Result = null;
Microsoft.Office.Interop.Outlook.Application OutlookIns = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace olNamespace = OutlookIns.GetNamespace("MAPI");
MAPIFolder myInbox = olNamespace.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Items items = myInbox.Items;
int count = items.Count;
MailItem mail = null;
int i = 1; //DO NOT START ON 0
while ((i < count) && (Result == null))
{
if (items[i] is MailItem)
{
mail = (MailItem)items[i];
if ((mail.ReceivedTime.ToString("yyyyMMdd hh:mm:ss") == dateReceived.ToString("yyyyMMdd hh:mm:ss")) && (mail.Subject == subject))
{
Result = mail;
MAPIFolder mySent = olNamespace.GetDefaultFolder(OlDefaultFolders.olFolderSentMail);
mySent.Items.ItemAdd += Items_SentMailItemAdd;
}
}
i++;
}
return Result;
}
and finally
private void Items_SentMailItemAdd(object Item)
{
//throw new NotImplementedException();
; // this event is never fired
}
You can use the Items.ItemAdd event on the Sent Items folder. To check if that is your message, set a custom property on the message that you create and display. You can use MailItem.UserProperties.Add, but that can force the message to be sent in the TNEF format. To prevent that from happening, you can use MailItem.PropertyAccessro.SetProperty to set a named MAPI property without using the UserProperties collection. You can set a test user property and look at its DASL name (to be used by SetProperty) with OutlookSpy (I am its author - select the message, click IMessage button, select your custom property, see the DASL edit box).
I am currently working on the below method which iterates through emails in my Inbox, but wonder how to filter them to focus on the ones with static subject such as : nice weather. Following searches I've thought folders.Items.Restrict() could help, however I've got condition is not valid on var fi = folder.Items.Restric("weather"). I've also tried
var fi = folder.Items.Find("[Subject] = weather"), to ensure the condition is valid,... but it ends up with no improvement.
Thanks in advance
static void IterateMessages(Outlook.Folder folder)
{
string[] extensionsArray = {".csv"};
//var fi = folder.Items;
var fi = folder.Items.Restrict("weather");
if (fi != null)
{
foreach (Object item in fi)
{
Outlook.MailItem mi = (Outlook.MailItem)item;
var attachments = mi.Attachments;
if (attachments.Count != 0)
{
if (!Directory.Exists(basePath)
{
Directory.CreateDirectory(basePath);
}
// Loop through each attachment
for (int i = 1; i <= mi.Attachments.Count; i++)
{
Console.WriteLine("Processing: {0}", mi.Attachments[i].FileName);
mi.Attachments[i].SaveAsFile(basePath);
Console.WriteLine("Attachment: {0}" + " Saved to Path", mi.Attachments[i].FileName);
}
}
}
}
}
Your Restrict parameter seems to be in a wrong format. Try this:
var fi = folder.Items.Restrict("#SQL=\"urn:schemas:httpmail:subject\" like '%weather%'";
More information
I am using below code to retrieve the different mail parameter from MS outlook 2010. but I am not able to get CC email address. CC property of MailItem class is returning Name, not email address.
NameSpace _nameSpace;
ApplicationClass _app;
_app = new ApplicationClass();
_nameSpace = _app.GetNamespace("MAPI");
object o = _nameSpace.GetItemFromID(EntryIDCollection);
MailItem Item = (MailItem)o;
string HTMLbpdyTest = Item.HTMLBody;
CreationTime = Convert.ToString(Item.CreationTime);
strEmailSenderEmailIdMAPI = Convert.ToString(Item.SenderEmailAddress);
strEmailSenderName = Item.SenderName;
Subject = Item.Subject;
string CCEmailAddress = Item.CC;
Please suggest, how can I get CC email addresses?
Loop through the MailItem.Recipients collection and for each Recipient object check its Type property; olCC is what you want. You can then read the Recipient.Address property.
EDIT: Off the top of my head.
foreach (Recipient recip in Item.Recipients)
{
if (recip.Type == OlMailRecipientType.olCC)
{
if (CCEmailAddress.length > 0) CCEmailAddress += ";";
CCEmailAddress += recip.Address;
}
}
I was inspired by #Dmitry's answer and tried a few things on my own to have these lines of code fix my problems and give me an array of the cc-ed addresses that are present in a given mail item.
public string[] GetCCAddress(MailItem mailItem)
{
string email;
Outlook.ExchangeUser exUser;
List <string> ccEmailAddressList = new List<string>();
foreach (Recipient recip in mailItem.Recipients)
{
if ((OlMailRecipientType)recip.Type == OlMailRecipientType.olCC)
{
email=recip.Address;
if (!email.Contains("#"))
{
exUser = recip.AddressEntry.GetExchangeUser();
email = exUser.PrimarySmtpAddress;
}
ccEmailAddressList.Add(email);
}
}
This statement if (!email.Contains("#")) is to avoid calling exUser.PrimarySmtpAddress on an actual email address and restrict that to entries such as " /O=EXG5/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=Test88067"
public static int ConnectToOutlook()
{
try
{
Outlook.Application oApp = new Outlook.Application();
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
oNS.Logon(Missing.Value, Missing.Value, false, true);
Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Parent;
List<string> ccRecipient = new List<string>();
foreach (MAPIFolder folder in oInbox.Folders)
{
if (folder.FullFolderPath.Contains("Inbox"))
{
foreach (MAPIFolder subFolder in folder.Folders)
{
try
{
if (subFolder.FullFolderPath.Contains("Folder Name Inside Inbox"))
{
foreach (object folderItems in subFolder.Items)
{
if (folderItems is Outlook.MailItem)
{
Outlook.MailItem email_Msg = (Outlook.MailItem)folderItems;
Console.WriteLine("Subject=>" + email_Msg.Subject);
//Console.WriteLine("From=>" + email_Msg.SenderEmailAddress);
//Console.WriteLine("Cc=>" + email_Msg.CC);
//Console.WriteLine("Recipients=>" + email_Msg.Recipients[1].Address);
foreach (Recipient recipient in email_Msg.Recipients)
{
if ((OlMailRecipientType)recipient.Type == OlMailRecipientType.olCC)
{
Console.WriteLine("Cc=>" + recipient.AddressEntry.GetExchangeUser().PrimarySmtpAddress);
}
}
}
}
}
}
catch (System.Exception error)
{
Console.WriteLine();
Console.WriteLine(error.Message);
}
}
}
}
}
catch (System.Exception e)
{
Console.WriteLine("{0} Exception caught: ", e);
}
return 0;
}
Try
Item.CC.Address
or
((MailAddress)Item.CC).Address
I've been having a little weekend project for myselff which involves getting all my ToDo tasks from Outlook, put them in a DataGridView and me being able to edit and export them.
The only problem I've been running into is me being unable to get the task specific properties for flagged emails while they still exist, I just don't see any way to access them.
Here is a portion of my current code.
private void retrieveTasks()
{
//Clear datagrid so we won't have duplicate information
taskList.Rows.Clear();
//Define some properties so we can use these to retrieve the tasks
Outlook.Application app = null;
_NameSpace ns = null;
Store outlookStore = null;
Outlook.MAPIFolder taskFolder = null;
Outlook.MAPIFolder specialFolder = null;
TaskItem task = null;
DateTime nonDate = new DateTime(4501, 1, 1);
try
{
//Connect to Outlook via MAPI
app = new Outlook.Application();
ns = app.GetNamespace("MAPI");
ns.Logon(null, null, false, false);
/*
outlookStore = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox).Store;
taskFolder = outlookStore.GetSpecialFolder(Microsoft.Office.Interop.Outlook.OlSpecialFolders.olSpecialFolderAllTasks);
*/
//Get the taskfolder containing the Outlook tasks
//taskFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks);
outlookStore = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox).Store;
taskFolder = outlookStore.GetSpecialFolder(OlSpecialFolders.olSpecialFolderAllTasks);
//Console.WriteLine(specialFolder.Items[1].Subject.ToString());
/*for (int i = 1; i <= specialFolder.Items.Count; i++)
{
//task = (Outlook.TaskItem)specialFolder.Items[i];
Console.WriteLine(specialFolder.Items[i].ToString());
}*/
for (int i = 1; i <= taskFolder.Items.Count; i++)
{
//Get task from taskfolder
Object item = taskFolder.Items[i];
if (item is Outlook.MailItem)
{
MailItem mail = (Outlook.MailItem)item;
if (mail.TaskCompletedDate.Equals(nonDate))
{
string percentComplete = "";
string taskPrio = "";
if (mail.UserProperties.Find("Prio") == null)
{
taskPrio = "";
}
else
{
taskPrio = mail.UserProperties.Find("Prio").Value.ToString();
}
//mail.UserProperties.
if (mail.UserProperties.Find("% Complete") == null)
{
percentComplete = "";
}
else
{
percentComplete = mail.UserProperties.Find("% Complete").Value.ToString();
}
//Add the tasks details to the datagrid
taskList.Rows.Add(
i.ToString(),
checkForNull(mail.Subject),
parseDate(mail.TaskStartDate.ToString()),
parseDate(mail.TaskDueDate.ToString()),
percentComplete, "Taak voltooid",
//statusToFriendlyName(mail.Status.ToString()),
taskPrio
);
}
}
else if (item is Outlook.TaskItem)
{
task = (Outlook.TaskItem)item;
Console.WriteLine(task.Subject);
if (task.Complete == false)
{
string taskPrio = "";
//Make sure custom task property is failed or set it to empty text to prevent crashes
if (task.UserProperties.Find("Prio") == null)
{
taskPrio = "";
}
else
{
taskPrio = task.UserProperties.Find("Prio").Value.ToString();
}
//Add the tasks details to the datagrid
taskList.Rows.Add(
i.ToString(),
task.Subject.ToString(),
parseDate(task.StartDate.ToString()),
parseDate(task.DueDate.ToString()),
task.PercentComplete.ToString(),
statusToFriendlyName(task.Status.ToString()),
taskPrio
);
}
}
}
}
catch (System.Runtime.InteropServices.COMException ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
//Release Outlook sources
ns = null;
app = null;
}
}
So specifically I am looking for the "% complete" property and the status property, everything else I am able to work around on.
It would make my life SO MUCH EASIER if I can get this to work :)
Hope to hear from anyone on here!
Jeffrey
Do you mean you need to retrieve the task specific properties from a MailItem object (as opposed to the TaskItem object)?
Take a look at the message with OutlookSpy (I am its author) - click IMessage button, look at the MAPI properties in the GetProps tab. Any property can be accessed using MailItem.PropertyAccessor.GetProperty. The DASL name to be used by GetProperty is displayed by OutlookSpy (select the property in the IMessage window, see the DASL edit box).