I am using EWS Managed API 2.0 to send the meeting invitation and capture the user response.
I have followed the reference from official website https://msdn.microsoft.com/en-us/library/office/jj220499(v=exchg.80).aspx
and https://msdn.microsoft.com/en-us/library/office/dd633661(v=exchg.80).aspx. I, am getting an error as Id is malformed.
I have used the exact code in the official website. I did some googling and found that if id has special character this error may appear. But the id I provided has no special character its just a simple character.
Here is the code
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("********#live.com", "************");
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.AutodiscoverUrl("***********#live.com", RedirectionUrlValidationCallback);
// Create the appointment.
Appointment appointment = Appointment.Bind(service, "AAMkA=");
// Set properties on the appointment. Add two required attendees and one optional attendee.
appointment.Subject = "Status Meeting";
appointment.Body = "The purpose of this meeting is to discuss status.";
appointment.Start = new DateTime(2009, 3, 1, 9, 0, 0);
appointment.End = appointment.Start.AddHours(2);
appointment.Location = "Conf Room";
appointment.RequiredAttendees.Add("***********#live.com");
// Send the meeting request to all attendees and save a copy in the Sent Items folder.
appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
foreach (Attendee t in appointment.RequiredAttendees)
{
if (t.ResponseType != null)
Console.WriteLine("Required attendee - " + t.Address + ": " + t.ResponseType.Value.ToString());
}
Getting an error in Appointment appointment = Appointment.Bind(service, "AAMkA=");The id is malfunction.
Exchange server will provide a unique Id on creating the appointment.
So need to save the Id and pass the same Id when fetching the user response.
var Id = appointment.Id;
So pass the Id to fetch in the response.
Related
I have been using Exchange WebServices (EWS) for some time now, in Asp.net C #, to add events in the calendars of Office365 users at my work.
I now needed those same events to appear at Microsoft Teams, with the possibility of going on videoconference.
Events appear but that possibility is not present.
One of the properties of "appointments" is "isOnlineMeeting". I tried to add it, making it true, but it always returns an error saying "Set action is invalid for property.".
In the online searches I have done, I have found that this is a read-only property.
So, is there any chance that I can "force" this property?
I have already configured my Exchange so that, in Outlook online when we do a new event, this is always by videoconference.
Some help?
Thank you!
UPDATE:
By the way, the code that I'm using is:
try {
ExchangeService service = new ExchangeService (ExchangeVersion.Exchange2013_SP1, TimeZoneInfo.FindSystemTimeZoneById ("GMT Standard Time"));
service.Url = new Uri ("https://outlook.office365.com/EWS/Exchange.asmx");
string User = "a#a.net";
string Password = "AAA";
service.Credentials = new NetworkCredential (User, Password);
Appointment appointment = new Appointment (service);
appointment.Subject = "Experiment";
appointment.Location = "Videoconference";
string dataStart = "10-02-2021 19:00:00.000";
string dataEnd = "10-02-2021 20:00:00.000";
appointment.Start = DateTime.Parse (dataStart);
appointment.End = DateTime.Parse (dataEnd);
appointment.Body = "<strong>Ignore! Just a test</strong>";
appointment.IsOnlineMeeting = true;
appointment.RequiredAttendees.Add ("b#a.net");
appointment.Save (SendInvitationsMode.SendOnlyToAll);
} catch (Exception ex) {
}
Posting the Answer for better knowledge
Copying from comments
Could you please try with this document by using Graph API. By using Graph API we can set "isOnlineMeeting" property to true, and "onlineMeetingProvider" property to "teamsForBusiness".
I'm using Google Calendar Api v3 for .Net in my project. I need to create event and send notification when any attendee replies to event ("Yes", "No"). I read the api documentation and tried what it says. Below is the code that i create service account credential and create event with organizer and creator information.
I have the domain "example.net" and trying to create event with organizer that has email "organizer#example.net" , both organizer and attendees can be from different domains like "gmail, outlook".
But whenever i create the event, api automatically sends email to attendees about event information, but organizer looks like "calendar#example-calendar.iam.gserviceaccount.com" which is defined in "calendar.json" file. So whenever attendee replies the event, organizer cannot get email about what an attendee replied for event. I couldnt able to set organizer to "organizer#example.com", it is always "calendar#example-calendar.iam.gserviceaccount.com".
Please look at the code below and tell me how can i set the organizer,creator of event to "organizer#example.com" (which also can be in different email address with different domain like gmail, outlook), or how can i make google calendar sends email notification to event organizer when any attendee replies to event (yes or no)
private static Event SendCalendarInvitation()
{
try
{
string credPath = #"C:\calendar.json";
var json = File.ReadAllText(credPath);
var cr = JsonConvert.DeserializeObject<PersonalServiceAccountCred>(json);
var xCred = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(cr.client_email)
{
Scopes = new[] {
CalendarService.Scope.Calendar
}
}.FromPrivateKey(cr.private_key));
// Create the service
CalendarService service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = xCred
});
Event calendarEvent = new Event
{
Summary = "Example Event",
Location = "Los Angeles",
Description = "Description",
Start = new EventDateTime()
{
DateTime = new DateTime(2018, 6, 2, 10, 0, 0),
TimeZone = "America/Los_Angeles"
},
End = new EventDateTime()
{
DateTime = new DateTime(2018, 6, 2, 12, 0, 0),
TimeZone = "America/Los_Angeles"
},
Attendees = new List<EventAttendee>()
{
new EventAttendee() { Email = "organizer#example.com", Organizer = true},
new EventAttendee() { Email = "attendee#gmail.com"}
},
Creator = new Event.CreatorData()
{
Email = "organizer#example.com",
DisplayName = "Organizer"
},
Organizer = new Event.OrganizerData()
{
Email = "organizer#example.com",
DisplayName = "Organizer"
},
Reminders = new Event.RemindersData()
{
UseDefault = false,
Overrides = new List<EventReminder>()
{
new EventReminder()
{
Method = "email",
Minutes = 30
},
new EventReminder()
{
Method = "email",
Minutes = 14400
}
}
}
};
Event calendarEventResult = null;
var statusCode = System.Net.HttpStatusCode.Accepted;
try
{
var request = service.Events.Insert(calendarEvent, "primary");
request.SendNotifications = true;
calendarEventResult = request.Execute();
}
catch (Exception ex)
{
statusCode = System.Net.HttpStatusCode.BadRequest;
}
return calendarEventResult;
}
catch (Exception ex)
{
return null;
}
}
Events have a single organizer which is the calendar containing the main copy of the event. Events can also have multiple attendees. An attendee is usually the primary calendar of an invited user.
If the service account is set to be the organizer then you are sending the events on behalf of the service account. Which is a dummpy user. When it invites a user to an even the user will be notified that the person who created the event has added them in this case its "calendar#example-calendar.iam.gserviceaccount.com" There is no way to change this.
I haven't tried this. But if you do an Event.patch and have the service account set your personal account to be organizer it should then send mails from you and not the service account.
// Building the initial request.
var request = service.Events.Patch(body, calendarId, eventId);
// Applying optional parameters to the request.
request = (EventsResource.PatchRequest)SampleHelpers.ApplyOptionalParms(request, optional);
// Requesting data.
return request.Execute();
code ripped from Events sample
Order of testing this idea.
Create an event.
Patch the event updating the organizer to be yourself instead of the service account.
Do an event get see wither or not you were able to update this field. Documentation says that it should be writable.
Add an attendee to the event. check what email its sent from.
IF it still doesn't work try setting your email as owner as well as organizer but i am worried the service account wont be able to edit it then.
I am trying to send meeting invitation by Appointment class of EWS.
I have a requirement to send different attachment to different recipients. I am referencing the following links:
https://social.msdn.microsoft.com/Forums/exchange/en-US/cf4b9d9a-7bbb-4caa-9d55-300371fa84ac/ews-attachment-not-sent-with-invitation
This link is just for one or more than one attachment might to be sent but I need each recipients should have different-2 attachments.
I am trying to following in my code that might be helpful to better understand the challenge:
Appointment appointment = new Appointment(service) {
Start = DateTime.Now,
End = DateTime.Now.AddHours(2),
Subject = "XYZ Invitation",
Location = "XYZ Tower, Room No. 3",
IsAllDayEvent = false,
AllowNewTimeProposal = false,
IsResponseRequested = false,
Body = new MessageBody(BodyType.HTML, html),
ReminderMinutesBeforeStart = 60
};
int i = 0;
foreach(var attendee in attendies) { // List<string>
appointment.Attachments.AddFileAttachment(Image[i], file);
appointment.Attachments[0].IsInline = true;
appointment.Attachments[0].ContentId = Image[i];
FolderId folderCalendar = new FolderId(WellKnownFolderName.Calendar, attendee);
appointment.Save(folderCalendar, SendInvitationsMode.SendToNone);
appointment.RequiredAttendees.Add(attendee);
i++;
appointment.Update(ConflictResolutionMode.AutoResolve, SendInvitationsOrCancellationsMode.SendOnlyToAll);
}
You must use Bind method of Appointment class in order to send different attachment second time to add receipt.
appointment.Bind(ExchangeService, ItemId, PropertySet);
Binds to an existing appointment and loads the specified set of properties. Calling this method results in a call to Exchange Web Services (EWS).
I hope it helps you.
I'm trying to create a program in C# which should make it able to create appointments in someone else's Outlook calendar. I have code which makes it able to create appointments in my own calendar. I searched on Google and I found I should use impersonation. So I added the line:
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, emailAddress);
This is my code:
private void button2_Click(object sender, EventArgs e) {
try{
ExchangeService service = new ExchangeService();
service.UseDefaultCredentials = true;
service.Credentials = new WebCredentials("Test#domain.com", "password");
service.AutodiscoverUrl("Test#domain.com", adAutoDiscoCallBack);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "Test2#domain.com");
Appointment appointment = new Appointment(service);
// Set the properties on the appointment object to create the appointment.
appointment.Subject = "Tennis lesson";
appointment.Body = "Focus on backhand this week.";
appointment.Start = DateTime.Now.AddDays(2);
appointment.End = appointment.Start.AddHours(1);
appointment.Location = "Tennis club";
appointment.ReminderDueBy = DateTime.Now;
// Save the appointment to your calendar.
appointment.Save(SendInvitationsMode.SendToNone);
// Verify that the appointment was created by using the appointment's item ID.
Item item = Item.Bind(service, appointment.Id, new PropertySet(ItemSchema.Subject));
}
}catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
internal static bool adAutoDiscoCallBack(string redirectionUrl) {
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https") {
result = true;
}
return result;
}
The problem is that I keep getting this error ""The SMTP-address has no mailbox associated with it."
Is it because impersonation isn't allowed on the server? If so how do I allow it?
I hope someone can help.
Ps: Sorry for the bad english
A few suggestions if this is Office365 or Exchange 2013 you first need the PrimarySMTP address of the Mailbox you wish to access eg
String MailboxToAccess = "PrimarySMTP#domain.demo";
Note for some tenants the SMTP and UPN/Logon are the same but that is not always the case.
This is what user you are going to be impersonating eg
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, MailboxToAccess);
You should also add in the X-AnchorMailbox header https://learn.microsoft.com/en-us/archive/blogs/webdav_101/best-practices-ews-authentication-and-access-issues eg
service.HttpHeaders.Add("X-AnchorMailbox", MailboxToAccess);
Also when you go to save the Appointment use the FolderId class with the Mailbox overload to ensure your hitting the correct Mailbox eg
FolderId CalendarFolderId = new FolderId(WellKnownFolderName.Calendar, MailboxToAccess);
appointment.Save(CalendarFolderId,SendInvitationsMode.SendToNone);
Cheers
Glen
I have an application that creates appointments in calendars in Exchange Online for Office 365. I'm using EWS Managed API.
public void CreateAppoitment(string principalName, int taskId) {
ExchangeService service = createService(principalName);
ItemView itemView = new ItemView(1000);
itemView.PropertySet = new PropertySet(BasePropertySet.IdOnly);
List<Appointment> toCreate = new List<Appointment>();
// Create the appointment.
Appointment appointment = new Appointment(service);
// Set properties on the appointment.
appointment.Subject = "Test Appointment";
appointment.Body = "The appointment ...";
appointment.Start = new DateTime(2014, 6, 18, 9, 0, 0);
appointment.End = appointment.Start.AddDays(2);
ExtendedPropertyDefinition epdTaskId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Appointment, "TASK_Id", MapiPropertyType.Integer);
appointment.SetExtendedProperty(epdTaskId, taskId);
appointment.IsResponseRequested = false;
toCreate.Add(appointment);
ServiceResponseCollection<ServiceResponse> createResponse = service.CreateItems(toCreate, WellKnownFolderName.Calendar, MessageDisposition.SaveOnly, SendInvitationsMode.SendToNone);
}
Note I'm setting ExtendedPropertyDefinition "TASK_Id"
I'm using impersonate to create appointments in users's calendars:
private ExchangeService createService(string principalName) {
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
service.UseDefaultCredentials = false;
service.Credentials = new WebCredentials("XXXX", "YYYY");
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, principalName);
return service;
}
Then, given a taskId, I want to delete all appointments with this taskId:
public void DeleteAppointment(string principalName, int appointmentId) {
ExchangeService service = createService(principalName);
ItemView itemView = new ItemView(1000);
itemView.PropertySet = new PropertySet(BasePropertySet.IdOnly);
ExtendedPropertyDefinition epdTaskId = new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.Appointment, "TASK_Id", MapiPropertyType.Integer);
SearchFilter filterOnTaskId = new SearchFilter.IsEqualTo(epdTaskId, appointmentId);
FindItemsResults<Item> appointments = service.FindItems(WellKnownFolderName.Calendar, filterOnTaskId, itemView);
List<ItemId> toDelete = appointments.Select(item => item.Id).ToList();
if (toDelete.Count > 0) {
ServiceResponseCollection<ServiceResponse> response = service.DeleteItems(
toDelete, DeleteMode.MoveToDeletedItems, SendCancellationsMode.SendToNone,
AffectedTaskOccurrence.SpecifiedOccurrenceOnly);
foreach (ServiceResponse del in response) {
if (del.Result == ServiceResult.Error) {
//...
}
}
}
}
But this way service.FindItems() only returns the principalName's appointment with TASK_Id = taskId and I want appointments of all users. Is there a way to to this?
The Exchange Managed API and Exchange Web Services only give access to the calendar of one user at a time -- either directly by using the credentials of a user or indirectly by using impersonation to give a service account access to a user's calendar.
To search multiple calendars at once requires a different technique. One option that comes to mind is using the eDiscovery operations in Exchange 2013. Although they are usually used to find email for legal reasons, you may be able to use the same process. Unfortunately, the documentation for eDiscovery is pretty sparse right now, but you can see the EWS operations that are available here: eDiscovery in EWS in Exchange, and you can find the corresponding EWS Managed API methods on the ExchangeService object.