I have the following code to login to an outlook inbox to retrieve emails. If I don't find a certain email that I'm looking for I would like to refresh Inbox folder and try again. Is it as simple as running this function again?
I want the equivalent of clicking on "Send/Receive" button in outlook to fetch any new emails.
private Microsoft.Office.Interop.Outlook.Items loginEmail()
{
//TODO.............................................
//RDOSession session = new RDOSession();
//session.Logon();
//Microsoft.Office.Interop.Outlook.Application myApp = new Microsoft.Office.Interop.Outlook.ApplicationClass();
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 myContacts = mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
//login
mapiNameSpace.Logon(null, null, false, false);
mapiNameSpace.Logon("login#mywebsite.com", "pass", false, true);
//Microsoft.Office.Interop.Outlook.Items myItems = myContacts.Items;
// Console.WriteLine("Total : ", myItems.Count);
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
// Console.Write(myInbox.Name);
Microsoft.Office.Interop.Outlook.Items inboxItems = myInbox.Items;
// Console.WriteLine("Total : ", inboxItems.Count);
//Microsoft.Office.Interop.Outlook.Explorer myexp = myInbox.GetExplorer(false);
//mapiNameSpace.Logon("Profile", Missing.Value, false, true);
return inboxItems;
}
Call this function to fetch new mail
mapiNameSpace.SendAndReceive(false);
The NameSpace.SendAndReceive method initiates immediate delivery of all undelivered messages submitted in the current session, and immediate receipt of mail for all accounts in the current profile.
SendAndReceive provides the programmatic equivalent to the Send/Receive All command that is available when you click Tools and then Send/Receive.
If you don't need to synchronize all objects, you can use the SyncObjects collection object to select specific objects. For more information, see NameSpace.SyncObjects.
private void DirectSendAndReceiveCall(object sender, IRibbonControl control, bool pressed)
{
Outlook.NameSpace ns = OutlookApp.GetNamespace("MAPI");
ns.SendAndReceive(false);
if (ns != null) Marshal.ReleaseComObject(ns);
}
See How To: Perform Send/Receive in Outlook programmatically for more information.
Related
I have made an Outlook Add-In (Outlook 2013 and 2016 VSTO Add-In) for business purposes to save the email details to our database. The add-in is launched when a new email is composed, but closes when the email is sent.
The sent date of the email is only added after the email is moved to the Sent mailbox. Is there a way to use my current add-in (or another add-in) can be used to get that sent date after it has been closed without letting the user wait for it to be moved to the sent mailbox?
I know it can easily be done in VBA, but I want to preferably use an Add-in so that it can be easily loaded to all users with exchange server.
Wouldn't that date be today's date/time (Now) or something close to it?
Everything you can do in VBA you can do in a COM addin - subscribe to the Items.ItemAdd event on the Sent Items folder and retrieve the date when the event fires.
Thank you Dmitry for the reply. It set me on the right path. I used my existing VSTO add in to fire when a new item is added to the Sent mailbox. I did not know that when inserting this in the "ThisAddIn_Startup" method re-activates the add-in, which now makes sense.
I followed this example.
Here is my code:
Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder Sent_items;
Outlook.Items items;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
outlookNameSpace = this.Application.GetNamespace("MAPI");
Sent_items = outlookNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderSentMail);
items = Sent_items.Items;
items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
void items_ItemAdd(object Item)
{
Outlook.MailItem mail = (Outlook.MailItem)Item;
string strMailItemNumber_filter = mail.UserProperties["MailItemNumber"].Value;
if ((Item != null) && (!string.IsNullOrWhiteSpace(strMailItemNumber_filter)))
{
if (mail.MessageClass == "IPM.Note" &&
mail.UserProperties["MailItemNumber"].Value.ToUpper().Contains(strMailItemNumber_filter.ToUpper())) //Instead of subject use other mail property
{
//Write 'Sent date' to DB
System.Windows.Forms.MessageBox.Show("Sent date is: "+ mail.SentOn.ToString()+ " MailNr = "+strMailItemNumber_filter);
}
}
}
I had to create a new mail user defined property to match the email I sent to find the correct email in the sent mailbox:
private void AddUserProperty(Outlook.MailItem mail)
{
Outlook.UserProperties mailUserProperties = null;
Outlook.UserProperty mailUserProperty = null;
try
{
mailUserProperties = mail.UserProperties;
mailUserProperty = mailUserProperties.Add("MailItemNrProperty", Outlook.OlUserPropertyType.olText, false, 1);
// Where 1 is OlFormatText (introduced in Outlook 2007)
mail.UserProperties["MailItemNumber"].Value = "Any value as string...";
mail.Save();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
if (mailUserProperty != null) Marshal.ReleaseComObject(mailUserProperty);
if (mailUserProperties != null) Marshal.ReleaseComObject(mailUserProperties);
}
}
I try this code :
Microsoft.Office.Interop.Outlook.Application myApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
mapiNameSpace.Logon(null, null, false, false);
mapiNameSpace.Logon("MyEmailID", "PasswordOfMyEmail", Missing.Value, true);
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
MessageBox.Show(myInbox.Items.Count + "");
But the MessageBox display me 0 (myInbox.Items.Count).
So maybe I am not able to access my outlook account !!!
I use Visual Studio 2010.
Can someone help me please ?
Firstly, if you are in an add-in, you should never create a new instance of the Outlook.Application object - you already have it exposed to your addin through globals.
Secondly, do not call Logon - Outlook will do that for you. That method is really for the external applications, not addins.
Thirdly, you call Logon once with null for the profile name. If you do not want to pass an optional parameter, pass Missing.Value, not null. And the second call to Logon (why do you need it?) will do absolutely nothing. Passing any email will not work anyway - the parameter must be the profile name as seen in Control Panel | Mail | Show Profiles.
And most importantly, when do you make that call? Does your Inbox actually contain any messages? Or is it a brand new profile and Outlook did not yet have a chance to download the messages from the mailbox?
So you can use :
Explorer currentExplorer = Globals.ThisAddIn.Application.ActiveExplorer();
MAPIFolder myInbox = Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder;
try
{
if ( (currentExplorer != null) && (currentExplorer.Selection != null) && (currentExplorer.Selection.Count > 0) )
{
object item = currentExplorer.Selection[1];
if (item is MailItem)
{
MailItem mailItem = item as MailItem;
MessageBox.Show(myInbox.Items.Count + "");
}
}
}
i have written a code that will read all unread mails from Outlook 2010 and write them in a file. After that i want to change the status of the mails as Read in outlook.
How do i do it?
I am using Interop for accessing the mails.
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MailItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
Microsoft.Office.Interop.Outlook.Items unreadItems = null;
app = new Microsoft.Office.Interop.Outlook.Application();//.CreateItem(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
ns = app.GetNamespace("MAPI");
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
unreadItems = inboxFolder.Items.Restrict("[Unread]=true");
Here are some link that could help you:
http://msdn.microsoft.com/en-us/library/aa289167%28VS.71%29.aspx (it is for Outlook 2003 but it still contains very usefull info)
http://msdn.microsoft.com/en-us/library/ms268731%28VS.80%29.aspx
I've a code sample that could help you:
OutLook.Application oApp;
OutLook._NameSpace oNS;
OutLook.MAPIFolder oFolder;
OutLook._Explorer oExp;
oApp = new OutLook.Application();
oNS = (OutLook._NameSpace)oApp.GetNamespace("MAPI");
oFolder = oNS.GetDefaultFolder(OutLook.OlDefaultFolders.olFolderInbox);
oExp = oFolder.GetExplorer(false);
oNS.Logon(Missing.Value, Missing.Value, false, true);
OutLook.Items items = oFolder.Items;
foreach (OutLook.MailItem mail in items)
{
if (mail.UnRead)
{
mail.UnRead = false;
mail.Save();
}
Marshal.ReleaseCOMObject(mail);
}
Marshal.ReleaseCOMObject(items);
// Dont forget to free all other object, using Marshal.ReleaseCOMObject then close oApp
Please note I've not tested if it works or even compile.
On of general rule with outlook dev is that you need to release ALL com object otherwise you can have strange behavior (save popup when closing outlook app, or even the outlook never close etc.)
EDIT:
I would advice to you indeed use the Restrict method to get only unred mail, because my snippet above will loop in all emails which could be unnecessary and not performant.
Set the OutLook.MailItem's UnRead property to false
I am in the process of writing an app that will use the Outlook API to copy Calendar Items from a shared calendar to my personal calendar. Here is what I have so far...
using Outlook = Microsoft.Office.Interop.Outlook;
public Outlook.Items GetPublicEntries(string calendar)
{
Microsoft.Office.Interop.Outlook.Items CalendarFolderItems = null;
Outlook.Application oApp;
oApp = new Outlook.Application();
Outlook.NameSpace oNS = oApp.GetNamespace("MAPI");
//oNS.Logon(Missing.Value, Missing.Value, true, true);
Outlook.Recipient oRecip = (Outlook.Recipient)oNS.CreateRecipient(calendar);
Outlook.MAPIFolder usersCalendarFolder = (Outlook.MAPIFolder)oNS.GetSharedDefaultFolder(oRecip, Outlook.OlDefaultFolders.olFolderCalendar);
CalendarFolderItems = usersCalendarFolder.Items;
return CalendarFolderItems;
}
static void Main(string[] args)
{
String[] Cals = { "Appointments","Deadlines","Hearings"};
foreach (string cal in Cals)
{
CalendarItems calobj = new CalendarItems();
Outlook.Items calobjs = calobj.GetPublicEntries(cal);
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in calobjs)
{
try
{
Console.WriteLine(item.Subject + " -> " + item.Start.ToLongDateString() + " - " + item.GlobalAppointmentID);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Console.ReadKey();
}
}
I am able to return a list of items from the three calendars, but now I need to copy them to my personal calendar and that is where I am stuck. Anyone know how to go about doing this?
Thanks!
Tony
Outlook will not let you copy directly to a specified folder (unlike AppointmentItem.Move() which takes a MAPIFolder object as a parameter) - use AppointmentItem.Copy, followed by AppointmentItem.Move:
AppointmentItem copiedItem = Item.Copy();
AppointmentItem newItem = copiedItem.Move(YourDestinationFolder);
newItem.Save();
Beware that Outlook will wipe out the global appointment id when you call Copy() - this means message updates, even if they come directly to your Inbox, will not find the appointment.
You can avoid the intermediary step if you use Redemption (I am its author) - its RDOAppointmentItem (derived from the RDOMail object) lets you pass the target folder when calling CopyTo().
Is there any way to get all mail from an specific Folder into my Application?
Check this link. Introduction to Outlook Programming will explain things more clearly.
You could loop through the mailitems. Sample code
using System.Runtime.InteropServices;
using OutLook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
OutLook.Application oApp;
OutLook._NameSpace oNS;
OutLook.MAPIFolder oFolder;
OutLook._Explorer oExp;
oApp = new OutLook.Application();
oNS = (OutLook._NameSpace)oApp.GetNamespace("MAPI");
oFolder = oNS.GetDefaultFolder(OutLook.OlDefaultFolders.olFolderInbox);
oExp = oFolder.GetExplorer(false);
oNS.Logon(Missing.Value, Missing.Value, false, true);
OutLook.Items items = oFolder.Items;
foreach (OutLook.MailItem mail in items)
{
if (mail.UnRead == true)
{
}
}
Edit:
Reference other folders
oFolder.Folders["Foldername"]
OutLook Code
Common Outlook tasks
Looping through all items in a folder is a terrible idea, especially if you are working against an online Exchange store. Items.Find/FindNext or Items.Restrict is the way to go.
Find/FindNext:
OutLook.Items items = oFolder.Items;
OutLook.MailItem mail = items.Find("[Unread] = true");
while (mail != null)
{
MessageBox.Show(mail.Subject);
mail = items.FindNext();
}
Items.Restrict:
OutLook.Items items = oFolder.Items.Restict("[Unread] = true")
foreach (OutLook.MailItem mail in items)
{
MessageBox.Show(mail.Subject);
}
There's some examples of accessing Outlook folders here, one of which deals specifically with unread mail.
Edit: There's a KB article specifically about accessing folders from C#, Programming samples that can reference items and folders in Outlook by using Visual C# .NET
To open another user's folder, use GetSharedDefaultFolder
foreach (Object Unreadmail in folderItems)
{
if ((Unreadmail as Outlook.MailItem) != null && (Unreadmail as Outlook.MailItem).UnRead == true)
{
//DO Your action Here
}
}
I have experienced "COM_object" exception error with above solutions, More info please refer here