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)
Related
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...
}
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");
I am developing an application that syncs an exchange calendar to another calendar. I put extended properties on the exchange appointments in order to preserve the mapping between appointments in the two calendars. Everything is working fine until I try to remove an extended property from an occurrence of a recurring appointment. When I try doing this, I get the error:
The delete action is not supported for this property.
Here is a code snippet that demonstrates the error:
public void ExchangeTest()
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1)
{
Credentials = new NetworkCredential("username", "password", "domain")
};
service.AutodiscoverUrl("username#domain.com");
Appointment appt = new Appointment(service)
{
Recurrence = new Recurrence.DailyPattern(DateTime.Now, 2) { NumberOfOccurrences = 3},
Start = DateTime.Now,
End = DateTime.Now.AddHours(2),
Subject = "Test Appointment"
};
NameResolutionCollection resolutionCollection = service.ResolveName("username", ResolveNameSearchLocation.DirectoryOnly, false);
string mailboxAddress = resolutionCollection.First().Mailbox.Address;
FolderId folderId = new FolderId(WellKnownFolderName.Calendar, mailboxAddress);
appt.Save(folderId);
PropertySet properties = new PropertySet(AppointmentSchema.ICalUid);
appt.Load(properties);
CalendarView view = new CalendarView(DateTime.Today, DateTime.Today.AddDays(8)){PropertySet = properties};
IEnumerable<Appointment> occurrences = service.FindAppointments(folderId, view)
.Where(a => a.ICalUid == appt.ICalUid);
ExtendedPropertyDefinition definition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "TestProperty", MapiPropertyType.String);
Appointment firstOccurrence = occurrences.First();
firstOccurrence.SetExtendedProperty(definition, "test");
firstOccurrence.Update(ConflictResolutionMode.AutoResolve);
//The error occurs on the next line.
firstOccurrence.RemoveExtendedProperty(definition);
firstOccurrence.Update(ConflictResolutionMode.AutoResolve);
//clean up
appt.Delete(DeleteMode.HardDelete);
}
It appears that the error is only thrown for an Exchange 2007 server (It works on 2010). Am I doing something wrong, or is this a problem with Exchange? Is there a way to work around this issue? Any help will be appreciated.
I ended up not using the RemoveExtendedProperty function. Instead, I worked around it by just setting the property again, but setting it to an empty space. I then handled the empty space in code. This appears to be a problem with Exchange or the managed API.
Did you try;
appointment.Delete(DeleteMode.SoftDelete,SendCancellationsMode.SendToAllAndSaveCopy);
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.