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");
Related
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)
Im currently looking at a way to save a few extra properties to an exchange appointment using C#. Currently I can save using the following properties:
Appointment calendar = new Appointment(p_service);
calendar.Subject = calendarS5Subject;
calendar.Body = calendarS5Body;
calendar.Start = calendarS5StartDateTime;
calendar.End = calendarS5EndDateTime;
calendar.IsReminderSet = false;
calendar.Location = calendarS5Location;
calendar.Body.BodyType = BodyType.Text;
calendar.Save();
However I want to be able to store my own custom properties like calendar.EventID and calendar.Blah . Is it possible to save these properties against the appointment and then be able to access them later? It would be even better if it could all be stored as a user control form inside the appoint window. I know you can do this with an outlook addin that uses the type AppointmentItem. However I am yet to find a way to do it with exchange with the type of Appointment.
TIA.
I have now been able to save the extra property using:
Guid EventIDSetGUID = new Guid("{C11FF724-AA03-4555-9952-8FA248A11C3E}");
ExtendedPropertyDefinition extendedPropertyEventID = new ExtendedPropertyDefinition(EventIDSetGUID, "EventID", MapiPropertyType.String);
calendar.SetExtendedProperty(extendedPropertyEventID, calendarS5EventID);
However I am now struggling to read back that property later on. This work right after I have saved the extra property but if I restart the application and then try to read the extra property eventIDProp always returns null. My code for reading:
Guid EventIDReadGUID = new Guid("{C11FF724-AA03-4555-9952-8FA248A11C3E}");
ExtendedPropertyDefinition extendedPropertyEventIDRead = new ExtendedPropertyDefinition(EventIDReadGUID, "EventID", MapiPropertyType.String);
object eventIDProp;
if (calendar.TryGetProperty(extendedPropertyEventIDRead, out eventIDProp) && eventIDProp != calendarS5EventID)
{
}
You can do that with MAPI extended properties:
// Define MAPI extended properties
private readonly ExtendedPropertyDefinition _extendedPropEventId =
new ExtendedPropertyDefinition(
new Guid("{00020329-0000-0000-C000-000000000046}"),
"Event Identifier",
MapiPropertyType.String);
private readonly ExtendedPropertyDefinition _extendedPropBlah =
new ExtendedPropertyDefinition(
new Guid("{00020329-0000-0000-C000-000000000046}"),
"Blah",
MapiPropertyType.String);
...
// Set extended properties for appointment
calendar.SetExtendedProperty(_extendedPropEventId, "custom EventID value");
calendar.SetExtendedProperty(_extendedPropBlah, "custom Blah value");
...
// Bind to existing item for reading extended properties
var propertySet = new PropertySet(BasePropertySet.FirstClassProperties, _extendedPropEventId, _extendedPropBlah);
var calendar = Appointment.Bind(p_service, itemId, propertySet);
if (calendar.ExtendedProperties.Any(ep => ep.PropertyDefinition.PropertySetId == _extendedPropEventId.PropertySetId))
{
// Add your code here...
}
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.
I think I'm creating it properly, like as follows. c is a Contact, and I'm just trying to store a unique identifier considering that ItemId which is provided by EWS isnt static...
propertySetId = System.Guid.NewGuid();
// Create a definition for the extended property.
ExtendedPropertyDefinition extendedPropertyDefinition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "itemGUID", MapiPropertyType.String);
c.SetExtendedProperty(extendedPropertyDefinition, propertySetId.ToString());
c.Update(ConflictResolutionMode.AlwaysOverwrite);
When I try to pull this back out when searching for the contact based on something else, like first name, I'm getting a null returned. I'm trying to get the value by:
foreach (Item c in findResults.Items)
{
foreach(ExtendedProperty extendedProperty in c.ExtendedProperties)
{
if(extendedProperty.PropertyDefinition.Name == "itemGUID")
{
results[i] = extendedProperty.Value.ToString();
}
}
}
EDIT: code for findResults
List<SearchFilter> searchFilters = new List<SearchFilter>();
searchFilters.Add(new SearchFilter.IsEqualTo(itemGUID, value));
//can be more filters here depending on situation
SearchFilter filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchFilters.ToArray());
findResults = service.FindItems(WellKnownFolderName.Contacts, filter, view);
You need to assign the PropertySet in the ItemView to tell EWS what properties to include when you search using FindItems. If you don't include it in your ItemView it won't be available for reading.The alternative approach is to use the Contact.Bind and request the property for each Contact in question (more service requests, but sometimes necessary).
See Viewing Extended Properties using EWS for a full example on working with Extended Properties in EWS.
Approach #1: Retrieve Extended Property for all Contacts
ExtendedPropertyDefinition propDef = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "itemGUID", MapiPropertyType.String);
ItemView view = new ItemView(50) { PropertySet = new PropertySet(propDef) };
Approach #2: Bind one contact at a time if you have a Contact ID
ExtendedPropertyDefinition propDef = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "itemGUID", MapiPropertyType.String);
Contact contact = Contact.Bind(service, contactID, new PropertySet(propDef));
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.