Getting the Outlook Out of Office flag with .NET - c#

My company is using Exchange 2003.
Is it possible to query exchange from .NET code to find out if someone's 'Out of Office' assisstant is on or off?

Using the Outlook Redemption library, you can get Out of Office status like this:
public bool IsOutOfOffice()
{
var outlook = new Microsoft.Office.Interop.Outlook.Application();
var rdoSession = new Redemption.RDOSession();
rdoSession.MAPIOBJECT = outlook.Session.MAPIOBJECT;
Redemption.RDOOutOfOfficeAssistant OOFA =
(_rdoSession.Stores.DefaultStore as Redemption.RDOExchangeMailboxStore).OutOfOfficeAssistant
return OOFA.OutOfOffice;
}
To check another user's status, you need to get the MAPIOBJECT for their mailbox.

Related

Getting contacts from Exchange instead of Outlook

I am currently developing an application to be used internally only at work. I need to get the currently logged in user's contacts to use in the application and I am currently getting the contacts with the following:
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace NameSpace = app.GetNamespace("MAPI");
Microsoft.Office.Interop.Outlook.MAPIFolder ContactsFolder = NameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
Microsoft.Office.Interop.Outlook.Items ContactItems = ContactsFolder.Items;
foreach (Microsoft.Office.Interop.Outlook.ContactItem item in ContactItems)
{
//do stuff with the contacts here
}
The problem with this approach is that whenever a user opens the application and Outlook is not already open, an Outlook popup appears asking the user to Allow or Deny the application's access to Outlook contacts. This is unnecessary and my only thought of how to stop this form happening is instead of using Outlook itself, get the contacts from the Exchange Server.
I have looked into a bunch of documentation for things like EWS however I have not found reference for EWS to be guaranteed working with Exchange 2019. I would also like any authentication done automatically based on domain authentication with the currently logged in user instead of requiring the user to input a password.
I did try to use this: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/get-started-with-ews-managed-api-client-applications however ExchangeVersion only has options up to Exchange 2013.
What should I be using to achieve this? Any push in the right direction would be greatly appreciated.
Use the active directory instead of EWS to get network users data, including email address.
the relevant namespace is: System.DirectoryServices
Here is an example that I wrote in my project to get user data including email by the first name and last name from AD. Note: ActiveDirectoryEntity us a class of mine. also, regarding another issue you wrote in your question, entering the user and password is not needed because authentication was already maid when the user authenticated to windows.
public static List<ActiveDirectoryEntity> GetActiveDirectoryData(string sname, string fname)
{
try
{
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(givenname={0}*)(sn={1}*))", sname, fname);
search.PropertiesToLoad.Add("givenName");
search.PropertiesToLoad.Add("sn");
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("mobile");
search.PropertiesToLoad.Add("department");
var result = search.FindAll();
List<ActiveDirectoryEntity> resultlist = new List<ActiveDirectoryEntity>();
foreach (SearchResult r in result)
{
if (r.Properties["mail"] != null)
{
if (r.Properties["mail"].Count > 0)
{
ActiveDirectoryEntity ade = new ActiveDirectoryEntity();
if ((r.Properties["givenname"].Count > 0))
ade.FirstName = r.Properties["givenName"][0].ToString();
if ((r.Properties["sn"].Count > 0))
ade.LastName = r.Properties["sn"][0].ToString();
if ((r.Properties["mail"].Count > 0))
ade.Email = r.Properties["mail"][0].ToString();
if ((r.Properties["department"].Count > 0))
ade.Department = r.Properties["department"][0].ToString();
resultlist.Add(ade);
}
}
}
return resultlist;
}
catch
{
return null;
}
}

Checking for an enabled outlook account

I just started to dabble into using Microsoft.Office.Interop.Outlook. I was able to successfully send an email using the bit of code below.
public void Send()
{
try
{
Outlook._Application _app = new Outlook.ApplicationClass();
var test = _app.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.MailItem mail = (Outlook.MailItem) _app.CreateItem(Outlook.OlItemType.olMailItem);
mail.To = "testemail#fakeaddress.com";
mail.Subject = "Test Outlook Subject";
mail.Body = "Test Outlook Body";
mail.Importance = Outlook.OlImportance.olImportanceNormal;
((Outlook.MailItem) mail).Send();
}
catch
{
Notification.Notice("Error");
}
}
I would like to have a Validate() function before the try/catch such that it'll check to see if there's a valid outlook account enabled. May I ask does anyone know how I can check if any outlook accounts are setup?
I tried this
public bool validate()
{
Outlook._Application _app = new Outlook.ApplicationClass();
Outlook.Accounts accounts = _app.Session.Accounts;
return accounts.Count > 0;
}
But accounts.Count returned 1 even after I removed my outlook account.
There will always be at least one account - the store. Otherwise Outlook won't run. But even if there are mail accounts, how would you know whether they are configured appropriately? Unless you take over the message submission, there is no way for you to know ahead of time.
UPDATE: Loop through the Namespace.Accounts collection and look for accounts with Account.AccountType == olExchange ,olImap,olPop3, olHttp. Keep in mind that OOM only list mail accounts, not store or address book.
If you were using Extended MAPI (C++ or Delphi), you could use IOlkAccountManager::EnumerateAccounts(CLSID_OlkMail, ...) (you can play with that interface in OutlookSpy (I am its author) - click IOlkAccountManager button). If Extended MAPI is not an option, Redemption (I am also its author) exposes the RDOAccounts object; its GetOrder(acMail) method will return all mail accounts. You'll just need to check if the returned collection has any elements.

