@checkfirst/nestjs-outlook v4.0.1
NestJS Outlook
An opinionated NestJS module for Microsoft Outlook integration that provides easy access to Microsoft Graph API for emails, calendars, and more.
Why We Built This
At Checkfirst, we believe that tools should be as transparent as the systems they support. This library is part of our commitment to the Testing, Inspection, Certification, and Compliance (TICC) industry, where we help transform operations through intelligent automation. While our ScheduleAI platform helps organizations optimize inspections, audits and fieldwork, we recognize that true innovation requires open collaboration. By sharing the Microsoft integration layer that powers our authentication, calendar, and email services, we're enabling developers to build robust, enterprise-grade applications without reimplementing complex Microsoft Graph protocols. Whether you're creating scheduling systems, communication tools, or productivity enhancers, this library embodies our philosophy that trust in technology starts with transparency and accessibility.
Table of Contents
- Features
- Installation
- Setup
- Permission Scopes
- Available Services and Controllers
- Events
- Example Application Architecture
- Local Development
- Support
- Contributing
- Code of Conduct
- About Checkfirst
- License
Features
- š Simple Microsoft authentication integration
- š Calendar management (create/update/delete events)
- š§ Email sending with rich content
- š Real-time notifications via webhooks
- š Event-driven architecture for easy integration
Installation
npm install @checkfirst/nestjs-outlookSetup
1. Database Setup
This library requires database tables to store authentication and subscription data. You can use the built-in migrations to set up these tables automatically.
For details, see the Migration Guide.
Alternatively, you can create the tables manually based on your database dialect (PostgreSQL, MySQL, etc.):
import { MigrationInterface, QueryRunner } from 'typeorm';
export class CreateOutlookTables1697025846000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
// Create required tables for webhooks, authentication, and user data
// See the Migration Guide for details
}
public async down(queryRunner: QueryRunner): Promise<void> {
// Drop tables in reverse order
await queryRunner.query(`DROP TABLE IF EXISTS outlook_webhook_subscriptions`);
await queryRunner.query(`DROP TABLE IF EXISTS microsoft_csrf_tokens`);
await queryRunner.query(`DROP TABLE IF EXISTS microsoft_users`);
}
}2. Microsoft App Registration
Register your application with Microsoft to get the necessary credentials:
- Go to the Azure Portal
- Navigate to Azure Active Directory > App registrations
- Create a new registration
- Configure redirects to include your callback URL (e.g.,
https://your-api.example.com/auth/microsoft/callback) - Add Microsoft Graph API permissions based on what features you need:
Calendars.ReadWrite- For calendar featuresMail.Send- For email featuresoffline_access- Required for all applications
3. Import Required Modules
Register the module in your NestJS application and include the module entities in TypeORM:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { ScheduleModule } from '@nestjs/schedule';
import { MicrosoftOutlookModule } from '@checkfirst/nestjs-outlook';
import * as path from 'path';
// Resolve the path to the outlook package
const outlookPackagePath = path.dirname(require.resolve('@checkfirst/nestjs-outlook/package.json'));
@Module({
imports: [
// Required modules
TypeOrmModule.forRoot({
// Your TypeORM configuration
entities: [
// Your app entities
__dirname + '/**/*.entity{.ts,.js}',
// Include outlook module entities
path.join(outlookPackagePath, 'dist', 'entities', '*.entity.js')
],
}),
ScheduleModule.forRoot(),
EventEmitterModule.forRoot(),
// Microsoft Outlook Module
MicrosoftOutlookModule.forRoot({
clientId: 'YOUR_MICROSOFT_APP_CLIENT_ID',
clientSecret: 'YOUR_MICROSOFT_APP_CLIENT_SECRET',
redirectPath: 'auth/microsoft/callback',
backendBaseUrl: 'https://your-api.example.com',
basePath: 'api/v1',
}),
],
})
export class AppModule {}4. Create an Auth Controller
The library provides a MicrosoftAuthController for handling authentication, but you can also create your own:
import { Controller, Get, Req } from '@nestjs/common';
import { MicrosoftAuthService, PermissionScope } from '@checkfirst/nestjs-outlook';
@Controller('auth')
export class AuthController {
constructor(
private readonly microsoftAuthService: MicrosoftAuthService
) {}
@Get('microsoft/login')
async login(@Req() req: any) {
// In a real application, get the user ID from your authentication system
const userId = req.user?.id.toString() || '1';
// Get the login URL with specific permission scopes
return await this.microsoftAuthService.getLoginUrl(userId, [
PermissionScope.CALENDAR_READ,
PermissionScope.EMAIL_READ,
PermissionScope.EMAIL_SEND
]);
}
}Permission Scopes
You can request specific Microsoft permissions based on what your application needs:
import { PermissionScope } from '@checkfirst/nestjs-outlook';
// Available permission scopes:
PermissionScope.CALENDAR_READ // Read-only access to calendars
PermissionScope.CALENDAR_WRITE // Read-write access to calendars
PermissionScope.EMAIL_READ // Read-only access to emails
PermissionScope.EMAIL_WRITE // Read-write access to emails
PermissionScope.EMAIL_SEND // Permission to send emailsWhen getting a login URL, specify which permissions you need:
// For a calendar-only app
const loginUrl = await microsoftAuthService.getLoginUrl(userId, [
PermissionScope.CALENDAR_READ
]);
// For an email-only app
const loginUrl = await microsoftAuthService.getLoginUrl(userId, [
PermissionScope.EMAIL_SEND
]);Available Services and Controllers
The library provides specialized services and controllers for Microsoft integration:
1. MicrosoftAuthService and MicrosoftAuthController
Handles the authentication flow with Microsoft:
// Get a login URL to redirect your user to Microsoft's OAuth page
const loginUrl = await microsoftAuthService.getLoginUrl(userId);After the user authenticates with Microsoft, they'll be redirected to your callback URL where you can complete the process.
2. CalendarService and CalendarController
Manage calendar operations:
// Create a calendar event
const event = {
subject: 'Team Meeting',
start: {
dateTime: '2023-06-01T10:00:00',
timeZone: 'UTC',
},
end: {
dateTime: '2023-06-01T11:00:00',
timeZone: 'UTC',
},
};
// Create the event
const result = await calendarService.createEvent(
event,
externalUserId,
calendarId
);
// Get user's default calendar ID
const calendarId = await calendarService.getDefaultCalendarId(externalUserId);The CalendarController provides a webhook endpoint at /calendar/webhook for receiving notifications from Microsoft Graph about calendar changes.
3. EmailService
Send emails:
// Create email message
const message = {
subject: 'Hello from NestJS Outlook',
body: {
contentType: 'HTML',
content: '<p>This is the email body</p>'
},
toRecipients: [
{
emailAddress: {
address: 'recipient@example.com'
}
}
]
};
// Send the email
const result = await emailService.sendEmail(
message,
externalUserId
);Events
The library emits events for various Microsoft activities that you can listen to in your application.
Available Events
USER_AUTHENTICATED- When a user completes authentication with MicrosoftEVENT_CREATED- When a new calendar event is createdEVENT_UPDATED- When a calendar event is updatedEVENT_DELETED- When a calendar event is deletedEMAIL_RECEIVED- When a new email is receivedEMAIL_UPDATED- When an email is updatedEMAIL_DELETED- When an email is deleted
Listening to Events
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { OutlookEventTypes, OutlookResourceData } from '@checkfirst/nestjs-outlook';
@Injectable()
export class YourService {
// Handle user authentication event
@OnEvent(OutlookEventTypes.USER_AUTHENTICATED)
async handleUserAuthenticated(externalUserId: string, data: { externalUserId: string, scopes: string[] }) {
console.log(`User ${externalUserId} authenticated with Microsoft`);
// Perform any custom logic needed when a user authenticates
}
// Handle calendar events
@OnEvent(OutlookEventTypes.EVENT_CREATED)
handleOutlookEventCreated(data: OutlookResourceData) {
console.log('New calendar event created:', data.id);
// Handle the new event
}
}Example Application Architecture
For a more complete example of how to structure your application using this library, check out the sample application included in this repository:
Path: samples/nestjs-outlook-example/
The sample app demonstrates a modular architecture with clear separation of concerns:
src/
āāā auth/
ā āāā auth.controller.ts # Handles Microsoft login and OAuth callback
ā āāā auth.module.ts # Configures MicrosoftOutlookModule for auth
ā
āāā calendar/
ā āāā calendar.controller.ts # API endpoints for calendar operations
ā āāā calendar.module.ts # Configures MicrosoftOutlookModule for calendar
ā āāā calendar.service.ts # Your business logic for calendars
ā āāā dto/
ā āāā create-event.dto.ts # Data validation for event creation
ā
āāā email/
ā āāā email.controller.ts # API endpoints for email operations
ā āāā email.module.ts # Configures MicrosoftOutlookModule for email
ā āāā email.service.ts # Your business logic for emails
ā āāā dto/
ā āāā send-email.dto.ts # Data validation for email sending
ā
āāā app.module.ts # Root module that imports feature modulesSee:
samples/nestjs-outlook-examplefor a full working example.
This modular architecture keeps concerns separated and makes your application easier to maintain and test.
Local Development
This section provides instructions for developers who want to run and test the library locally with the sample application.
Prerequisites
Install yalc globally:
npm install -g yalcNode.js and npm installed on your system
Setup Steps
Clone the repository:
git clone https://github.com/checkfirst-ltd/nestjs-outlook.git cd nestjs-outlookInstall dependencies in the main library:
npm installInstall dependencies in the sample application:
cd samples/nestjs-outlook-example npm installLink the library with the sample app using yalc:
In the root directory of the library:
npm run build yalc publishIn the sample app directory:
yalc add @checkfirst/nestjs-outlook
Running for Development
Start the library in development mode:
In the root directory:
npm run devThis will watch for changes in the library code and rebuild automatically.
Start the sample app in development mode:
In the sample app directory:
npm run start:dev:yalcThis will start the NestJS sample application with hot-reload enabled, using the locally linked library.
Using ngrok for Webhook Testing
To test Microsoft webhooks locally, you'll need to expose your local server to the internet using ngrok:
Install ngrok if you haven't already (https://ngrok.com/download)
Start ngrok to create a tunnel to your local server:
ngrok http 3000Update your application configuration with the ngrok URL:
- Copy the HTTPS URL provided by ngrok (e.g.,
https://1234-abcd-5678.ngrok.io) - Update the
backendBaseUrlin yourMicrosoftOutlookModule.forRoot()configuration
- Copy the HTTPS URL provided by ngrok (e.g.,
Register your webhook with the Microsoft Graph API using the ngrok URL
This allows Microsoft to send webhook notifications to your local development environment.
Configuring Microsoft Entra (Azure AD) for Local Development
For authentication to work properly with Microsoft, you need to configure your redirect URLs in Microsoft Entra (formerly Azure AD):
Log in to the Microsoft Entra admin center (or Azure Portal > Azure Active Directory)
Navigate to App Registrations and select your application
Go to Authentication > Add a platform > Web
Add redirect URIs for local development:
- For local development with ngrok:
https://[your-ngrok-url]/auth/microsoft/callback - For local development without ngrok:
http://localhost:[your-port]/auth/microsoft/callback
- For local development with ngrok:
Save your changes
Note: The sample app runs on the port specified in your configuration (typically 3000). If you're using a different port, make sure to:
- Start ngrok with your actual port:
ngrok http [your-port]- Update your redirect URLs in Microsoft Entra accordingly
- Update the port in your
.envfile or configuration
Support
Contributing
We welcome contributions! Please see our Contributing Guide for more details.
Code of Conduct
This project adheres to a Code of Conduct that all participants are expected to follow. Please read the Code of Conduct for details on our expectations.
About Checkfirst
Checkfirst is a trusted provider of developer tools and solutions. We build open-source libraries that help developers create better applications faster.