Why Microsoft Graph Webhook notifications stops notifying me at a certain point?

Fabian Finalé Franqui 20 Reputation points
2023-07-07T22:32:13.88+00:00

I am building a daemon app for listening to incoming emails on a certain email account, and for some reason, Graph webhooks randomly stop notifying me about incoming emails. Furthermore, my subscription gets removed at some point without Microsoft notifying me, although I also subscribe to lifecycle events. I am not receiving missed notifications either.

Here's what my code looks like:

async subscribeToEmailNotifications() {
    try {
      const expirationDateTime = generateExpirationDate();
      const hasAttachmentsParam = 'hasAttachments:true';
      const senderDomainParam = 'from:@mydomain.com';
      const queryString = `?$search="${hasAttachmentsParam} AND ${senderDomainParam}"`;
      const emailSubscription = {
        changeType: 'created,updated',
        notificationUrl: `${SERVICE_BASE_URL}/email-notifications`,
        lifecycleNotificationUrl: `${SERVICE_BASE_URL}/lifecycle-notifications`,
        resource: `/users/${USER_PRINCIPAL_NAME}/messages${queryString}`,
        expirationDateTime,
        clientState: `${CLIENT_STATE}`,
      };

      const response = await this.client
        .api('/subscriptions')
        .post(emailSubscription);

    } catch (error) {
      // Error handling snippet
    }
  }

The generateExpirarionDate function provides a date 24 hours from now, all environment variables are being set/read properly, and the Microsoft Graph client is working as expected.

Also, here are the functions called by the email-notifications and lifecycle-notifications endpoints:

async handleNotificationMessages(req, res) {
    const { validationToken } = req.query;
    if (validationToken) return res.send(200, validationToken);

    try {
	  // Sending a 202 status since my function may take more than 3 sec to end processing
      res.send(202, 'Accepted');
      const notifications = req.body.value;

      for (const notification of notifications) {
        const message = await this.graphService.getMessage(
          notification.resourceData.id
        );
        if (message) await this.#processMessage(message);
      }
    } catch (error) {
 		// Error handling snippet
    }
  }

  async handleLifeCycleNotifications(req, res) {
    const { validationToken } = req.query;
    if (validationToken) return res.send(200, validationToken);

    try {
      const [value] = req.body.value;
      
      if (value.lifecycleEvent === 'reauthorizationRequired') {
        console.info('Microsoft Graph subscription is about to expire');
        // Extend subscription
      } else if (value.lifecycleEvent === 'missed') {
        console.info(`Missed notification received ${value}`);
        // Handle missed notification logic
      } else if (value.lifecycleEvent === 'subscriptionRemoved') {
        console.info(`Subscription removed notification received ${value}`);
        // Handle subscription removal logic
      }

      res.send(200, 'Success');
    } catch (error) {
      return res.send(500, error);
    }
  }

Am I missing something here?

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
12,113 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Ahmad Abdalghafoor 0 Reputation points
    2023-08-06T08:50:32.0366667+00:00

    @Fabian Finalé Franqui Do you have any solution for this, I'm facing the same problem and I appreciate any help


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.