Send Lync meeting Invitations using Exchange web service and UCWA

I want to make a webservice which sends lync meeting invitations to attendees. I've done the UCWA Part, for generate the meeting conference adress.
But now i'm trying to create the invitation using EWS. I can send standard appointment, with the meeting URL as body, but the Outlook Lync addin dont recognize it as a lync meeting.
Thanks to the Outlook Spy addin, I can see the right tags for transform my appointment into a lync meeting. So I think that i just have to add the same tags than an original Lync meeting (created with the lync addin for outlook).
I've tried to set extended properties of my appointment:
Guid MY_PROPERTY_SET_GUID0 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID1 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID2 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID3 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID4 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID5 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID6 = Guid.NewGuid();
Guid MY_PROPERTY_SET_GUID7 = Guid.NewGuid();
ExtendedPropertyDefinition EPD0 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID0, "MeetingType", MapiPropertyType.Long);
ExtendedPropertyDefinition EPD1 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID1, "OnlineMeetingConfLink", MapiPropertyType.String);
ExtendedPropertyDefinition EPD2 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID2, "UCMeetingSetting", MapiPropertyType.String);
ExtendedPropertyDefinition EPD3 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID3, "UCOpenedConferenceID", MapiPropertyType.String);
ExtendedPropertyDefinition EPD5 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID5, "UCMeetingSettingSent", MapiPropertyType.String);
ExtendedPropertyDefinition EPD4 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID4, "OnlineMeetingExternalLink", MapiPropertyType.String);
ExtendedPropertyDefinition EPD6 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID6, "UCInband", MapiPropertyType.String);
ExtendedPropertyDefinition EPD7 = new ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID7, "UCCapabilities", MapiPropertyType.String);
appointment.SetExtendedProperty(EPD0, 65536);
appointment.SetExtendedProperty(EPD1, cd.HttpJoinLink);
appointment.SetExtendedProperty(EPD2, cd.getUCMeetingSettings());
appointment.SetExtendedProperty(EPD3, Guid.NewGuid().ToString());
appointment.SetExtendedProperty(EPD4, cd.ConfJoinLink);
appointment.SetExtendedProperty(EPD5, cd.getUCMeetingSettings());
appointment.SetExtendedProperty(EPD6,[XMLVALUE]);
appointment.SetExtendedProperty(EPD7, [XMLVALUE]);
string mailAddress;
foreach (string a in attendees)
{
if (a.StartsWith("sip:"))
{
mailAddress = a.Substring(4, a.Length - 4);
}
else
{
mailAddress = a;
}
appointment.RequiredAttendees.Add(mailAddress);
}
appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
The two [XMLVALUES] are just copy/paste from outlook spy, this is a pretty long text that i don't write here for clarity purpose.
After that I recieve my invitation but, these tags doesn't appear as property tags in Outlookspy, so my appointment is not reconized as a "Lync meeting".
Do you have any ideas?
Thanks a lot.
You may consider executing the Lync Meeting button on the ribbon in Outlook programmatically to get the right meeting item. The ExecuteMso method of the CommandBars class executes the control identified by the idMso parameter. This method is useful in cases where there is no object model for a particular command. Works on controls that are built-in buttons, toggleButtons and splitButtons. See Office 2013 Help Files: Office Fluent User Interface Control Identifiers.
This what you need to make EWS meeting to online meeting.
ExtendedPropertyDefinition extendedUCMeetingSetting = new ExtendedPropertyDefinition(Guid.NewGuid(), "OnlineMeetingExternalLink",MapiPropertyType.String);
appointment.SetExtendedProperty(extendedUCMeetingSetting, skype_meeting_join_url)

outlook contact can't get SMTP address, No MAPI properties on "exchange" contact list

