Search code examples
node.jsbotframeworkazure-bot-service

How to send adaptive card through outlook with botFramework NodeJs


I've built a bot that sends adaptive cards through teams. I'm able to successfuly interact with the card. However, I would like to extend the functionality and make it capable to send cards through outlook as well. I have followed this steps and added the channel to the azure bot services. However, I do not know how to start sending the card because its not explained in the documentation. Here is the snipped of how I send the card to teams.

// HTTP trigger to send notification. You need to add authentication / authorization for this API. Refer https://aka.ms/teamsfx-notification for more details.
server.post(
  "/api/notificationByTeams",
  restify.plugins.queryParser(),
  restify.plugins.bodyParser(), // Add more parsers if needed
  async (req, res) => {
    let continuationToken = undefined;
    do {
      const pagedData = await notificationApp.notification.getPagedInstallations();
      let adaptiveCardData = req.body;
      const { MerlinUser, MerlinPassword, Receivers, TemplateType } = adaptiveCardData;

      //Here we get all the users receiving the notification
      const usersReceivingCardInformation = await getNotificationMembersInfoByEmail(Receivers)
      const installations = pagedData.data;
      continuationToken = pagedData.continuationToken;

      //Here we encrypt the data of the admin user
      adaptiveCardData.MerlinUser = encryptData(MerlinUser);
      adaptiveCardData.MerlinPassword = encryptData(MerlinPassword);
      adaptiveCardData.Originator = process.env.Originator;
      console.info("Llegamos a setear el originator ", adaptiveCardData.Originator);
      adaptiveCardData.UserIds = usersReceivingCardInformation.map(x => x.id);

      for (const target of installations) {
       
        if (target.type === "Person" && usersReceivingCardInformation.some(x => x.id === target.conversationReference.user.id)) {
          let selectedTemplate = selectTemplate(TemplateType);
          await target.sendAdaptiveCard(
            AdaptiveCards.declare(selectedTemplate).render({
              ...adaptiveCardData
            })
          );
        }
      }
    } while (continuationToken);

    res.json({});
  }
);

I added the outlook channels to my bot service in azure.


Solution

  • I would like to extend the functionality and make it capable to send cards through outlook as well.

    By using Microsoft Graph API, we can be able to send an adaptive card via email through Outlook.

    Here, I have added outlook channel to my azure bot service.

    enter image description here

    • Create an app registration and Navigate to API permissions<Add a permission.

    enter image description here

    • Click on Microsoft graph and select application permissions then search for Mail.send to grant permission for your application.

    enter image description here

    • Create a JSON structure for the adaptive card as like below.
    {
        "type": "AdaptiveCard",
        "body": [
            {
                "type": "TextBlock",
                "text": "Hello!",
                "size": "large"
            },
            {
                "type": "TextBlock",
                "text": "This is an adaptive card sent via email."
            },
            {
                "type": "Image",
                "url": "https://adaptivecards.io/content/cats/1.png"
            }
        ],
        "actions": [
            {
                "type": "Action.OpenUrl",
                "title": "Learn More",
                "url": "https://adaptivecards.io"
            }
        ],
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "version": "1.2"
    }
    

    enter image description here

    • I have referred this MS doc to authenticate and send the email attaching an adaptive card using Microsoft Graph API.
    const msal = require('@azure/msal-node');
    const { Client } = require('@microsoft/microsoft-graph-client');
    require('isomorphic-fetch');
    
    // MSAL configuration
    const msalConfig = {
        auth: {
            clientId: 'YOUR_CLIENT_ID',
            authority: 'https://login.microsoftonline.com/YOUR_TENANT_ID',
            clientSecret: 'YOUR_CLIENT_SECRET'
        }
    };
    
    const cca = new msal.ConfidentialClientApplication(msalConfig);
    
    async function getToken() {
        const clientCredentialRequest = {
            scopes: ['https://graph.microsoft.com/.default'],
        };
        const response = await cca.acquireTokenByClientCredential(clientCredentialRequest);
        return response.accessToken;
    }
    
    async function sendAdaptiveCardEmail() {
        const accessToken = await getToken();
    
        const client = Client.init({
            authProvider: (done) => {
                done(null, accessToken);
            }
        });
    
        const adaptiveCardJson = require('./adaptiveCard.json');
    
        const email = {
            message: {
                subject: 'Adaptive Card Email',
                body: {
                    contentType: 'HTML',
                    content: 'Please see the adaptive card below.'
                },
                toRecipients: [
                    {
                        emailAddress: {
                            address: '[email protected]'
                        }
                    }
                ],
                attachments: [
                    {
                        '@odata.type': '#microsoft.graph.fileAttachment',
                        name: 'adaptiveCard.json',
                        contentType: 'application/json',
                        contentBytes: Buffer.from(JSON.stringify(adaptiveCardJson)).toString('base64')
                    }
                ]
            }
        };
    
        await client.api('/me/sendMail')
            .post({ message: email.message, saveToSentItems: 'true' });
    
        console.log('Email sent successfully.');
    }
    
    sendAdaptiveCardEmail().catch(console.error);
    

    enter image description here