vonwolf
vonwolf

Reputation: 655

Is it possible to create a meeting request for outlook with nodeJS?

I am developing a very basic calendar with Angular and Node and I haven't found any code on this.

Workflow is the following : create an event, input the recipient's e-mail address, validate the event. This triggers an e-mail sent to the recipient. The mail should be in the outlook meeting request format (not an attached object).

This means that when received in outlook the meeting is automatically added in the calendar.

Is this possible? If yes is it possible with only javascript on Node side?

Upvotes: 12

Views: 14205

Answers (5)

Juncheng Zhu
Juncheng Zhu

Reputation: 11

Please check the following sample:

const options = {
    authProvider,
};

const client = Client.init(options);

const onlineMeeting = {
  startDateTime: '2019-07-12T14:30:34.2444915-07:00',
  endDateTime: '2019-07-12T15:00:34.2464912-07:00',
  subject: 'User Token Meeting'
};

await client.api('/me/onlineMeetings')
    .post(onlineMeeting);

More Information: https://learn.microsoft.com/en-us/graph/api/application-post-onlinemeetings?view=graph-rest-1.0&tabs=http

Upvotes: 0

Ingit Bhatnagar
Ingit Bhatnagar

Reputation: 61

Instead of using 'ical-generator', I used 'ical-toolkit' to build a calender invite event. Using this, the invite directly gets appended in the email instead of the attached .ics file object.

Here is a sample code:

const icalToolkit = require("ical-toolkit");

//Create a builder
var builder = icalToolkit.createIcsFileBuilder();
builder.method = "REQUEST"; // The method of the request that you want, could be REQUEST, PUBLISH, etc

//Add events
builder.events.push({
  start: new Date(2020, 09, 28, 10, 30),
  end: new Date(2020, 09, 28, 12, 30),
  timestamp: new Date(),
  summary: "My Event",
  uid: uuidv4(), // a random UUID
  categories: [{ name: "MEETING" }],
  attendees: [
    {
      rsvp: true,
      name: "Akarsh ****",
      email: "Akarsh **** <akarsh.***@abc.com>"
    },
    {
      rsvp: true,
      name: "**** RANA",
      email: "**** RANA <****[email protected]>"
    }
  ],
  organizer: {
    name: "A****a N****i",
    email: "A****a N****i <a****a.r.n****[email protected]>"
  }
});

//Try to build
var icsFileContent = builder.toString();

//Check if there was an error (Only required if yu configured to return error, else error will be thrown.)
if (icsFileContent instanceof Error) {
  console.log("Returned Error, you can also configure to throw errors!");
  //handle error
}

var mailOptions = { // Set the values you want. In the alternative section, set the calender file
            from: obj.from,
            to: obj.to,
            cc: obj.cc,
            subject: result.email.subject,
            html: result.email.html,
            text: result.email.text,
            alternatives: [
              {
                contentType: 'text/calendar; charset="utf-8"; method=REQUEST',
                content: icsFileContent.toString()
              }
            ]
          }

        //send mail with defined transport object 
        transporter.sendMail(mailOptions, function(error, info){
            if(error){
                console.log(error);
            }
            else{
                console.log('Message sent: ' + info.response);  
            }
        });

Upvotes: 3

Gautam Singh
Gautam Singh

Reputation: 1138

If you do not want to use smtp server approach in earlier accepted solution, you have Exchange focused solution available. Whats wrong in current accepted answer? it does not create a meeting in sender's Calendar, you do not have ownership of the meeting item for further modification by the sender Outlook/OWA.

here is code snippet in javascript using npm package ews-javascript-api

var ews = require("ews-javascript-api");
var credentials = require("../credentials");
ews.EwsLogging.DebugLogEnabled = false;

var exch = new ews.ExchangeService(ews.ExchangeVersion.Exchange2013);

exch.Credentials = new ews.ExchangeCredentials(credentials.userName, credentials.password);

exch.Url = new ews.Uri("https://outlook.office365.com/Ews/Exchange.asmx");

var appointment = new ews.Appointment(exch);

appointment.Subject = "Dentist Appointment";
appointment.Body = new ews.TextBody("The appointment is with Dr. Smith.");
appointment.Start = new ews.DateTime("20170502T130000");
appointment.End = appointment.Start.Add(1, "h");
appointment.Location = "Conf Room";
appointment.RequiredAttendees.Add("[email protected]");
appointment.RequiredAttendees.Add("[email protected]");
appointment.OptionalAttendees.Add("[email protected]");

appointment.Save(ews.SendInvitationsMode.SendToAllAndSaveCopy).then(function () {
    console.log("done - check email");
}, function (error) {
    console.log(error);
});

Upvotes: 5

vonwolf
vonwolf

Reputation: 655

For those still looking for an answer, here's how I managed to get the perfect solution for me. I used iCalToolkit to create a calendar object.

It's important to make sure all the relevant fields are set up (organizer and attendees with RSVP).

Initially I was using the Postmark API service to send my emails but this solution was only working by sending an ics.file attachment.

I switched to the Postmark SMTP service where you can embed the iCal data inside the message and for that I used nodemailer.

This is what it looks like :

        var icalToolkit = require('ical-toolkit');
        var postmark = require('postmark');
        var client = new postmark.Client('xxxxxxxKeyxxxxxxxxxxxx');
        var nodemailer = require('nodemailer');
        var smtpTransport = require('nodemailer-smtp-transport');

        //Create a iCal object
        var builder = icalToolkit.createIcsFileBuilder();
        builder.method = meeting.method;
        //Add the event data

        var icsFileContent = builder.toString();
        var smtpOptions = {
            host:'smtp.postmarkapp.com',
            port: 2525,
            secureConnection: true,
            auth:{
               user:'xxxxxxxKeyxxxxxxxxxxxx',
               pass:'xxxxxxxPassxxxxxxxxxxx'
            }
        };

        var transporter = nodemailer.createTransport(smtpTransport(smtpOptions));

        var mailOptions = {
            from: '[email protected]',
            to: meeting.events[0].attendees[i].email,
            subject: 'Meeting to attend',
            html: "Anything here",
            text: "Anything here",
            alternatives: [{
              contentType: 'text/calendar; charset="utf-8"; method=REQUEST',
              content: icsFileContent.toString()
            }]
        };

        //send mail with defined transport object 
        transporter.sendMail(mailOptions, function(error, info){
            if(error){
                console.log(error);
            }
            else{
                console.log('Message sent: ' + info.response);  
            }
        });

This sends a real meeting request with the Accept, decline and Reject button.

It's really unbelievable the amount of work you need to go through for such a trivial functionality and how all of this not well documented. Hope this helps.

Upvotes: 14

mike.k
mike.k

Reputation: 3447

It should be possible as long as you can use SOAP in Node and also if you can use NTLM authentication for Exchange with Node. I believe there are modules for each.

I found this blog very helpful when designing a similar system using PHP

Upvotes: 0

Related Questions