Exchange API incorrect Subject - c#

When ever I create a meeting in Outlook, Subject field for an appointment is going through incorrectly. Instead of something like "Test" I get the name of the user who created an appointment.
-> bold = title, admin = creator name
-> admin = creator name even though it suppose to be subject.
foreach (Appointment a in room.appointments)
m.Subject = a.Subject
Is this a known issue; Is there another field that is responsible for subject?

This is actually not an "issue" but a "feature" of Exchange's workflow for meeting invites. The default on a room resource is to replace the subject with the orgranizer. This can be changed for a room with a PowerShell command:
Set-Calendarprocessing -Identity:roommb -AddOrganizerToSubject:$false -DeleteSubject:$false
Of course you need proper permissions to do this, or else bribe your Exchange admin!

Related

Using Microsoft's EWS to create online Lync/Skype meeting

Anybody knows how to create meeting request with online conference(Lync/Skype) using EWS?
So my approach is first getting an online and regular meeting created via Outlook and then simulate the creation of event with the same property.
Here is my code snippet for getting the meeting (calendarView is already initialized with start date, end date etc.):
ExtendedPropertyDefinition extendedOnlineMeetingProperty =
new ExtendedPropertyDefinition(new Guid("{00062008-0000-0000-c000-000000000046}"), 34112,
MapiPropertyType.Integer);
var properties = new PropertySet(
ItemSchema.Id,
AppointmentSchema.ICalUid,
ItemSchema.Subject,
AppointmentSchema.Start,
AppointmentSchema.End,
AppointmentSchema.Organizer,
AppointmentSchema.Location,
AppointmentSchema.LegacyFreeBusyStatus,
AppointmentSchema.IsCancelled,
AppointmentSchema.ICalRecurrenceId,
AppointmentSchema.MyResponseType, // Mandatory Meeting.MyResponseType can be retrieved without a search in the participant list
ItemSchema.LastModifiedTime,
AppointmentSchema.IsOnlineMeeting,
AppointmentSchema.IsMeeting,
ItemSchema.DisplayTo) { };
properties.Add(extendedOnlineMeetingProperty);
var activeResults = service.FindAppointments(WellKnownFolderName.Calendar, calendarView).ToList();
if (activeResults.Count > 0)
{
service.LoadPropertiesForItems(activeResults, properties);
}
I got the property IsOnlineMeeting with the correct bool value (tested -
created online and regular meeting with Outlook) in variable activeResults but I do not understand where to get conference link and other Lync/Skype properties needed for joining a conference.
Also I am not sure where and how to assign the values of Lync/Skype conference URL and other properties.
Sometimes I ask myself if it's worth it to developed some app based on MS products since their documentation suck.
After one week of cursing MS I have found a solution. Using the tool MFCMAPI you can check what property and their values your item in mailbox have.
download the program link
build and run it
Session - Logon - choose your mail profile - pick the mailbox and double click
actions - open special folder - calendar - double click on calendar
open the item with online S4B/Lync conference
the UC* properties are the one I was looking for.
If you open the property you can see something like this on the top:
ag: 0x8096001E
Type: PT_STRING8
DASL: http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/UCMeetingSetting
Named Prop Name: UCMeetingSetting
Named Prop Guid: {00020329-0000-0000-C000-000000000046} = PS_PUBLIC_STRINGS
So my definition of the extended property was wrong. It is not only one property but actually you need all 7 of them.
So the definition should be:
private static ExtendedPropertyDefinition CreateOnlineMeetingProperty()
{
ExtendedPropertyDefinition extendedUCMeetingSetting =
new ExtendedPropertyDefinition(new Guid("{00020329-0000-0000-C000-000000000046}"), "UCMeetingSetting",
MapiPropertyType.String);
return extendedUCMeetingSetting;
}
With the correct extended definition you can get the values from the item easily.
accessing the Value of ExtendedProperties
Calling TryGetProperty
var activeResults = service.FindAppointments(new
FolderId(WellKnownFolderName.Calendar, resource.Email),calendarView).ToList();
service.LoadPropertiesForItems(activeResults, properties);
foreach (Appointment result in activeResults)
{
// 1.
var b = result.ExtendedProperties[1].Value;
// 2.
string UCMeetingSetting;
result.TryGetProperty(extendedUCMeetingSetting, out UCMeetingSetting);
}
using steps above you can get whatever extended property you want, not only Unified Communications (UC) properties.
Ok, I managed to have this working (almost!) by setting just one of the extended properties:
appointment.SetExtendedProperty(
new ExtendedPropertyDefinition(
new Guid("00020329-0000-0000-C000-000000000046"),
"OnlineMeetingExternalLink",
MapiPropertyType.String
),
skypeMeeting.JoinUrl
);
I say almost because the appointment doesn't look exactly like a Skype meeting when you open it in Outlook: doesn't have the footer will the Join link and phone number etc.
Maybe there are other differences, but for now we see it in Skype for business with the Join button and also we see the it in the Outlook reminder with the Join button.
As a workaround, we have to hard-code the body content of the appointment.
Also conference ID, can be taken using UCWA 2.0 (https://learn.microsoft.com/en-us/skype-sdk/ucwa/myonlinemeetings_ref)
We used UCWA 2.0 to create the Skype conference call and attached it to the EWS appointment object.

Given Email display name not updated in outlook

I want to change my email display name which is sent by my MVC application.
actually, the email address is: sample#company.com
the default display name is: Company Sample.
Now i want to change that display name into "SomeOne" but it not works. i have tried below items,
Tried Email display name property:
MailAddress from = new MailAddress("sample#company.com", "SomeOne");
It works fine in Gmail but in outlook, the display name not changed.
MailAddress from = new MailAddress("sample#company.com", "\\SomeOne\\");
It will change the display name in outlook but double quote(") added at the last like this
SomeOne"
objMail.From = new MailAddress("<DisplayName>EmailAddress#domain.com");
Not works.
Can you please provide any suggestions..?
Thanks,
Nagaraj M
Your first address is correct
MailAddress from = new MailAddress("sample#company.com", "SomeOne");
And I believe the third is backwards
//objMail.From = new MailAddress("<DisplayName>EmailAddress#domain.com");
objMail.From = new MailAddress("DisplayName<EmailAddress#domain.com>");
Outlook presents other challenges. If the address is in your Outlook contacts it may overwrite the friendly address coming in. Same if you are sending from Outlook to a previous friendly address. In most cases clearing out the Most Recently Used (MRU) cache will take care of it. There are a few ways of doing this, some require working with the registry to find the location of the actual file
Clearing Outlook Most Recently Used Lists
your first address is correc

EWS API get Sender name when Cc information is missing

In work we have service mailbox and suddenly started coming mails with attachement daily, no one know why and how to stop that and nobody need that.
So im writing deleting script and i dont know how to detect/find these emails, because Cc field is blank and email with same Subject from same email address is already coming but difference is between alias, how can i read information from the image ?
I need declare a SearchFilter like
SearchFilter subjectFilter =
new SearchFilter.ContainsSubstring(ItemSchema.?WHATHERE?, "JOBRUN <something#company.com>");
Thank you :-)
If I do understand you correctly, and based on your screenshot, you want to get those emails that have the string JOBRUN in their Display Name (not in their Subject as your variable name states).
Altough I'm not sure if the following does the filtering based on the email-address of the sender only or additionally based on the sender's displayname (the documentation is pretty poor...), you could try the following:
var filter = new SearchFilter.ContainsSubstring(EmailMessageSchema.Sender, "JOBRUN");

Facebook API - getting friend list with detail info again

I'm using Facebook SDK ( http://facebooksdk.net ) and want to get friend list with the following information:
1. ID
2. Name
3. Photo
4. link
5. Email
6. etc...
I have read Facebook's documentation and different posts of forum (including stackoverflow), but I'm confused. After it I'm not sure, is it possible to get this information by API request or not. First at all, this request returns only ID and name data:
var client = new FacebookClient("XXX");
dynamic friends = client.Get("/me/friends");
Next step - try to modify this request to specify returned fields:
var client = new FacebookClient("XXX");
dynamic friends = client.Get("/me/friends?fields=about,bio,age_range,first_name,gender,address,email,location,link,languages,username,last_name,timezone,updated_time");
it returns only some fields:
"first_name": "XXX",
"gender": "male",
"link": "https://www.facebook.com/XXX",
"username": "XXX",
"last_name": "XXX",
"updated_time": "2013-09-07T12:18:34+0000",
"id": "XXX"
is it possible to return more fields? As I understood, it depends on permissions. I try to set these permissions. I go to Applications -> MyApp -> Permissions, and see, that field "User & Friend Permissions" is empty. I try to set some permissions, i.e.
user_about_me,friends_about_me
and after click "Save" button I see the message:
Changes saved. Note that your changes may take several minutes to
propagate to all servers.
but field "User & Friend Permissions" is empty again. First question : why and how can I see all set permissions?
secondly - I don't see any changes in my request via FacebookClient (but field "About" is added to request). Why?
Thanks
The fields that you can get without any extra permissions:
first_name
gender
link
username
last_name
updated_time
id
With permissions-
friends_about_me - about, bio
friends_location - location
friends_likes - languages
Invalid fields (I don't know from where you saw these)-
age_range
address
email
timezone
Another thing that you are not getting all the fields is because the permissions are not being asked by the user (and hence not granted any to your app).
This is because, you have to add the permissions in your code, while login-in the user- not just adding permissions in the App Settings.
For eg, if you are using javascript sdk, it is done using the scope parameter. Reference
You can always test your call here: Graph API Explorer
To answer your first question, you can see the answer here, use the Facebook graph api and search /{user id}/permissions.
Some clerification for the rest. You can't get friends email address as answered here. In order to get the friends profile picture you need to add the field picture (you can specify the size like this picture.width().height().
I reccomend you try to use Facebooks Graph Api Explorer to play with the permissions and the info you request.

iCalendar does not create an event for organizer

I’m trying to create an event in my Microsoft Outlook calendar by using iCalendar standard. I’ve sent an email with content type “text/calendar” to my Exchange mailbox from .NET application.
It arrives to Outlook as an meeting request. Everything looks good, till the moment when I click the received meeting request, Outlook displays it as an empty calendar view with the text: “Meeting cannot be found in the calendar”.
I don’t understand why – I wanted to create an event and it is trying to find some existing?
If I send exactly the same email to whoever participant of the meeting except the organizer, it creates an event in their calendars and everything seems to be ok.
I’ve found that it is caused by the “ORGANIZER” property. If it is set to organizer’s email (my email) and I send meeting request to myself, an event is not created with the information “Meeting cannot be found in the calendar”.
So the question is why it doesn’t create an event for organizer? Organizer must have that event created to be notified by other participants if they have accepted or cancelled the meeting.
Here is the iCalendar:
BEGIN:VCALENDAR
PRODID:-//Company//Product 3.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:20130225T200000Z
DTEND:20130225T203000Z
DTSTAMP:20130225T143039Z
ORGANIZER;CN="John Doe":mailto:john.doe#domain.com
UID:20130225T143039Z#domain.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;RSVP=TRUE;CN="John Smith"
;X-NUM-GUESTS=0:mailto:john.smith#domain.com
CLASS:PUBLIC
CREATED:20130225T143039Z
DESCRIPTION:
LAST-MODIFIED:20130225T143039Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Booking test
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
Let’s say that organizer want to create an meeting for 2 attendees. He fills in a form in the booking system.
The booking system sends email containing iCalendar standard to himself and to 2 meeting attendees.
This scenario doesn’t work.
It is not possible to create an event (cancellable meeting object) in the calendar of the organizer. The client thinks that email containing iCalendar format is just notification for attendee of the meeting already created in the organizer calendar. If such an email arrives to organizer’s mailbox, client app doesn’t create an event in the organizer’s calendar. It assumes that an event was created by organizer himself. E.g.: Outlook tells you in that case that “Meeting cannot be found in the calendar”.
If you ask Microsoft support about it, they only tell you that they does not support open standards: http://support.microsoft.com/kb/2269506
Working solution to this problem is to use platform services (Exchange Web Services or Google Calendar API) to create an event in the organizer’s calendar. Forget iCalendar standard.
The services can be configured for sending notifications to attendees automatically.
So it is enough to pass “SendInvitationsMode.SendToAllAndSaveCopy” if you’re using EWS:
Appointment appointment = new Appointment(service);
appointment.Subject = "Status Meeting";
appointment.Body = "The purpose of this meeting is to discuss status.";
appointment.Start = new DateTime(2014, 3, 1, 9, 0, 0);
appointment.End = appointment.Start.AddHours(2);
appointment.Location = "Conf Room";
appointment.RequiredAttendees.Add("user1#contoso.com");
appointment.RequiredAttendees.Add("user2#contoso.com");
appointment.OptionalAttendees.Add("user3#contoso.com");
appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
or set “sendNotifications” parameter to true in case of Google Calendar API.
You don’t need to send an email to every particular attendee.
This is a bit of an old issue, but i think it is caused from using
METHOD:REQUEST
This marks that the ical should be updated, not that it is a new item. Instead, use
METHOD:PUBLISH
I can confirm that this works with DDay.iCal and Outlook Calendars.
This drove me mad for a week, so it is nice to see someone else confirming what I suspected. There is actually a relatively simple solution, which solves the question, although it is not very elegant. I can understand why one would not be allowed to take the role of Organiser from an outside source, but it is annoying that you can't.
Send out 2 invites. One to yourself (or whoever the organiser is) and then a different one to everyone else.
The one to yourself should have something else other than you down as the ORGANSISER, e.g. ORGANIZER:donotreply#outlook.com
The one to everyone else should have your email down as the organizer.
For this approach to work, you should set METHOD:REQUEST. If you set it to PUBLISH you will get duplicates on updates.
This approach means you get the meeting in your diary and you also get replies (to get replies you need to include the following line for each attendee:
ATTENDEE;CN="The Name";RSVP=TRUE:mailto:the_email#address.com.)
Note that the UID is the same for both versions of the file. It helps if the ORGANISER gets the Invite first so they can accept it before they start getting replies, otherwise people will be replying to something that effectively does not yet exist. That wont stop them accepting the invite, but it might be a little confusing for the ORGANIZER. To help with this I put in a slight delay between email 1 and 2.
I would assume that your problem is because Exchange assumes that the organizer of the event is also the originator of the event. Which seems fair enough, as otherwise it would be child's play to send meetings to people making them the organizer and they would be added automatically to the person's calendar.
All that said, no idea how to get around the issue.
the behavior of event invitation being sent by email is described in rfc6047 which further extends the icalendar RFC (RFC5545).
section 2 and section 3 on security, summarizes two spoofing threats:
spoofing the "Organizer", and spoofing an "Attendee"
that is
spoof#xyz.example.net is not allowed to modify or cancel a meeting that was organized by a#example.com.
to your case:
did you send the invitation from the same email address as your exchange (talking about the From: in the mail not the Organizer:mailto ? if not it might be worth trying to send it via the exchange address.
should above not work, to address your need for the organizer to have the invitation in its calendar you probably will need to add it programmatically in the organizer's agenda as it is likely that the CUA (Calendar User Agent) or Exchange does not allow a 3rd party mailer to add events in agenda without end-user UI usage.
In recent months ,our service also meet the same problem as you:
our service create meeting calendar for organizer and attendees,
if attendees contains organizer ,organizer (as a atteendee) can get a calendar email,
but it does neither be allowed to receive/reject the meeting(the button is disabled) nor see it in calendar(no calendar event).
finally, I notice that only when under following condition this will happen:
1. mail.From = organizer
2. Ateendees.contains(organizer) //case-insensitive.
So , I simply change my code to follwing , and it works fine for all attendees (include organizer):
if (!attendeeEmail.ToLower().Contains(organizer.Address.ToLower()))
{
message.From = organizer;
}
else
{
//such as your actual email sender, in our case, our mail sender use another email,
//say ActualSender,and if leave empty, then our mail sender will fill as:
message.From = ActualSenderEmail;
}

Categories