nmarus / node-ews

A simple JSON wrapper for the Exchange Web Services (EWS) SOAP API.
MIT License
116 stars 52 forks source link

Can't create a calendar meeting with more than 2 attendees #60

Closed eduarte closed 7 years ago

eduarte commented 7 years ago

I am trying to create meetings using the node-ews library. I am using this https://msdn.microsoft.com/en-us/library/office/dd633661(v=exchg.80).aspx

These are the arguments that I am sending to the function "Create Item" { "attributes": { "SendMeetingInvitations": "SendToAllAndSaveCopy" }, "SavedItemFolderId": { "DistinguishedFolderId": { "attributes": { "Id": "calendar" } } }, "Items": { "CalendarItem": { "Subject": "Test Meeting", "Body": { "attributes": { "BodyType": "Text" }, "$value": "Let's learn to really work as a team and then have lunch!" }, "ReminderMinutesBeforeStart": "60", "Start": "2017-08-28T23:00:00.000Z", "End": "2017-08-29T00:00:00.000Z", "Location": "Conf Room", "RequiredAttendees": [ { "Mailbox": { "Address": "email1@email.com" } }, { "Mailbox": { "Address": "email2@email.com" } }, { "Mailbox": { "Address": "email3@email.com" } } ], "TimeZoneContext": { "TimeZoneDefinition": { "attributes": { "Id": "Central Standard Time" } } } } } }

after sending this arguments the function only takes the first email and the last email only 2 emails are being added to the calendar meeting

kcastrotech commented 7 years ago

Try editing the "node_modules\soap\lib\client.js" file and add console.log("XML:",xml); someplace before the "self.emit(..."line which in my case is line 263. It should look something like this:

  if(self.security && self.security.postProcess){
    xml = self.security.postProcess(xml);
  }
console.log("XML:",xml); //Log the XML string for debugging
  self.lastMessage = message;
  self.lastRequest = xml;
  self.lastEndpoint = location;

  self.emit('message', message);
  self.emit('request', xml);

This should output the actual XML that is getting sent to the server. Check that and see if all three attendees are present. If they are then the problem is somewhere on your server, but if not then it is somewhere in the soap XML generation.

eduarte commented 7 years ago

This is the XML, I can see the 3 emails (user1, user2, room), the meeting was created but it didn't include the user2.

See the attached image capture

`<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:wsi="http://ws-i.org/schemas/conformanceClaim/">

Test Meeting Let's learn to really work as a team and then have lunch! 60 2017-08-28T23:00:00.000Z 2017-08-29T00:00:00.000Z arenal@avantica.net emilio.duarte@avantica.net marco.salazar@avantica.net arenal@avantica.net `
eduarte commented 7 years ago

This is my code `var ewsArgs = { "attributes": { "SendMeetingInvitations": "SendToAllAndSaveCopy" }, "SavedItemFolderId": { "DistinguishedFolderId": { "attributes": { "Id": "calendar" } } }, 'Items': { 'CalendarItem': { 'Subject': 'Test Meeting', "Body": { "attributes": { "BodyType": "Text" }, "$value": 'Let\'s learn to really work as a team and then have lunch!' },

            'ReminderMinutesBeforeStart': '60',
            'Start': userRequest.start,
            'End': userRequest.end,
            'Location': userRequest.room,
            'RequiredAttendees': utils.setAttendees(userRequest.participants, userRequest.room),
            'TimeZoneContext': {
                'TimeZoneDefinition': {
                    "attributes": {
                        'Id': 'Central Standard Time'
                    }
                }
            }
        }
    }
};
console.log(JSON.stringify(ewsArgs, null, 2));
ews.run(ewsFunction, ewsArgs)
    .then(result => {
        var createItemResponse = result.ResponseMessages.CreateItemResponseMessage.attributes.ResponseClass;
        var conflicts = (createItemResponse == "Success" ? true : false);
        onSuccess(conflicts)
    })
    .catch(err => {
        console.log("[DEBUG]: " + err.message)
        onError(err.message)
    });`
eduarte commented 7 years ago

function setAttendees(emails, room) { var emailList = emails.split(","); var jsonObj = [] emailList.forEach(function(email) { jsonObj.push({ "Attendee": { "Mailbox": { "EmailAddress": email } } }); });

jsonObj.push({
    "Attendee": {
        "Mailbox": {
            "EmailAddress": room
        }
    }
});

return jsonObj;

}

eduarte commented 7 years ago

We are using Office 365 to handle our email

kcastrotech commented 7 years ago

Interesting... The XML looks good. What happens if you change the order of the attendees? I'd be curious if the middle attendee gets dropped or if the same user does.

eduarte commented 7 years ago

In this case, I added the room at the middle, the meeting was created but only took the 2 attendees not the room at the middle

image

emilio.duarte@avantica.net arenal@avantica.net marco.salazar@avantica.net Something that I see here is that the tags are being duplicated every time I add a new attendee is that OK? I think that in the documentation the tags that should be repited is etc
eduarte commented 7 years ago

Any comments?

kcastrotech commented 7 years ago

Good catch! I completely missed that and based on the Microsoft link you provided in your original post, that would be the problem. The XML should look like:

<t:RequiredAttendees>
    <t:Attendee>
        <t:Mailbox>
            <t:EmailAddress>emilio.duarte@avantica.net</t:EmailAddress>
      </t:Mailbox>
    </t:Attendee>
    <t:Attendee>
        <t:Mailbox>
            <t:EmailAddress>arenal@avantica.net</t:EmailAddress>
        </t:Mailbox>
    </t:Attendee>
    <t:Attendee>
        <t:Mailbox>
            <t:EmailAddress>marco.salazar@avantica.net</t:EmailAddress>
        </t:Mailbox>
    </t:Attendee>
</t:RequiredAttendees>

The node soap XML generator takes whatever key has an array and replicates that for every element in the array, so to get the proper output you will need to change it so that "Attendee" has the array by changing: 'RequiredAttendees': utils.setAttendees(userRequest.participants, userRequest.room), to

'RequiredAttendees': {
  'Attendee':utils.setAttendees(userRequest.participants, userRequest.room)
},

And then in your utils.setAttendees function you need to change both the email and room sections to push the object:

{
    "Mailbox": {
        "EmailAddress": email
    }
}

Note: You'll obviously need to change the "email" variable to "room" for the room section.

eduarte commented 7 years ago

that was the problem. it solve my question 👍 thanks