is it a bug in outlook?
i've created a local Contact list card, and i gave him in the address field an exchange user address. (double click on that address, see that its exchange).
when i try to get the address using MAPI - i can't, the problem is this, when i check the AddressEntry object, i get the following:
Type = "EX"
Address = "/o=.../ou=Exchange..."/cn=Recipients/cn=Name
Class = olAddressEntry
AddressEntryUserType = olOutlookContactAddressEntry
when i checked in OutlookSpy - no MAPI properties, so i can't get PR_SMTP_ADDRESS nor PR_EMS_AB_PROXY_ADDRESSES, also, this is not SMTP so i have no valid address.
i checked other users and those are the properties (which it works):
Real exchange user recipient, same email address as the exchange one, but it was created without autocorrect to the exchange user, so it stays smtp:
Type = "SMTP"
Address = "Email#email.com"
Class = olAddressEntry
AddressEntryUserType = olExchangeUserAddressEntry
Regular address entry
Type = "EX"
Address = "/o=.../ou=Exchange..."/cn=Recipients/cn=Name
Class = olAddressEntry
AddressEntryUserType = olOutlookContactAddressEntry
if i double click on the "exchange" local contact, it opens exchange window of its properties, if i open the "regular one i created manually", it opens the "SMTP" address window.
any workaround i can do?
thanks.
It didn't work in way "Dmitry Streblechenko" suggested because for some reason
ContactItem.Email1EntryId, ContactItem.Email2EntryId and ContactItem.Email3EntryId contains not id but some wrong random data (even some html tags) - office 2016.
But it finally worked with following code
using (var pa = new InteropWrapper<Outlook.PropertyAccessor>(contact.innerObject.PropertyAccessor))
{
String EMAIL1_ENTRYID = "http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/80850102";
string emailEntryID = pa.innerObject.BinaryToString(pa.innerObject.GetProperty(EMAIL1_ENTRYID));
using (var rs = new InteropWrapper<Outlook.NameSpace>(Globals.ThisAddIn.Application.Session))
{
rs.innerObject.Logon();
using (var addressEntry = new InteropWrapper<Outlook.AddressEntry>(rs.innerObject.GetAddressEntryFromID(emailEntryID)))
using (var exchangeUser = new InteropWrapper<Outlook.ExchangeUser>(addressEntry.innerObject.GetExchangeUser()))
{
return exchangeUser.innerObject.PrimarySmtpAddress;
}
}
}
where InteropWrapper<T> just IDisposable wrapper around com object - it does Marshal.ReleaseComObject(innerObject) on dispose. So you can do everything without it by using Marshal.ReleaseComObject() directly.
just in case if someone need email 2 and email 3 including them here
String EMAIL2_ENTRYID = "http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/80950102";
String EMAIL3_ENTRYID = "http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/80A50102";
Hope it will save someones time! I've spent like a day on it.
If you have an EX type contact, use the value of the ContactItem.Email1EntryId property to call Namespace,GetAddressEntryFromId, then read the AddressEntry.GetExchangeUser.PrimarySmtpAddress property.

Getting ExtendedPropertyDefinition values from EWS in Outlook addin

Im doing an automatic process on a mailbox using EWS webservices and assigning ExtendedPropertyDefinition to the messages like this:
Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition extendedPropertyDefinition =
new Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "Archivado", MapiPropertyType.String);
msgComplete.SetExtendedProperty(extendedPropertyDefinition, iddoc);
msgComplete.Update(ConflictResolutionMode.AlwaysOverwrite);
On the other side, I am developing an Outlook Addin who needs to evaluate on every message click, if that message has this ExtendedPropertyDefinition name defined but I dont know how can I recover the Extended property from outlook addin using Outlook class.
I dont mind If I have to use another kind of properties to be accessible from both frameworks.
I have tried using the following properties in Outlook with no luck;
item.Userproperties;
item.PropertyAccesor.GetProperty("Archivado");
item.ItemProperties;
Ok, finally I got it. I had to create the ExtendedPropertyDefinition using a Guid
and recover it from outlook using the schema on the property like this:
//Setting the property with Exchange webservice:
string guid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
Guid MY_PROPERTY_SET_GUID = new Guid(guid);
Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition extendedPropertyDefinition =
new Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(MY_PROPERTY_SET_GUID, "Archivado", MapiPropertyType.String);
//Recover the property using Outlook:
Outlook.MailItem item = (Outlook.MailItem)e.OutlookItem;
Outlook.UserProperties mailUserProperties = item.UserProperties;
dynamic property=item.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/string/{Outlook.MailItem item = (Outlook.MailItem)e.OutlookItem;
Outlook.UserProperties mailUserProperties = item.UserProperties;
dynamic property=item.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/string/{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}/Archivado");

Categories