Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 340
vonwolf Avatar asked Jun 26 '15 20:06

vonwolf


People also ask

How do I send a calendar invite in node JS?

If we need to send calendar invites just create a calendar object from the above-mentioned function and then send its return object to the below sendemail function. sendemail, };


3 Answers

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);
});
like image 40
Gautam Singh Avatar answered Sep 28 '22 07:09

Gautam Singh


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.

like image 175
vonwolf Avatar answered Sep 28 '22 07:09

vonwolf


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);  
            }
        });
like image 22
Ingit Bhatnagar Avatar answered Sep 28 '22 07:09

Ingit Bhatnagar