EWS API - Create calendar and share with reviewer permissions - c#

I'm having some trouble on creating and share a calendar with review permissions using Exchange Webservice API .NET.
At the moment this is my code:
Folder addCalendar = new Folder(service);
addCalendar.DisplayName = name;
addCalendar.FolderClass = "IPF.Appointment";
var perm = new FolderPermission(new UserId("reviewer#test.com"),
FolderPermissionLevel.Reviewer);
addCalendar.Permissions.Add(perm);
addCalendar.Save(WellKnownFolderName.MsgFolderRoot);
The calendar is created, in my account I can see the calendar and the user 'reviewer#test.com' has the correct permissions.
The problem is: The calendar doesn't show at the reviewer's account.

You have to do two things:
Set the appropiate permissions:
var folder = Folder.Bind(service, WellKnownFolderName.Calendar);
folder.Permissions.Add(new FolderPermission("someone#yourcompany.com",
FolderPermissionLevel.Reviewer));
folder.Update();
Then, send an invitation message. Now, this is the hard part. The message format is specifified in [MS-OXSHARE]: Sharing Message Object Protocol Specification. The extended properties are defined in [MS-OXPROPS]: Exchange Server Protocols Master Property List. You need to create a message according to that specification and send it to the recipient.
EDITED:
To set the sharing properties on the element, use extended properties.
First, define the properties. For example, the PidLidSharingProviderGuidProperty is defined as follows:
private static readonly Guid PropertySetSharing = new Guid("{00062040-0000-0000-C000-000000000046}");
private static readonly ExtendedPropertyDefinition PidLidSharingProviderGuidProperty = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A01, MapiPropertyType.CLSID);
private static readonly ExtendedPropertyDefinition ConversationIdProperty = new ExtendedPropertyDefinition(0x3013, MapiPropertyType.Binary);
You can then set the property on a new item using the SetExtendedProperty method:
item.SetExtendedProperty(PidLidSharingProviderGuidProperty, "somevalue");

I figured out how to programmatically send a sharing invitation within an organization through EWS. May not answer all your questions, but it's a good start to understanding how in-depth you gotta get to actually do it. Heres the link

Related

How to stop meeting being stripped on forward (EWS)

I am using C# with the Exchange Web Service (EWS).
I have meetings that I need to forward and whenever I do they get stripped, but only from some accounts and not others. The link for the meeting is still there but it is not being recognised by the online Outlook as a meeting item, nor by Teams which is connected to the account.
This even happens if I manually forward, but again only if I forward emails that are from some accounts - some other accounts are fine!
I'm using this on incoming emails:
var fwdEmailArr = new EmailAddress[1];
fwdEmailArr [0] = fwdEmail;
MeetingRequest appointment = MeetingRequest.Bind(service, email.Id);
appointment.Forward("", fwdEmailArr);
This is the same issue if I use the email.forward as well, etc.
However, if I create a new appointment and send it, it doesn't get stripped - this is with the same addresses.
Appointment appt = new Appointment(service);
appt.Subject = email.Subject;
appt.Body = appointment.Body;
appt.Start = appointment.Start;
appt.End = appointment.End;
appt.Location = appointment.Location;
appt.RequiredAttendees.Add(fwdEmail);
foreach (var reqAtt in appt.RequiredAttendees)
{
appt.RequiredAttendees.Add(reqAtt);
}
foreach (var reqAtt in appt.OptionalAttendees)
{
appt.OptionalAttendees.Add(reqAtt);
}
appt.RequiredAttendees.Add(appointment.From.Address);
appt.Save(SendInvitationsMode.SendToAllAndSaveCopy);
So, I could do this but it means that they are no longer the same meeting and declining the original wont decline this. Unless there's a way I can connect the meetings or something?
Any ideas how I can stop the meeting being stripped?
Or alternatively just add another recipient to the current meeting, that will show on their calendar?
If anyone comes here with a similar issue, it turns out that, first of all you need to make sure you define the correct server version on the service declaration:
service = new ExchangeService(ExchangeVersion.Exchange2016){}
In addition, for some reason some images when attached to the forwarded email for some reason confuse EWS and make it think there's no meeting. I got around this by scanning the MIME content and just extracting the calendar block and deleting all other attachments.
This has been working flawlessly for about 5 months.

ExchangeService: connecting without credentials, how to retrieve user information?

I am analyzing a users Exchange mailbox with calls to the ExchangeService. This tool needs to run on the client environment periodically and by ommiting the credentials to the service I am connecting to the Exchange Service as the logged in Windows User. I can succesfully loop thrue the folders and items.
Now I want tot retrieve the information about the mailbox being used. Username and (main) E-mail should suffice. But I cannot find anything about how to retrieve this information. Every example provides credentails for the user, or auto-discovering the Exchange service from the e-mail adres. I do not want the user to configure anything :-).
Any suggestions?
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Url = new Uri("https://FQDN/EWS/Exchange.asmx");
???
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.SentItems, new ItemView(100)); // this works
I've tried using service.ResolveName, but that can give multiple answers, even using Environment.UserName
The easiest method to do this is to use ConvertId operation and use unresolvable address (blah#blah.com always works for me) in the Mailbox element. Exchange should convert this to the actual Mailbox in the response. eg
Folder chk = Folder.Bind(service, WellKnownFolderName.Inbox);
AlternateId aiItem = new AlternateId();
aiItem.Mailbox = "Blah#Blah.com";
aiItem.UniqueId = chk.Id.UniqueId;
aiItem.Format = IdFormat.EwsId;
String CasServer = service.Url.Host.ToString();
AlternateIdBase caid = service.ConvertId(aiItem, IdFormat.HexEntryId);
Console.WriteLine(((AlternateId)caid).Mailbox);
Cheers
Glen

Access custom view column from exchange public folder

I'm using Exchange Web Services to access contact records in a public folder. I need to pull a custom column, "Client Contact Management", created for a view in that folder. The custom column was created in the user interface.
I've already used the ExtendedPropertyDefinition class before on properties that I have created on my own through code. Is that what I'm supposed to use in this case and if so then how do I get the guid for the custom column?
I finally found the answer on this thread from David Sterling on the microsoft exchange server forums. His example (copied below) shows how to do things using EWS directly and using the managed api.
// via autogenerated proxy classes
PathToExtendedFieldType hairColorPath = new PathToExtendedFieldType();
hairColorPath.DistinguishedPropertySetId = DistinguishedPropertySetType.PublicStrings;
hairColorPath.DistinguishedPropertySetIdSpecified = true;
hairColorPath.PropertyName = "HairColor";
hairColorPath.PropertyType = MapiPropertyTypeType.String;
// via the Client API
ExtendedPropertyDefinition hairColor = new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.PublicStrings,
"HairColor",
MapiPropertyType.String);
Here is what I did using the managed api for my own problem. The key is using the DefaultExtendedPropertySet.PublicStrings which is where outlook stores the custom view column.
ExtendedPropertyDefinition _clientContactManagementPropertyDefinition =
new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.PublicStrings,
"Client Contact Management",
MapiPropertyType.Boolean
);

Creating New Message with default signature using Exchange Web Services

Currently a piece of our application creates and saves new mail messages to a user's drafts folder using Exchange Web Services. We would like to automatically append the user's default signature to these messages when creating them, but I have not been able to find a way to access the signature to append it to the body. The email message is currently created with the following code:
CreateItemType createEmailRequest = new CreateItemType();
createEmailRequest.MessageDisposition = MessageDispositionType.SaveOnly;
createEmailRequest.MessageDispositionSpecified = true;
DistinguishedFolderIdType draftsFolder = new DistinguishedFolderIdType();
draftsFolder.Id = distinguishedFolderIdNameType;
createEmailRequest.SavedItemFolderId = new TargetFolderIdType();
createEmailRequest.SavedItemFolderId.Item = draftsFolder;
MessageType emailMessage = new MessageType();
emailMessage.Subject = subject;
emailMessage.Body = new BodyType();
emailMessage.Body.BodyType1 = bodyType;
emailMessage.Body.Value = body;
emailMessage.Sensitivity = SensitivityChoicesType.Normal;
emailMessage.SensitivitySpecified = true;
createEmailRequest.Items = new NonEmptyArrayOfAllItemsType();
createEmailRequest.Items.Items = new ItemType[1];
createEmailRequest.Items.Items[0] = emailMessage;
Any ideas on how to get the current user's default signature and append it to the body the email?
The signatures in Outlook are a client-side feature and thus can't be accessed from Exchange Web Services. In fact I believe the signatures are actually stored in the users profile on the machine - I know I have to redo my signature when moving from one machine to another (I'm on Outlook/Exchange 2010).
In Exchange 2010 You can create a transport rule that can access user information, but there's not a way to use the Outlook signature information that I'm aware of.

Adding an Event to a "specific" Google Calender with GData API

I'm trying to add an event to a specific calendar in google calendar and I just don't find how. Here's my code :
CalendarService service = new CalendarService("MyTEst");
service.setUserCredentials("Username", "Password");
EventEntry entry = new EventEntry();
// Set the title and content of the entry.
entry.Title.Text = "title";
entry.Content.Content = "test";
// Set a location for the event.
Where eventLocation = new Where();
eventLocation.ValueString = "Location";
entry.Locations.Add(eventLocation);
When eventTime = new When(DateTime.now, DateTime.now.AddDays(2));
entry.Times.Add(eventTime);
Uri postUri = new Uri("http://www.google.com/calendar/feeds/default/private/full");
// Send the request and receive the response
AtomEntry insertedEntry = service.Insert(postUri, entry);
Can anyone help me out with this one?
Edit
Maybe I should mention that this fonctionnability is only accessible for an administrator of a site which want to easly add rendez-vous and note to his google calendar so I automaticaly authenticated it with "hardcoded" value so I'm sure the username and password are ok.
Your code is working with the default Google Calendar for your specified user name and password. (IE it is using the default calendar for username#gmail.com) You can see this because the URI points to "/feed/default/private". If you want to post the event to another calendar the user name must authorized to post to that calendar, and you need to post to THAT calendars private uri.
EDIT:
The default format of this private URL is "http://www.google.com/calendar/feeds/CALENDAR_ID/private/full"
To find the calendar id, it is next Calendar Address in the calendar settings page on Google Calendars. It will appear similar to this:
"***************************#group.calendar.google.com"
The final URL would be:
EDIT:
"http://www.google.com/calendar/feeds/***************************#group.calendar.google.com/private/full"
This will go in your Uri postUri = new Uri();
EDIT:
My mistake was that I mentioned that you need to also include the private key after the word private. You do not actually have to do this. I have verified that I could successfully post to a secondary calendar by removing the private key.

Categories

Resources