Blog Post

Azure Communication Services Blog
13 MIN READ

Part 2 - Multichannel notification system using Azure Communication Services and Azure Functions

MilanKaur's avatar
MilanKaur
Icon for Microsoft rankMicrosoft
Oct 28, 2024

In the first part of this topic, we setup all the Azure resources like the Azure Communication Services for Email, SMS, WhatsApp for Business and developed the Azure Functions code for the email trigger. In this second part, we complete coding for the remaining Azure Functions triggers and then go ahead to deploy the multichannel notification system to Azure Functions, testing the Email, SMS, and WhatsApp triggers with OpenAI GPTs. Let’s get started!

Prerequisite

To follow this tutorial, ensure you have completed the first part of this topic.

Coding the SMSTrigger

Enhancing the SMSTrigger Azure Function from the default template involves a series of steps. These steps transform the basic Function into one that can send SMS messages using Azure Communication Services. Below is a guide to get you from the default HTTP triggered function to the finished SMSTrigger.

 

Step 1: Set Up the Function Template

Follow the instructions for setting up the function template from the Email section and name the trigger as ‘SMSTrigger’ or any other string you prefer.

 

Step 2: Add Azure Communication Services SMS Reference

Add a reference to using Azure.Communication.Sms then create a property in the SMS Trigger class to hold an instance of SmsClient and a property to hold the email sender address.

csharp

private readonly SmsClient _smsClient;
private string? sender = Environment.GetEnvironmentVariable("SENDER_PHONE_NUMBER");
 

Step 3: Read Configuration and Initialize SmsClient

In the constructor of the SMSTrigger class, read the Azure Communication Services connection string from the environment variables using the Environment.GetEnvironmentVariable() 
method and initialize the SmsClient instance.

Be sure to check if the connection string is null, and if so, throw an exception to indicate that the environment variable is missing:

csharp

string? connectionString = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_CONNECTION_STRING");
if (connectionString is null)
{
    throw new InvalidOperationException("COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.");
}
_smsClient = new SmsClient(connectionString);
 

Step 4: Define the Request Model

Create a request model class within the SMSTrigger class called SmsRequest. This model should contain properties for the message text and the phone number to which the message is sent.

csharp

public class SmsRequest
{
    public string Message { get; set; } = string.Empty;
    public string PhoneNumber { get; set; } = string.Empty;
}
 

Step 5: Parse the Request Body

Change the Run function to be async as we perform asynchronous operations. Use a StreamReader to read the request body as a string and deserialize it into an SmsRequest object using JsonSerializer.

csharp

public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req)
 

If the request body fails to deserialize into SmsRequest, return a BadRequestResult:

csharp

string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
SmsRequest? data = JsonSerializer.Deserialize<SmsRequest>(requestBody, new JsonSerializerOptions() {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            });
if (data is null)
{
    return new BadRequestResult();
}
 

Step 6: Define the Sender and Send an SMS

Retrieve the sender's phone number from the environment variables with Environment.GetEnvironmentVariable(). Then, attempt to send the SMS with a try-catch block, handling any RequestFailedException that may occur and logging the relevant information:

csharp

try
{
    _logger.LogInformation("Sending SMS...");
    SmsSendResult smsSendResult = await _smsClient.SendAsync(
        sender,
        data.PhoneNumber,
        data.Message
    );
    _logger.LogInformation($"SMS Sent. Successful = {smsSendResult.Successful}");
    _logger.LogInformation($"SMS operation id = {smsSendResult.MessageId}");
}
catch (RequestFailedException ex)
{
    _logger.LogInformation($"SMS send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}");
    // Return an appropriate error response if needed
}
 

Step 7: Return a Success Response

If sending the SMS is successful, return an OkObjectResult to the caller indicating that the SMS has been sent.

csharp

return new OkObjectResult("SMS sent successfully!");
 

Final Code

The final SMSTrigger Azure Function, with the steps implemented, should look as follows:

csharp

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging; 

using Azure;
using Azure.Communication.Messages;
using System.Text.Json;
using System.IO;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic; 

namespace ACSGPTFunctions
{
    public class WhatsAppTrigger
    {
        private readonly ILogger<WhatsAppTrigger> _logger;
        private readonly NotificationMessagesClient _messagesClient;
        private string? sender = Environment.GetEnvironmentVariable("WHATSAPP_NUMBER");

        public WhatsAppTrigger(ILogger<WhatsAppTrigger> logger)
        {
            _logger = logger;
            string? connectionString = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_CONNECTION_STRING");
            if (connectionString is null)
            {
                throw new InvalidOperationException("COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.");
            }
            _messagesClient = new NotificationMessagesClient(connectionString);
        }

        public class WhatsAppRequest
        {
            public string PhoneNumber { get; set; } = string.Empty;
            public string TemplateName { get; set; } = "appointment_reminder";
            public string TemplateLanguage { get; set; } = "en";
            public List<string> TemplateParameters { get; set; } = new List<string>();
        }

        [Function("WhatsAppTrigger")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
        {
            _logger.LogInformation("Processing request.");

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            }); 

            if (data is null)
            {
                return new BadRequestResult();
            } 

            var recipientList = new List<string> { data.PhoneNumber };
            var values = data.TemplateParameters
                .Select((parameter, index) => new MessageTemplateText($"value{index + 1}", parameter))
                .ToList();
            var bindings = new MessageTemplateWhatsAppBindings(
                body: values.Select(value => value.Name).ToList()
            );
            var template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);
            var sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template);

            try
            {
                Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions);
                _logger.LogInformation("WhatsApp message sent successfully!");
            }
            catch (RequestFailedException ex)
            {
                _logger.LogError($"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}");
                return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };
            }
            return new OkObjectResult("WhatsApp sent successfully!");
        }
    }
}
 

This completed SMSTrigger Azure Function can now facilitate SMS as part of your multichannel notification system.

Coding the WhatsAppTrigger

Creating a functional WhatsAppTrigger Azure Function involves iterating on the default HTTP-triggered function template provided by Azure Functions for C#. We modify this template to integrate Azure Communication Services for sending WhatsApp messages via template messages. Follow the steps below to transform this template into a complete WhatsAppTrigger function:

 

Step 1: Set Up the Function Template

Follow the instructions in the first step for setting up SMS trigger and name the function as WhatsAppTrigger. Set the authorization level to anonymous or function, depending on your security preference.

Step 2: Reference the Azure Communication Services Messages Package

Ensure the Azure.Communication.Messages NuGet package is included in your project to enable messaging features needed for WhatsApp. Install the package with the following command in Visual Studio Code’s terminal:

bash

dotnet add package Azure.Communication.Messages --prerelease
 

Add a reference to using Azure.Communication.Messages then create a property in the WhatsApp Trigger class to hold an instance of NotificationMessagesClient and a property to hold the WhatsApp identifier.

csharp

private readonly NotificationMessagesClient _messagesClient;
private string? sender = Environment.GetEnvironmentVariable("WHATSAPP_NUMBER");
 

Step 3: Read Configuration and Initialize NotificationMessagesClient

Update the WhatsAppTrigger class constructor to read the Azure Communication Services connection string from environment variables using Environment.GetEnvironmentVariable() and initialize NotificationMessagesClient with this connection string:

csharp

string? connectionString = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_CONNECTION_STRING");
if (connectionString is null)
{
    throw new InvalidOperationException("COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.");
}
_messagesClient = new NotificationMessagesClient(connectionString);
 

Step 4: Define the Request Model

Create a request model class named WhatsAppRequest within the WhatsAppTrigger class, containing properties for the destination phone number, template name, language, and template parameters:

csharp

public class WhatsAppRequest 

{
    public string PhoneNumber { get; set; } = string.Empty;
    public string TemplateName { get; set; } = "appointment_reminder";
    public string TemplateLanguage { get; set; } = "en";
    public List<string> TemplateParameters { get; set; } = new List<string>();
}
 

Step 5: Parse the Request Body

Convert the Run function to be async to enable asynchronous work. Use StreamReader to read the request body and deserialize it to a WhatsAppRequest instance using 
System.Text.Json.JsonSerializer with JsonNamingPolicy.CamelCase.

csharp

public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req)
 

Handle potential deserialization failure by returning BadRequestResult:

csharp

string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); 
WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});

if (data is null)
{
    return new BadRequestResult();
}
 

Step 6: Prepare Template Message and Send WhatsApp Message

Modify the try-catch block to construct a SendMessageOptions object using MessageTemplateWhatsAppBindingsand MessageTemplate, and then make a call to _messagesClient.SendMessageAsync(sendTemplateMessageOptions):

csharp

try
{
    _logger.LogInformation("Sending WhatsApp message...");

    List<string> recipientList = new List<string> { data.PhoneNumber };
    List<MessageTemplateText> values = data.TemplateParameters
        .Select((parameter, index) => new MessageTemplateText($"value{index + 1}", parameter))
        .ToList();
    MessageTemplateWhatsAppBindings bindings = new MessageTemplateWhatsAppBindings(
        body: values.Select(value => value.Name).ToList()
    );
    MessageTemplate template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);
    SendMessageOptions sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template);
    Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions); 

    _logger.LogInformation("WhatsApp message sent successfully!");
}
catch (RequestFailedException ex)
{
    _logger.LogError($"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}");
    return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };
}
 

Step 7: Return Success Response

After sending the WhatsApp message successfully, return an OkObjectResult stating "WhatsApp sent successfully!".

csharp

return new OkObjectResult("WhatsApp sent successfully!");
 

Final Code

Following the described steps, the final WhatsAppTrigger Azure Function should look like this:

csharp

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

using Azure;
using Azure.Communication.Messages;
using System.Text.Json;
using System.IO;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic; 

namespace ACSGPTFunctions
{
    public class WhatsAppTrigger
    {
        private readonly ILogger<WhatsAppTrigger> _logger;
        private readonly NotificationMessagesClient _messagesClient;
        private string? sender = Environment.GetEnvironmentVariable("WHATSAPP_NUMBER"); 

        public WhatsAppTrigger(ILogger<WhatsAppTrigger> logger)
        {
            _logger = logger;
            string? connectionString = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_CONNECTION_STRING");
            if (connectionString is null)
            {
                throw new InvalidOperationException("COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.");
            }
            _messagesClient = new NotificationMessagesClient(connectionString);
        }

        public class WhatsAppRequest
        {
            public string PhoneNumber { get; set; } = string.Empty;
            public string TemplateName { get; set; } = "appointment_reminder";
            public string TemplateLanguage { get; set; } = "en";
            public List<string> TemplateParameters { get; set; } = new List<string>();
        }

        [Function("WhatsAppTrigger")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
        {
            _logger.LogInformation("Processing request.");

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            });

            if (data is null)
            {
                return new BadRequestResult();
            }

            var recipientList = new List<string> { data.PhoneNumber };
            var values = data.TemplateParameters
                .Select((parameter, index) => new MessageTemplateText($"value{index + 1}", parameter))
                .ToList();
            var bindings = new MessageTemplateWhatsAppBindings(
                body: values.Select(value => value.Name).ToList()
            );
            var template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);
            var sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template); 

            try
            {
                Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions);
                _logger.LogInformation("WhatsApp message sent successfully!");
            }
            catch (RequestFailedException ex)
            {
                _logger.LogError($"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}");
                return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };
            }
            return new OkObjectResult("WhatsApp sent successfully!");
        }
    }
}
 

The WhatsAppTrigger Azure Function is now ready to send WhatsApp template messages. Be sure to test it extensively and remember to handle any issues related to input validation and communicate with the Azure Communication Services API correctly.

Deployment and Testing

After developing the multichannel notification system using Azure Functions, the next step is to deploy and test the functions. This section guides you through deploying your Azure Function to the cloud and testing the Email, SMS, and WhatsApp triggers.

 

Deploying the Azure Function

Deployment of your Azure Function can be done right from Visual Studio Code with the Azure Functions extension.

  1. Publish the Function App: In Visual Studio Code, sign in to Azure if you haven't already. In the Azure Functions extension tab, find the Deploy to Function App... button and select it.



  2. Choose Your Function App: You can either create a new Function App or deploy it to an existing one. If it's the first time you are deploying, choose Create New Function App in Azure....
  3. Set the Configuration: Provide a unique name for your Function App, select a runtime stack (.NET Core in this case), choose the appropriate region, and confirm your selections.
  4. Wait for Deployment: The deployment process takes a few minutes. Monitor the output window for completion status and any potential errors.

 

Set Up Application Settings

After deployment, you need to configure the application settings (environment variables) in Azure.

  1. Open the Function App: Navigate to the Azure Portal and find your Function App under All Resources or by searching the name you provided.
  2. Access Application Settings: In the Function App's menu, go to Configuration under the Settings section.
  3. Add the Settings: Click New application setting and add the key-value pairs for the environment variables specified in your local.settings.json
    COMMUNICATION_SERVICES_CONNECTION_STRINGSENDER_EMAIL_ADDRESSSENDER_PHONE_NUMBERWHATSAPP_NUMBER, and so on.

json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "COMMUNICATION_SERVICES_CONNECTION_STRING": "<<connection string>>",
    "SENDER_PHONE_NUMBER": "<<phone number>>",
    "SENDER_EMAIL_ADDRESS": "<<email address>>",
    "WHATSAPP_NUMBER":"<<WhatsApp id>>"
  }
}
 
  1. Save and Restart: After adding the required settings, make sure to save the configurations and restart the Function App to ensure the new settings take effect.

Alternatively, when the Function has finished deploying, you can click Upload settings to upload your settings from local.settings.json. Don't forget to restart the Function App after uploading the settings.

 

Testing the Function

With the deployment complete and the environment configured, it's time to verify that your function works as intended through each communication channel.

 

Testing Email Notifications

To test the EmailTrigger function:

  1. Send an HTTP POST Request: Use a tool like Postman to send a POST request to the Function App's URL suffixed with /api/EmailTrigger. The body should contain JSON with keys for subjecthtmlContent, and recipient.
  2. Verify Email Receipt: Check the recipient's email inbox for the message. Ensure that the subject and content match what you sent through the POST request.

 

Testing SMS Notifications

To test the SMSTrigger function:

  1. Send an HTTP POST Request: Using Postman, send a POST request to the Function App's URL with /api/SMSTrigger at the end. The body of your request should contain JSON with message and phoneNumberkeys.
  2. Check for SMS: Ensure that the specified phone number receives the SMS and the message content matches the request.

 

Testing WhatsApp Notifications

To test the WhatsAppTrigger function:

  1. Send an HTTP POST Request: Use Postman again to POST to the Function URL, this time ending with /api/WhatsAppTrigger. Include a JSON body with keys for phoneNumbertemplateNametemplateLanguage, and templateParameters.
  2. Confirm WhatsApp Message: Verify that the WhatsApp message reaches the intended recipient with correct template filling.

Integrate with OpenAI GPTs

In OpenAI GPTs editor, click 'new GPT' and 'configure'. Name it "Email Sender" and set the description and instructions as mentioned.

Compose wonderful emails and send them

Help author short and delightful emails. Ask for details on the nature of the email content and include creative ideas for topics. Compose the email with placeholders for the sender's name and receiver's name. You do not need a full name. Share a draft of the email and ask for the sender's name, and the receiver's name and email address. Provide a draft of the final email and confirm the user is happy with it. When the user provides a recipient's email address ask if it is correct before sending. Do not send the email until you provide a final draft and you have a confirmed recipient email address.
 

 

Add Actions and JSON Schema

Click 'Create new action' in your GPT configuration. Enter the following JSON:

json

{
  "openapi": "3.1.0",
  "info": {
    "title": "Send Message API",
    "description": "API for sending a message to a specified email address.",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://<<function-app-url>>.azurewebsites.net"
    }
  ],
   "paths": {
    "/api/emailtrigger": {
      "post": {
        "description": "Send a message to a given email address",
        "operationId": "SendMessage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipient": {
                    "type": "string",
                    "format": "email",
                    "description": "Email address of the recipient"
                  },
                  "subject": {
                    "type": "string",
                    "description": "The message subject"
                  },
                  "htmlContent": {
                    "type": "string",
                    "description": "The body content of the email encoded as escaped HTML"
                  }
                },
                "required": [
                  "to",
                  "message"
                ]
              }
            }
          }
        },
        "deprecated": false
      }
    }
  },
  "components": {
    "schemas": {}
  }
}
 

Leave Authentication to none, and Privacy Policy blank.

Test Your GPT

Finally, try out your GPT in the preview pane to see it in action!

By following these steps, you can easily integrate Azure Communication Services with OpenAI GPTs to send emails effortlessly.

 

Conclusion and Further Reading

We have successfully walked through the journey of building a serverless multichannel notification system using Azure Functions and Azure Communication Services. This system can send timely and personalized notifications across multiple channels, such as Email, SMS, and WhatsApp. In addition, we have explored how to enhance our system with sophisticated content generation capabilities using OpenAI GPTs.

 

The modular nature of the Azure Functions framework allows your application to scale and adapt easily to changing requirements and traffic demands. Meanwhile, Azure Communication Services enrich the user experience by meeting customers on their preferred platforms, contributing to a seamless and cohesive communication strategy.

 

As developers, there's always room to expand our knowledge and add robust features to our applications. Here are some suggestions for further exploration and resources that can assist you in taking your applications to the next level:

  1. Azure Communication Services AI samples: One stop shop for GitHub samples for AI-powered communication solutions.
  2. Azure Functions Best Practices: Learn about best practices for designing and implementing Azure Functions by visiting Azure Functions best practices.
  3. Azure Communication Services Documentation: Explore the full capabilities of Azure Communication Services including chat, phone numbers, video calling, and more on the Azure Communication Services documentation.
  4. Security and Compliance in Azure: Understand the best practices for security and compliance in Azure applications, particularly relevant for handling sensitive user communication data. Check the Microsoft Azure Trust Center.
  5. OpenAI GPT Documentation: For more insight into using and customizing OpenAI GPTs, refer to the OpenAI API documentation.
  6. Azure AI Services: Azure offers a range of AI services beyond just communication. Explore Azure AI services for more advanced scenarios such as speech recognition, machine translation, and anomaly detection at Azure AI services documentation.
  7. Handling Large-scale Data: To handle a large amount of data and improve the performance of communication systems, consider learning about Azure's data-handling services like Azure Cosmos DB, Azure SQL Database, and Azure Cache for Redis. Start with the Azure Data storage documentation.
  8. Monitoring and Diagnostics: Improve the reliability of your applications by implementing robust monitoring and diagnostics tools. Azure offers several tools such as Azure Monitor and Application Insights. Dive into Application Insights for Azure Functions.
  9. Serverless Workflow Automation with Azure Logic Apps: Enhance your serverless applications using Azure Logic Apps to automate and simplify workflows. Learn more about Azure Logic Apps at What is Azure Logic Apps?.

 

 Happy coding!

Updated Nov 06, 2024
Version 6.0
No CommentsBe the first to comment
"}},"componentScriptGroups({\"componentId\":\"custom.widget.MicrosoftFooter\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/ranks/UserRankLabel\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"components/tags/TagView/TagViewChip\"]})":[{"__ref":"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserRegistrationDate\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserRegistrationDate-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeAvatar-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeDescription\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeDescription-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1745505307000"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Deleted","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"MMM dd yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US","es-ES"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1747128071991":{"__typename":"CachedAsset","id":"pages-1747128071991","value":[{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"UserBlogPermissions.Page","type":"COMMUNITY","urlPath":"/c/user-blog-permissions/page","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"AllEvents","type":"CUSTOM","urlPath":"/Events","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"CommunityHub.Page","type":"CUSTOM","urlPath":"/Directory","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"AllBlogs.Page","type":"CUSTOM","urlPath":"/blogs","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747128071991,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/cmstNC05WEo0blc\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/cmstNC05WEo0blc","height":512,"width":512,"mimeType":"image/png"},"Rank:rank:4":{"__typename":"Rank","id":"rank:4","position":6,"name":"Microsoft","color":"333333","icon":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/cmstNC05WEo0blc\"}"},"rankStyle":"OUTLINE"},"User:user:1712503":{"__typename":"User","id":"user:1712503","uid":1712503,"login":"MilanKaur","deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS0xNzEyNTAzLTUzMjEyMWkwQjFGQUQyRDZBMzcyQzA2"},"rank":{"__ref":"Rank:rank:4"},"email":"","messagesCount":17,"biography":null,"topicsCount":16,"kudosReceivedCount":11,"kudosGivenCount":19,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":null,"registrationTime":"2023-01-31T12:46:30.445-08:00","confirmEmailStatus":null},"followersCount":null,"solutionsCount":0},"Category:category:Azure":{"__typename":"Category","id":"category:Azure","entityType":"CATEGORY","displayId":"Azure","nodeType":"category","depth":3,"title":"Azure","shortTitle":"Azure","parent":{"__ref":"Category:category:products-services"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","entityType":"CATEGORY","displayId":"top","nodeType":"category","depth":0,"title":"Top","shortTitle":"Top"},"Category:category:communities":{"__typename":"Category","id":"category:communities","entityType":"CATEGORY","displayId":"communities","nodeType":"category","depth":1,"parent":{"__ref":"Category:category:top"},"title":"Communities","shortTitle":"Communities"},"Category:category:products-services":{"__typename":"Category","id":"category:products-services","entityType":"CATEGORY","displayId":"products-services","nodeType":"category","depth":2,"parent":{"__ref":"Category:category:communities"},"title":"Products","shortTitle":"Products"},"Blog:board:AzureCommunicationServicesBlog":{"__typename":"Blog","id":"board:AzureCommunicationServicesBlog","entityType":"BLOG","displayId":"AzureCommunicationServicesBlog","nodeType":"board","depth":4,"conversationStyle":"BLOG","repliesProperties":{"__typename":"RepliesProperties","sortOrder":"REVERSE_PUBLISH_TIME","repliesFormat":"threaded"},"tagProperties":{"__typename":"TagNodeProperties","tagsEnabled":{"__typename":"PolicyResult","failureReason":null}},"requireTags":true,"tagType":"PRESET_ONLY","description":"","title":"Azure Communication Services Blog","shortTitle":"Azure Communication Services Blog","parent":{"__ref":"Category:category:Azure"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:gxcuf89792"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:communities"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:products-services"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:Azure"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"theme":{"__ref":"Theme:customTheme1"},"boardPolicies":{"__typename":"BoardPolicies","canViewSpamDashBoard":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.access_spam_quarantine.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.access_spam_quarantine.allowed.accessDenied","args":[]}},"canArchiveMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.content_archivals.enable_content_archival_settings.accessDenied","key":"error.lithium.policies.content_archivals.enable_content_archival_settings.accessDenied","args":[]}},"canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}}}},"BlogTopicMessage:message:4280563":{"__typename":"BlogTopicMessage","uid":4280563,"subject":"Part 2 - Multichannel notification system using Azure Communication Services and Azure Functions","id":"message:4280563","revisionNum":8,"repliesCount":0,"author":{"__ref":"User:user:1712503"},"depth":0,"hasGivenKudo":false,"board":{"__ref":"Blog:board:AzureCommunicationServicesBlog"},"conversation":{"__ref":"Conversation:conversation:4280563"},"messagePolicies":{"__typename":"MessagePolicies","canPublishArticleOnEdit":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","args":[]}},"canModerateSpamMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","args":[]}}},"contentWorkflow":{"__typename":"ContentWorkflow","state":"PUBLISH","scheduledPublishTime":null,"scheduledTimezone":null,"userContext":{"__typename":"MessageWorkflowContext","canSubmitForReview":null,"canEdit":false,"canRecall":null,"canSubmitForPublication":null,"canReturnToAuthor":null,"canPublish":null,"canReturnToReview":null,"canSchedule":false},"shortScheduledTimezone":null},"readOnly":false,"editFrozen":false,"moderationData":{"__ref":"ModerationData:moderation_data:4280563"},"teaser":"\n

In this second part of this tutorial, we complete coding the remaining Azure Functions triggers and then go ahead to deploy the multichannel notification system to Azure Functions, testing the Email, SMS, and WhatsApp triggers with OpenAI GPTs. Let’s get started!

","body":"

In the first part of this topic, we setup all the Azure resources like the Azure Communication Services for Email, SMS, WhatsApp for Business and developed the Azure Functions code for the email trigger. In this second part, we complete coding for the remaining Azure Functions triggers and then go ahead to deploy the multichannel notification system to Azure Functions, testing the Email, SMS, and WhatsApp triggers with OpenAI GPTs. Let’s get started!

\n

Prerequisite

\n

To follow this tutorial, ensure you have completed the first part of this topic.

\n

Coding the SMSTrigger

\n

Enhancing the SMSTrigger Azure Function from the default template involves a series of steps. These steps transform the basic Function into one that can send SMS messages using Azure Communication Services. Below is a guide to get you from the default HTTP triggered function to the finished SMSTrigger.

\n
\n
\n

 

\n
\n
\n

Step 1: Set Up the Function Template

\n

Follow the instructions for setting up the function template from the Email section and name the trigger as ‘SMSTrigger’ or any other string you prefer.

\n

 

\n

Step 2: Add Azure Communication Services SMS Reference

\n

Add a reference to using Azure.Communication.Sms then create a property in the SMS Trigger class to hold an instance of SmsClient and a property to hold the email sender address.

\n

csharp

\n
\n
private readonly SmsClient _smsClient;\nprivate string? sender = Environment.GetEnvironmentVariable(\"SENDER_PHONE_NUMBER\");\n
\n
 
\n
\n
\n

Step 3: Read Configuration and Initialize SmsClient

\n

In the constructor of the SMSTrigger class, read the Azure Communication Services connection string from the environment variables using the Environment.GetEnvironmentVariable() 
method and initialize the SmsClient instance.

\n

Be sure to check if the connection string is null, and if so, throw an exception to indicate that the environment variable is missing:

\n

csharp

\n
\n
string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\nif (connectionString is null)\n{\n    throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n}\n_smsClient = new SmsClient(connectionString);\n
\n
 
\n
\n
\n

Step 4: Define the Request Model

\n

Create a request model class within the SMSTrigger class called SmsRequest. This model should contain properties for the message text and the phone number to which the message is sent.

\n

csharp

\n
\n
public class SmsRequest\n{\n    public string Message { get; set; } = string.Empty;\n    public string PhoneNumber { get; set; } = string.Empty;\n}\n
\n
 
\n
\n
\n

Step 5: Parse the Request Body

\n

Change the Run function to be async as we perform asynchronous operations. Use a StreamReader to read the request body as a string and deserialize it into an SmsRequest object using JsonSerializer.

\n

csharp

\n
\n
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, \"post\")] HttpRequest req)\n
\n
 
\n
\n
\n

If the request body fails to deserialize into SmsRequest, return a BadRequestResult:

\n

csharp

\n
\n
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\nSmsRequest? data = JsonSerializer.Deserialize<SmsRequest>(requestBody, new JsonSerializerOptions() {\n                PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n            });\nif (data is null)\n{\n    return new BadRequestResult();\n}\n
\n
 
\n
\n
\n

Step 6: Define the Sender and Send an SMS

\n

Retrieve the sender's phone number from the environment variables with Environment.GetEnvironmentVariable(). Then, attempt to send the SMS with a try-catch block, handling any RequestFailedException that may occur and logging the relevant information:

\n

csharp

\n
\n
try\n{\n    _logger.LogInformation(\"Sending SMS...\");\n    SmsSendResult smsSendResult = await _smsClient.SendAsync(\n        sender,\n        data.PhoneNumber,\n        data.Message\n    );\n    _logger.LogInformation($\"SMS Sent. Successful = {smsSendResult.Successful}\");\n    _logger.LogInformation($\"SMS operation id = {smsSendResult.MessageId}\");\n}\ncatch (RequestFailedException ex)\n{\n    _logger.LogInformation($\"SMS send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n    // Return an appropriate error response if needed\n}\n
\n
 
\n
\n
\n

Step 7: Return a Success Response

\n

If sending the SMS is successful, return an OkObjectResult to the caller indicating that the SMS has been sent.

\n

csharp

\n
\n
return new OkObjectResult(\"SMS sent successfully!\");\n
\n
 
\n
\n
\n

Final Code

\n

The final SMSTrigger Azure Function, with the steps implemented, should look as follows:

\n

csharp

\n
\n
using Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Azure.Functions.Worker;\nusing Microsoft.Extensions.Logging; \n\nusing Azure;\nusing Azure.Communication.Messages;\nusing System.Text.Json;\nusing System.IO;\nusing System.Threading.Tasks;\nusing System.Linq;\nusing System.Collections.Generic; \n\nnamespace ACSGPTFunctions\n{\n    public class WhatsAppTrigger\n    {\n        private readonly ILogger<WhatsAppTrigger> _logger;\n        private readonly NotificationMessagesClient _messagesClient;\n        private string? sender = Environment.GetEnvironmentVariable(\"WHATSAPP_NUMBER\");\n\n        public WhatsAppTrigger(ILogger<WhatsAppTrigger> logger)\n        {\n            _logger = logger;\n            string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\n            if (connectionString is null)\n            {\n                throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n            }\n            _messagesClient = new NotificationMessagesClient(connectionString);\n        }\n\n        public class WhatsAppRequest\n        {\n            public string PhoneNumber { get; set; } = string.Empty;\n            public string TemplateName { get; set; } = \"appointment_reminder\";\n            public string TemplateLanguage { get; set; } = \"en\";\n            public List<string> TemplateParameters { get; set; } = new List<string>();\n        }\n\n        [Function(\"WhatsAppTrigger\")]\n        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\")] HttpRequest req)\n        {\n            _logger.LogInformation(\"Processing request.\");\n\n            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\n            WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {\n                PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n            }); \n\n            if (data is null)\n            {\n                return new BadRequestResult();\n            } \n\n            var recipientList = new List<string> { data.PhoneNumber };\n            var values = data.TemplateParameters\n                .Select((parameter, index) => new MessageTemplateText($\"value{index + 1}\", parameter))\n                .ToList();\n            var bindings = new MessageTemplateWhatsAppBindings(\n                body: values.Select(value => value.Name).ToList()\n            );\n            var template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);\n            var sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template);\n\n            try\n            {\n                Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions);\n                _logger.LogInformation(\"WhatsApp message sent successfully!\");\n            }\n            catch (RequestFailedException ex)\n            {\n                _logger.LogError($\"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n                return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };\n            }\n            return new OkObjectResult(\"WhatsApp sent successfully!\");\n        }\n    }\n}\n
\n
 
\n
\n
\n

This completed SMSTrigger Azure Function can now facilitate SMS as part of your multichannel notification system.

\n

Coding the WhatsAppTrigger

\n

Creating a functional WhatsAppTrigger Azure Function involves iterating on the default HTTP-triggered function template provided by Azure Functions for C#. We modify this template to integrate Azure Communication Services for sending WhatsApp messages via template messages. Follow the steps below to transform this template into a complete WhatsAppTrigger function:

\n

 

\n

Step 1: Set Up the Function Template

\n

Follow the instructions in the first step for setting up SMS trigger and name the function as WhatsAppTrigger. Set the authorization level to anonymous or function, depending on your security preference.

\n

Step 2: Reference the Azure Communication Services Messages Package

\n

Ensure the Azure.Communication.Messages NuGet package is included in your project to enable messaging features needed for WhatsApp. Install the package with the following command in Visual Studio Code’s terminal:

\n

bash

\n
\n
dotnet add package Azure.Communication.Messages --prerelease\n
\n
 
\n
\n
\n

Add a reference to using Azure.Communication.Messages then create a property in the WhatsApp Trigger class to hold an instance of NotificationMessagesClient and a property to hold the WhatsApp identifier.

\n

csharp

\n
\n
private readonly NotificationMessagesClient _messagesClient;\nprivate string? sender = Environment.GetEnvironmentVariable(\"WHATSAPP_NUMBER\");\n
\n
 
\n
\n
\n

Step 3: Read Configuration and Initialize NotificationMessagesClient

\n

Update the WhatsAppTrigger class constructor to read the Azure Communication Services connection string from environment variables using Environment.GetEnvironmentVariable() and initialize NotificationMessagesClient with this connection string:

\n

csharp

\n
\n
string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\nif (connectionString is null)\n{\n    throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n}\n_messagesClient = new NotificationMessagesClient(connectionString);\n
\n
 
\n
\n
\n

Step 4: Define the Request Model

\n

Create a request model class named WhatsAppRequest within the WhatsAppTrigger class, containing properties for the destination phone number, template name, language, and template parameters:

\n

csharp

\n
\n
public class WhatsAppRequest \n\n{\n    public string PhoneNumber { get; set; } = string.Empty;\n    public string TemplateName { get; set; } = \"appointment_reminder\";\n    public string TemplateLanguage { get; set; } = \"en\";\n    public List<string> TemplateParameters { get; set; } = new List<string>();\n}\n
\n
 
\n
\n
\n

Step 5: Parse the Request Body

\n

Convert the Run function to be async to enable asynchronous work. Use StreamReader to read the request body and deserialize it to a WhatsAppRequest instance using 
System.Text.Json.JsonSerializer with JsonNamingPolicy.CamelCase.

\n

csharp

\n
\n
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, \"post\")] HttpRequest req)\n
\n
 
\n
\n
\n

Handle potential deserialization failure by returning BadRequestResult:

\n

csharp

\n
\n
string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); \nWhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {\n    PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n});\n\nif (data is null)\n{\n    return new BadRequestResult();\n}\n
\n
 
\n
\n
\n

Step 6: Prepare Template Message and Send WhatsApp Message

\n

Modify the try-catch block to construct a SendMessageOptions object using MessageTemplateWhatsAppBindingsand MessageTemplate, and then make a call to _messagesClient.SendMessageAsync(sendTemplateMessageOptions):

\n

csharp

\n
\n
try\n{\n    _logger.LogInformation(\"Sending WhatsApp message...\");\n\n    List<string> recipientList = new List<string> { data.PhoneNumber };\n    List<MessageTemplateText> values = data.TemplateParameters\n        .Select((parameter, index) => new MessageTemplateText($\"value{index + 1}\", parameter))\n        .ToList();\n    MessageTemplateWhatsAppBindings bindings = new MessageTemplateWhatsAppBindings(\n        body: values.Select(value => value.Name).ToList()\n    );\n    MessageTemplate template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);\n    SendMessageOptions sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template);\n    Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions); \n\n    _logger.LogInformation(\"WhatsApp message sent successfully!\");\n}\ncatch (RequestFailedException ex)\n{\n    _logger.LogError($\"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n    return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };\n}\n
\n
 
\n
\n
\n

Step 7: Return Success Response

\n

After sending the WhatsApp message successfully, return an OkObjectResult stating \"WhatsApp sent successfully!\".

\n

csharp

\n
\n
return new OkObjectResult(\"WhatsApp sent successfully!\");\n
\n
 
\n
\n
\n

Final Code

\n

Following the described steps, the final WhatsAppTrigger Azure Function should look like this:

\n

csharp

\n
\n
using Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Azure.Functions.Worker;\nusing Microsoft.Extensions.Logging;\n\nusing Azure;\nusing Azure.Communication.Messages;\nusing System.Text.Json;\nusing System.IO;\nusing System.Threading.Tasks;\nusing System.Linq;\nusing System.Collections.Generic; \n\nnamespace ACSGPTFunctions\n{\n    public class WhatsAppTrigger\n    {\n        private readonly ILogger<WhatsAppTrigger> _logger;\n        private readonly NotificationMessagesClient _messagesClient;\n        private string? sender = Environment.GetEnvironmentVariable(\"WHATSAPP_NUMBER\"); \n\n        public WhatsAppTrigger(ILogger<WhatsAppTrigger> logger)\n        {\n            _logger = logger;\n            string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\n            if (connectionString is null)\n            {\n                throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n            }\n            _messagesClient = new NotificationMessagesClient(connectionString);\n        }\n\n        public class WhatsAppRequest\n        {\n            public string PhoneNumber { get; set; } = string.Empty;\n            public string TemplateName { get; set; } = \"appointment_reminder\";\n            public string TemplateLanguage { get; set; } = \"en\";\n            public List<string> TemplateParameters { get; set; } = new List<string>();\n        }\n\n        [Function(\"WhatsAppTrigger\")]\n        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\")] HttpRequest req)\n        {\n            _logger.LogInformation(\"Processing request.\");\n\n            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\n            WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {\n                PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n            });\n\n            if (data is null)\n            {\n                return new BadRequestResult();\n            }\n\n            var recipientList = new List<string> { data.PhoneNumber };\n            var values = data.TemplateParameters\n                .Select((parameter, index) => new MessageTemplateText($\"value{index + 1}\", parameter))\n                .ToList();\n            var bindings = new MessageTemplateWhatsAppBindings(\n                body: values.Select(value => value.Name).ToList()\n            );\n            var template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);\n            var sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template); \n\n            try\n            {\n                Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions);\n                _logger.LogInformation(\"WhatsApp message sent successfully!\");\n            }\n            catch (RequestFailedException ex)\n            {\n                _logger.LogError($\"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n                return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };\n            }\n            return new OkObjectResult(\"WhatsApp sent successfully!\");\n        }\n    }\n}\n
\n
 
\n
\n
\n

The WhatsAppTrigger Azure Function is now ready to send WhatsApp template messages. Be sure to test it extensively and remember to handle any issues related to input validation and communicate with the Azure Communication Services API correctly.

\n

Deployment and Testing

\n

After developing the multichannel notification system using Azure Functions, the next step is to deploy and test the functions. This section guides you through deploying your Azure Function to the cloud and testing the Email, SMS, and WhatsApp triggers.

\n

 

\n

Deploying the Azure Function

\n

Deployment of your Azure Function can be done right from Visual Studio Code with the Azure Functions extension.

\n
    \n
  1. Publish the Function App: In Visual Studio Code, sign in to Azure if you haven't already. In the Azure Functions extension tab, find the Deploy to Function App... button and select it.



  2. \n
  3. Choose Your Function App: You can either create a new Function App or deploy it to an existing one. If it's the first time you are deploying, choose Create New Function App in Azure....
  4. \n
  5. Set the Configuration: Provide a unique name for your Function App, select a runtime stack (.NET Core in this case), choose the appropriate region, and confirm your selections.
  6. \n
  7. Wait for Deployment: The deployment process takes a few minutes. Monitor the output window for completion status and any potential errors.
  8. \n
\n

 

\n

Set Up Application Settings

\n

After deployment, you need to configure the application settings (environment variables) in Azure.

\n
    \n
  1. Open the Function App: Navigate to the Azure Portal and find your Function App under All Resources or by searching the name you provided.
  2. \n
  3. Access Application Settings: In the Function App's menu, go to Configuration under the Settings section.
  4. \n
  5. Add the Settings: Click New application setting and add the key-value pairs for the environment variables specified in your local.settings.json
    COMMUNICATION_SERVICES_CONNECTION_STRINGSENDER_EMAIL_ADDRESSSENDER_PHONE_NUMBERWHATSAPP_NUMBER, and so on.

  6. \n
\n

json

\n
\n
{\n  \"IsEncrypted\": false,\n  \"Values\": {\n    \"AzureWebJobsStorage\": \"\",\n    \"FUNCTIONS_WORKER_RUNTIME\": \"dotnet-isolated\",\n    \"COMMUNICATION_SERVICES_CONNECTION_STRING\": \"<<connection string>>\",\n    \"SENDER_PHONE_NUMBER\": \"<<phone number>>\",\n    \"SENDER_EMAIL_ADDRESS\": \"<<email address>>\",\n    \"WHATSAPP_NUMBER\":\"<<WhatsApp id>>\"\n  }\n}\n
\n
 
\n
\n
\n
    \n
  1. Save and Restart: After adding the required settings, make sure to save the configurations and restart the Function App to ensure the new settings take effect.
  2. \n
\n

Alternatively, when the Function has finished deploying, you can click Upload settings to upload your settings from local.settings.json. Don't forget to restart the Function App after uploading the settings.

\n\n

 

\n

Testing the Function

\n

With the deployment complete and the environment configured, it's time to verify that your function works as intended through each communication channel.

\n

 

\n

Testing Email Notifications

\n

To test the EmailTrigger function:

\n
    \n
  1. Send an HTTP POST Request: Use a tool like Postman to send a POST request to the Function App's URL suffixed with /api/EmailTrigger. The body should contain JSON with keys for subjecthtmlContent, and recipient.
  2. \n
  3. Verify Email Receipt: Check the recipient's email inbox for the message. Ensure that the subject and content match what you sent through the POST request.
  4. \n
\n

 

\n

Testing SMS Notifications

\n

To test the SMSTrigger function:

\n
    \n
  1. Send an HTTP POST Request: Using Postman, send a POST request to the Function App's URL with /api/SMSTrigger at the end. The body of your request should contain JSON with message and phoneNumberkeys.
  2. \n
  3. Check for SMS: Ensure that the specified phone number receives the SMS and the message content matches the request.
  4. \n
\n

 

\n

Testing WhatsApp Notifications

\n

To test the WhatsAppTrigger function:

\n
    \n
  1. Send an HTTP POST Request: Use Postman again to POST to the Function URL, this time ending with /api/WhatsAppTrigger. Include a JSON body with keys for phoneNumbertemplateNametemplateLanguage, and templateParameters.
  2. \n
  3. Confirm WhatsApp Message: Verify that the WhatsApp message reaches the intended recipient with correct template filling.

  4. \n
\n

Integrate with OpenAI GPTs

\n

In OpenAI GPTs editor, click 'new GPT' and 'configure'. Name it \"Email Sender\" and set the description and instructions as mentioned.

\n
\n
Compose wonderful emails and send them\n\nHelp author short and delightful emails. Ask for details on the nature of the email content and include creative ideas for topics. Compose the email with placeholders for the sender's name and receiver's name. You do not need a full name. Share a draft of the email and ask for the sender's name, and the receiver's name and email address. Provide a draft of the final email and confirm the user is happy with it. When the user provides a recipient's email address ask if it is correct before sending. Do not send the email until you provide a final draft and you have a confirmed recipient email address.\n
\n
 
\n
\n
\n\n

 

\n

Add Actions and JSON Schema

\n

Click 'Create new action' in your GPT configuration. Enter the following JSON:

\n

json

\n
\n
{\n  \"openapi\": \"3.1.0\",\n  \"info\": {\n    \"title\": \"Send Message API\",\n    \"description\": \"API for sending a message to a specified email address.\",\n    \"version\": \"v1.0.0\"\n  },\n  \"servers\": [\n    {\n      \"url\": \"https://<<function-app-url>>.azurewebsites.net\"\n    }\n  ],\n   \"paths\": {\n    \"/api/emailtrigger\": {\n      \"post\": {\n        \"description\": \"Send a message to a given email address\",\n        \"operationId\": \"SendMessage\",\n        \"requestBody\": {\n          \"required\": true,\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"type\": \"object\",\n                \"properties\": {\n                  \"recipient\": {\n                    \"type\": \"string\",\n                    \"format\": \"email\",\n                    \"description\": \"Email address of the recipient\"\n                  },\n                  \"subject\": {\n                    \"type\": \"string\",\n                    \"description\": \"The message subject\"\n                  },\n                  \"htmlContent\": {\n                    \"type\": \"string\",\n                    \"description\": \"The body content of the email encoded as escaped HTML\"\n                  }\n                },\n                \"required\": [\n                  \"to\",\n                  \"message\"\n                ]\n              }\n            }\n          }\n        },\n        \"deprecated\": false\n      }\n    }\n  },\n  \"components\": {\n    \"schemas\": {}\n  }\n}\n
\n
 
\n
\n
\n

Leave Authentication to none, and Privacy Policy blank.

\n

Test Your GPT

\n

Finally, try out your GPT in the preview pane to see it in action!

\n

By following these steps, you can easily integrate Azure Communication Services with OpenAI GPTs to send emails effortlessly.

\n\n

 

\n

Conclusion and Further Reading

\n

We have successfully walked through the journey of building a serverless multichannel notification system using Azure Functions and Azure Communication Services. This system can send timely and personalized notifications across multiple channels, such as Email, SMS, and WhatsApp. In addition, we have explored how to enhance our system with sophisticated content generation capabilities using OpenAI GPTs.

\n

 

\n

The modular nature of the Azure Functions framework allows your application to scale and adapt easily to changing requirements and traffic demands. Meanwhile, Azure Communication Services enrich the user experience by meeting customers on their preferred platforms, contributing to a seamless and cohesive communication strategy.

\n

 

\n

As developers, there's always room to expand our knowledge and add robust features to our applications. Here are some suggestions for further exploration and resources that can assist you in taking your applications to the next level:

\n
    \n
  1. Azure Communication Services AI samples: One stop shop for GitHub samples for AI-powered communication solutions.
  2. \n
  3. Azure Functions Best Practices: Learn about best practices for designing and implementing Azure Functions by visiting Azure Functions best practices.
  4. \n
  5. Azure Communication Services Documentation: Explore the full capabilities of Azure Communication Services including chat, phone numbers, video calling, and more on the Azure Communication Services documentation.
  6. \n
  7. Security and Compliance in Azure: Understand the best practices for security and compliance in Azure applications, particularly relevant for handling sensitive user communication data. Check the Microsoft Azure Trust Center.
  8. \n
  9. OpenAI GPT Documentation: For more insight into using and customizing OpenAI GPTs, refer to the OpenAI API documentation.
  10. \n
  11. Azure AI Services: Azure offers a range of AI services beyond just communication. Explore Azure AI services for more advanced scenarios such as speech recognition, machine translation, and anomaly detection at Azure AI services documentation.
  12. \n
  13. Handling Large-scale Data: To handle a large amount of data and improve the performance of communication systems, consider learning about Azure's data-handling services like Azure Cosmos DB, Azure SQL Database, and Azure Cache for Redis. Start with the Azure Data storage documentation.
  14. \n
  15. Monitoring and Diagnostics: Improve the reliability of your applications by implementing robust monitoring and diagnostics tools. Azure offers several tools such as Azure Monitor and Application Insights. Dive into Application Insights for Azure Functions.
  16. \n
  17. Serverless Workflow Automation with Azure Logic Apps: Enhance your serverless applications using Azure Logic Apps to automate and simplify workflows. Learn more about Azure Logic Apps at What is Azure Logic Apps?.
  18. \n
\n

 

\n

 Happy coding!

","body@stringLength":"51324","rawBody":"

In the first part of this topic, we setup all the Azure resources like the Azure Communication Services for Email, SMS, WhatsApp for Business and developed the Azure Functions code for the email trigger. In this second part, we complete coding for the remaining Azure Functions triggers and then go ahead to deploy the multichannel notification system to Azure Functions, testing the Email, SMS, and WhatsApp triggers with OpenAI GPTs. Let’s get started!

\n

Prerequisite

\n

To follow this tutorial, ensure you have completed the first part of this topic.

\n

Coding the SMSTrigger

\n

Enhancing the SMSTrigger Azure Function from the default template involves a series of steps. These steps transform the basic Function into one that can send SMS messages using Azure Communication Services. Below is a guide to get you from the default HTTP triggered function to the finished SMSTrigger.

\n
\n
\n

 

\n
\n
\n

Step 1: Set Up the Function Template

\n

Follow the instructions for setting up the function template from the Email section and name the trigger as ‘SMSTrigger’ or any other string you prefer.

\n

 

\n

Step 2: Add Azure Communication Services SMS Reference

\n

Add a reference to using Azure.Communication.Sms then create a property in the SMS Trigger class to hold an instance of SmsClient and a property to hold the email sender address.

\n

csharp

\n
\n
private readonly SmsClient _smsClient;\nprivate string? sender = Environment.GetEnvironmentVariable(\"SENDER_PHONE_NUMBER\");\n\n
 
\n
\n
\n

Step 3: Read Configuration and Initialize SmsClient

\n

In the constructor of the SMSTrigger class, read the Azure Communication Services connection string from the environment variables using the Environment.GetEnvironmentVariable() 
method and initialize the SmsClient instance.

\n

Be sure to check if the connection string is null, and if so, throw an exception to indicate that the environment variable is missing:

\n

csharp

\n
\n
string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\nif (connectionString is null)\n{\n throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n}\n_smsClient = new SmsClient(connectionString);\n\n
 
\n
\n
\n

Step 4: Define the Request Model

\n

Create a request model class within the SMSTrigger class called SmsRequest. This model should contain properties for the message text and the phone number to which the message is sent.

\n

csharp

\n
\n
public class SmsRequest\n{\n public string Message { get; set; } = string.Empty;\n public string PhoneNumber { get; set; } = string.Empty;\n}\n\n
 
\n
\n
\n

Step 5: Parse the Request Body

\n

Change the Run function to be async as we perform asynchronous operations. Use a StreamReader to read the request body as a string and deserialize it into an SmsRequest object using JsonSerializer.

\n

csharp

\n
\n
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, \"post\")] HttpRequest req)\n\n
 
\n
\n
\n

If the request body fails to deserialize into SmsRequest, return a BadRequestResult:

\n

csharp

\n
\n
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\nSmsRequest? data = JsonSerializer.Deserialize<SmsRequest>(requestBody, new JsonSerializerOptions() {\n PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n });\nif (data is null)\n{\n return new BadRequestResult();\n}\n\n
 
\n
\n
\n

Step 6: Define the Sender and Send an SMS

\n

Retrieve the sender's phone number from the environment variables with Environment.GetEnvironmentVariable(). Then, attempt to send the SMS with a try-catch block, handling any RequestFailedException that may occur and logging the relevant information:

\n

csharp

\n
\n
try\n{\n _logger.LogInformation(\"Sending SMS...\");\n SmsSendResult smsSendResult = await _smsClient.SendAsync(\n sender,\n data.PhoneNumber,\n data.Message\n );\n _logger.LogInformation($\"SMS Sent. Successful = {smsSendResult.Successful}\");\n _logger.LogInformation($\"SMS operation id = {smsSendResult.MessageId}\");\n}\ncatch (RequestFailedException ex)\n{\n _logger.LogInformation($\"SMS send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n // Return an appropriate error response if needed\n}\n\n
 
\n
\n
\n

Step 7: Return a Success Response

\n

If sending the SMS is successful, return an OkObjectResult to the caller indicating that the SMS has been sent.

\n

csharp

\n
\n
return new OkObjectResult(\"SMS sent successfully!\");\n\n
 
\n
\n
\n

Final Code

\n

The final SMSTrigger Azure Function, with the steps implemented, should look as follows:

\n

csharp

\n
\n
using Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Azure.Functions.Worker;\nusing Microsoft.Extensions.Logging; \n\nusing Azure;\nusing Azure.Communication.Messages;\nusing System.Text.Json;\nusing System.IO;\nusing System.Threading.Tasks;\nusing System.Linq;\nusing System.Collections.Generic; \n\nnamespace ACSGPTFunctions\n{\n public class WhatsAppTrigger\n {\n private readonly ILogger<WhatsAppTrigger> _logger;\n private readonly NotificationMessagesClient _messagesClient;\n private string? sender = Environment.GetEnvironmentVariable(\"WHATSAPP_NUMBER\");\n\n public WhatsAppTrigger(ILogger<WhatsAppTrigger> logger)\n {\n _logger = logger;\n string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\n if (connectionString is null)\n {\n throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n }\n _messagesClient = new NotificationMessagesClient(connectionString);\n }\n\n public class WhatsAppRequest\n {\n public string PhoneNumber { get; set; } = string.Empty;\n public string TemplateName { get; set; } = \"appointment_reminder\";\n public string TemplateLanguage { get; set; } = \"en\";\n public List<string> TemplateParameters { get; set; } = new List<string>();\n }\n\n [Function(\"WhatsAppTrigger\")]\n public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\")] HttpRequest req)\n {\n _logger.LogInformation(\"Processing request.\");\n\n string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\n WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {\n PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n }); \n\n if (data is null)\n {\n return new BadRequestResult();\n } \n\n var recipientList = new List<string> { data.PhoneNumber };\n var values = data.TemplateParameters\n .Select((parameter, index) => new MessageTemplateText($\"value{index + 1}\", parameter))\n .ToList();\n var bindings = new MessageTemplateWhatsAppBindings(\n body: values.Select(value => value.Name).ToList()\n );\n var template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);\n var sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template);\n\n try\n {\n Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions);\n _logger.LogInformation(\"WhatsApp message sent successfully!\");\n }\n catch (RequestFailedException ex)\n {\n _logger.LogError($\"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };\n }\n return new OkObjectResult(\"WhatsApp sent successfully!\");\n }\n }\n}\n\n
 
\n
\n
\n

This completed SMSTrigger Azure Function can now facilitate SMS as part of your multichannel notification system.

\n

Coding the WhatsAppTrigger

\n

Creating a functional WhatsAppTrigger Azure Function involves iterating on the default HTTP-triggered function template provided by Azure Functions for C#. We modify this template to integrate Azure Communication Services for sending WhatsApp messages via template messages. Follow the steps below to transform this template into a complete WhatsAppTrigger function:

\n

 

\n

Step 1: Set Up the Function Template

\n

Follow the instructions in the first step for setting up SMS trigger and name the function as WhatsAppTrigger. Set the authorization level to anonymous or function, depending on your security preference.

\n

Step 2: Reference the Azure Communication Services Messages Package

\n

Ensure the Azure.Communication.Messages NuGet package is included in your project to enable messaging features needed for WhatsApp. Install the package with the following command in Visual Studio Code’s terminal:

\n

bash

\n
\n
dotnet add package Azure.Communication.Messages --prerelease\n\n
 
\n
\n
\n

Add a reference to using Azure.Communication.Messages then create a property in the WhatsApp Trigger class to hold an instance of NotificationMessagesClient and a property to hold the WhatsApp identifier.

\n

csharp

\n
\n
private readonly NotificationMessagesClient _messagesClient;\nprivate string? sender = Environment.GetEnvironmentVariable(\"WHATSAPP_NUMBER\");\n\n
 
\n
\n
\n

Step 3: Read Configuration and Initialize NotificationMessagesClient

\n

Update the WhatsAppTrigger class constructor to read the Azure Communication Services connection string from environment variables using Environment.GetEnvironmentVariable() and initialize NotificationMessagesClient with this connection string:

\n

csharp

\n
\n
string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\nif (connectionString is null)\n{\n throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n}\n_messagesClient = new NotificationMessagesClient(connectionString);\n\n
 
\n
\n
\n

Step 4: Define the Request Model

\n

Create a request model class named WhatsAppRequest within the WhatsAppTrigger class, containing properties for the destination phone number, template name, language, and template parameters:

\n

csharp

\n
\n
public class WhatsAppRequest \n\n{\n public string PhoneNumber { get; set; } = string.Empty;\n public string TemplateName { get; set; } = \"appointment_reminder\";\n public string TemplateLanguage { get; set; } = \"en\";\n public List<string> TemplateParameters { get; set; } = new List<string>();\n}\n\n
 
\n
\n
\n

Step 5: Parse the Request Body

\n

Convert the Run function to be async to enable asynchronous work. Use StreamReader to read the request body and deserialize it to a WhatsAppRequest instance using 
System.Text.Json.JsonSerializer with JsonNamingPolicy.CamelCase.

\n

csharp

\n
\n
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, \"post\")] HttpRequest req)\n\n
 
\n
\n
\n

Handle potential deserialization failure by returning BadRequestResult:

\n

csharp

\n
\n
string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); \nWhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {\n PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n});\n\nif (data is null)\n{\n return new BadRequestResult();\n}\n\n
 
\n
\n
\n

Step 6: Prepare Template Message and Send WhatsApp Message

\n

Modify the try-catch block to construct a SendMessageOptions object using MessageTemplateWhatsAppBindingsand MessageTemplate, and then make a call to _messagesClient.SendMessageAsync(sendTemplateMessageOptions):

\n

csharp

\n
\n
try\n{\n _logger.LogInformation(\"Sending WhatsApp message...\");\n\n List<string> recipientList = new List<string> { data.PhoneNumber };\n List<MessageTemplateText> values = data.TemplateParameters\n .Select((parameter, index) => new MessageTemplateText($\"value{index + 1}\", parameter))\n .ToList();\n MessageTemplateWhatsAppBindings bindings = new MessageTemplateWhatsAppBindings(\n body: values.Select(value => value.Name).ToList()\n );\n MessageTemplate template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);\n SendMessageOptions sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template);\n Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions); \n\n _logger.LogInformation(\"WhatsApp message sent successfully!\");\n}\ncatch (RequestFailedException ex)\n{\n _logger.LogError($\"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };\n}\n\n
 
\n
\n
\n

Step 7: Return Success Response

\n

After sending the WhatsApp message successfully, return an OkObjectResult stating \"WhatsApp sent successfully!\".

\n

csharp

\n
\n
return new OkObjectResult(\"WhatsApp sent successfully!\");\n\n
 
\n
\n
\n

Final Code

\n

Following the described steps, the final WhatsAppTrigger Azure Function should look like this:

\n

csharp

\n
\n
using Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Azure.Functions.Worker;\nusing Microsoft.Extensions.Logging;\n\nusing Azure;\nusing Azure.Communication.Messages;\nusing System.Text.Json;\nusing System.IO;\nusing System.Threading.Tasks;\nusing System.Linq;\nusing System.Collections.Generic; \n\nnamespace ACSGPTFunctions\n{\n public class WhatsAppTrigger\n {\n private readonly ILogger<WhatsAppTrigger> _logger;\n private readonly NotificationMessagesClient _messagesClient;\n private string? sender = Environment.GetEnvironmentVariable(\"WHATSAPP_NUMBER\"); \n\n public WhatsAppTrigger(ILogger<WhatsAppTrigger> logger)\n {\n _logger = logger;\n string? connectionString = Environment.GetEnvironmentVariable(\"COMMUNICATION_SERVICES_CONNECTION_STRING\");\n if (connectionString is null)\n {\n throw new InvalidOperationException(\"COMMUNICATION_SERVICES_CONNECTION_STRING environment variable is not set.\");\n }\n _messagesClient = new NotificationMessagesClient(connectionString);\n }\n\n public class WhatsAppRequest\n {\n public string PhoneNumber { get; set; } = string.Empty;\n public string TemplateName { get; set; } = \"appointment_reminder\";\n public string TemplateLanguage { get; set; } = \"en\";\n public List<string> TemplateParameters { get; set; } = new List<string>();\n }\n\n [Function(\"WhatsAppTrigger\")]\n public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\")] HttpRequest req)\n {\n _logger.LogInformation(\"Processing request.\");\n\n string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\n WhatsAppRequest? data = JsonSerializer.Deserialize<WhatsAppRequest>(requestBody, new JsonSerializerOptions() {\n PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n });\n\n if (data is null)\n {\n return new BadRequestResult();\n }\n\n var recipientList = new List<string> { data.PhoneNumber };\n var values = data.TemplateParameters\n .Select((parameter, index) => new MessageTemplateText($\"value{index + 1}\", parameter))\n .ToList();\n var bindings = new MessageTemplateWhatsAppBindings(\n body: values.Select(value => value.Name).ToList()\n );\n var template = new MessageTemplate(data.TemplateName, data.TemplateLanguage, values, bindings);\n var sendTemplateMessageOptions = new SendMessageOptions(sender, recipientList, template); \n\n try\n {\n Response<SendMessageResult> templateResponse = await _messagesClient.SendMessageAsync(sendTemplateMessageOptions);\n _logger.LogInformation(\"WhatsApp message sent successfully!\");\n }\n catch (RequestFailedException ex)\n {\n _logger.LogError($\"WhatsApp send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}\");\n return new ObjectResult(new { error = ex.Message }) { StatusCode = 500 };\n }\n return new OkObjectResult(\"WhatsApp sent successfully!\");\n }\n }\n}\n\n
 
\n
\n
\n

The WhatsAppTrigger Azure Function is now ready to send WhatsApp template messages. Be sure to test it extensively and remember to handle any issues related to input validation and communicate with the Azure Communication Services API correctly.

\n

Deployment and Testing

\n

After developing the multichannel notification system using Azure Functions, the next step is to deploy and test the functions. This section guides you through deploying your Azure Function to the cloud and testing the Email, SMS, and WhatsApp triggers.

\n

 

\n

Deploying the Azure Function

\n

Deployment of your Azure Function can be done right from Visual Studio Code with the Azure Functions extension.

\n
    \n
  1. Publish the Function App: In Visual Studio Code, sign in to Azure if you haven't already. In the Azure Functions extension tab, find the Deploy to Function App... button and select it.



  2. \n
  3. Choose Your Function App: You can either create a new Function App or deploy it to an existing one. If it's the first time you are deploying, choose Create New Function App in Azure....
  4. \n
  5. Set the Configuration: Provide a unique name for your Function App, select a runtime stack (.NET Core in this case), choose the appropriate region, and confirm your selections.
  6. \n
  7. Wait for Deployment: The deployment process takes a few minutes. Monitor the output window for completion status and any potential errors.
  8. \n
\n

 

\n

Set Up Application Settings

\n

After deployment, you need to configure the application settings (environment variables) in Azure.

\n
    \n
  1. Open the Function App: Navigate to the Azure Portal and find your Function App under All Resources or by searching the name you provided.
  2. \n
  3. Access Application Settings: In the Function App's menu, go to Configuration under the Settings section.
  4. \n
  5. Add the Settings: Click New application setting and add the key-value pairs for the environment variables specified in your local.settings.json
    COMMUNICATION_SERVICES_CONNECTION_STRINGSENDER_EMAIL_ADDRESSSENDER_PHONE_NUMBERWHATSAPP_NUMBER, and so on.

  6. \n
\n

json

\n
\n
{\n \"IsEncrypted\": false,\n \"Values\": {\n \"AzureWebJobsStorage\": \"\",\n \"FUNCTIONS_WORKER_RUNTIME\": \"dotnet-isolated\",\n \"COMMUNICATION_SERVICES_CONNECTION_STRING\": \"<<connection string>>\",\n \"SENDER_PHONE_NUMBER\": \"<<phone number>>\",\n \"SENDER_EMAIL_ADDRESS\": \"<<email address>>\",\n \"WHATSAPP_NUMBER\":\"<<WhatsApp id>>\"\n }\n}\n\n
 
\n
\n
\n
    \n
  1. Save and Restart: After adding the required settings, make sure to save the configurations and restart the Function App to ensure the new settings take effect.
  2. \n
\n

Alternatively, when the Function has finished deploying, you can click Upload settings to upload your settings from local.settings.json. Don't forget to restart the Function App after uploading the settings.

\n\n

 

\n

Testing the Function

\n

With the deployment complete and the environment configured, it's time to verify that your function works as intended through each communication channel.

\n

 

\n

Testing Email Notifications

\n

To test the EmailTrigger function:

\n
    \n
  1. Send an HTTP POST Request: Use a tool like Postman to send a POST request to the Function App's URL suffixed with /api/EmailTrigger. The body should contain JSON with keys for subjecthtmlContent, and recipient.
  2. \n
  3. Verify Email Receipt: Check the recipient's email inbox for the message. Ensure that the subject and content match what you sent through the POST request.
  4. \n
\n

 

\n

Testing SMS Notifications

\n

To test the SMSTrigger function:

\n
    \n
  1. Send an HTTP POST Request: Using Postman, send a POST request to the Function App's URL with /api/SMSTrigger at the end. The body of your request should contain JSON with message and phoneNumberkeys.
  2. \n
  3. Check for SMS: Ensure that the specified phone number receives the SMS and the message content matches the request.
  4. \n
\n

 

\n

Testing WhatsApp Notifications

\n

To test the WhatsAppTrigger function:

\n
    \n
  1. Send an HTTP POST Request: Use Postman again to POST to the Function URL, this time ending with /api/WhatsAppTrigger. Include a JSON body with keys for phoneNumbertemplateNametemplateLanguage, and templateParameters.
  2. \n
  3. Confirm WhatsApp Message: Verify that the WhatsApp message reaches the intended recipient with correct template filling.

  4. \n
\n

Integrate with OpenAI GPTs

\n

In OpenAI GPTs editor, click 'new GPT' and 'configure'. Name it \"Email Sender\" and set the description and instructions as mentioned.

\n
\n
Compose wonderful emails and send them\n\nHelp author short and delightful emails. Ask for details on the nature of the email content and include creative ideas for topics. Compose the email with placeholders for the sender's name and receiver's name. You do not need a full name. Share a draft of the email and ask for the sender's name, and the receiver's name and email address. Provide a draft of the final email and confirm the user is happy with it. When the user provides a recipient's email address ask if it is correct before sending. Do not send the email until you provide a final draft and you have a confirmed recipient email address.\n\n
 
\n
\n
\n\n

 

\n

Add Actions and JSON Schema

\n

Click 'Create new action' in your GPT configuration. Enter the following JSON:

\n

json

\n
\n
{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"title\": \"Send Message API\",\n \"description\": \"API for sending a message to a specified email address.\",\n \"version\": \"v1.0.0\"\n },\n \"servers\": [\n {\n \"url\": \"https://<<function-app-url>>.azurewebsites.net\"\n }\n ],\n \"paths\": {\n \"/api/emailtrigger\": {\n \"post\": {\n \"description\": \"Send a message to a given email address\",\n \"operationId\": \"SendMessage\",\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"recipient\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"description\": \"Email address of the recipient\"\n },\n \"subject\": {\n \"type\": \"string\",\n \"description\": \"The message subject\"\n },\n \"htmlContent\": {\n \"type\": \"string\",\n \"description\": \"The body content of the email encoded as escaped HTML\"\n }\n },\n \"required\": [\n \"to\",\n \"message\"\n ]\n }\n }\n }\n },\n \"deprecated\": false\n }\n }\n },\n \"components\": {\n \"schemas\": {}\n }\n}\n\n
 
\n
\n
\n

Leave Authentication to none, and Privacy Policy blank.

\n

Test Your GPT

\n

Finally, try out your GPT in the preview pane to see it in action!

\n

By following these steps, you can easily integrate Azure Communication Services with OpenAI GPTs to send emails effortlessly.

\n\n

 

\n

Conclusion and Further Reading

\n

We have successfully walked through the journey of building a serverless multichannel notification system using Azure Functions and Azure Communication Services. This system can send timely and personalized notifications across multiple channels, such as Email, SMS, and WhatsApp. In addition, we have explored how to enhance our system with sophisticated content generation capabilities using OpenAI GPTs.

\n

 

\n

The modular nature of the Azure Functions framework allows your application to scale and adapt easily to changing requirements and traffic demands. Meanwhile, Azure Communication Services enrich the user experience by meeting customers on their preferred platforms, contributing to a seamless and cohesive communication strategy.

\n

 

\n

As developers, there's always room to expand our knowledge and add robust features to our applications. Here are some suggestions for further exploration and resources that can assist you in taking your applications to the next level:

\n
    \n
  1. Azure Communication Services AI samples: One stop shop for GitHub samples for AI-powered communication solutions.
  2. \n
  3. Azure Functions Best Practices: Learn about best practices for designing and implementing Azure Functions by visiting Azure Functions best practices.
  4. \n
  5. Azure Communication Services Documentation: Explore the full capabilities of Azure Communication Services including chat, phone numbers, video calling, and more on the Azure Communication Services documentation.
  6. \n
  7. Security and Compliance in Azure: Understand the best practices for security and compliance in Azure applications, particularly relevant for handling sensitive user communication data. Check the Microsoft Azure Trust Center.
  8. \n
  9. OpenAI GPT Documentation: For more insight into using and customizing OpenAI GPTs, refer to the OpenAI API documentation.
  10. \n
  11. Azure AI Services: Azure offers a range of AI services beyond just communication. Explore Azure AI services for more advanced scenarios such as speech recognition, machine translation, and anomaly detection at Azure AI services documentation.
  12. \n
  13. Handling Large-scale Data: To handle a large amount of data and improve the performance of communication systems, consider learning about Azure's data-handling services like Azure Cosmos DB, Azure SQL Database, and Azure Cache for Redis. Start with the Azure Data storage documentation.
  14. \n
  15. Monitoring and Diagnostics: Improve the reliability of your applications by implementing robust monitoring and diagnostics tools. Azure offers several tools such as Azure Monitor and Application Insights. Dive into Application Insights for Azure Functions.
  16. \n
  17. Serverless Workflow Automation with Azure Logic Apps: Enhance your serverless applications using Azure Logic Apps to automate and simplify workflows. Learn more about Azure Logic Apps at What is Azure Logic Apps?.
  18. \n
\n

 

\n

 Happy coding!

","kudosSumWeight":0,"postTime":"2024-10-28T13:20:58.649-07:00","images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMzI2NGk1QzVGQzlBRjlGNzg0NzIx?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwMmk2RjE2QzQ0NTIxRTEzMzJF?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwNGk0QjY3OERCRTY2RUQwRUND?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwM2kyRjhFMTc1NTUyMkRFRjg4?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwNWlGMDc4MTc3NDYxQjQzQkVB?revision=8\"}"}}],"totalCount":5,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"attachments":{"__typename":"AttachmentConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[]},"tags":{"__typename":"TagConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDE","node":{"__typename":"Tag","id":"tag:ai","text":"ai","time":"2018-01-27T01:25:04.985-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDI","node":{"__typename":"Tag","id":"tag:email","text":"email","time":"2016-06-23T13:36:20.889-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDM","node":{"__typename":"Tag","id":"tag:sms","text":"sms","time":"2018-10-16T16:43:31.596-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDQ","node":{"__typename":"Tag","id":"tag:whatsapp","text":"whatsapp","time":"2019-07-25T01:32:24.970-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}}]},"timeToRead":13,"rawTeaser":"\n

In this second part of this tutorial, we complete coding the remaining Azure Functions triggers and then go ahead to deploy the multichannel notification system to Azure Functions, testing the Email, SMS, and WhatsApp triggers with OpenAI GPTs. Let’s get started!

","introduction":"","coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""},"currentRevision":{"__ref":"Revision:revision:4280563_8"},"latestVersion":{"__typename":"FriendlyVersion","major":"6","minor":"0"},"metrics":{"__typename":"MessageMetrics","views":1597},"visibilityScope":"PUBLIC","canonicalUrl":null,"seoTitle":null,"seoDescription":null,"placeholder":false,"originalMessageForPlaceholder":null,"contributors":{"__typename":"UserConnection","edges":[]},"nonCoAuthorContributors":{"__typename":"UserConnection","edges":[]},"coAuthors":{"__typename":"UserConnection","edges":[]},"blogMessagePolicies":{"__typename":"BlogMessagePolicies","canDoAuthoringActionsOnBlog":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.blog.action_can_do_authoring_action.accessDenied","key":"error.lithium.policies.blog.action_can_do_authoring_action.accessDenied","args":[]}}},"archivalData":null,"replies":{"__typename":"MessageConnection","edges":[],"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"customFields":[],"revisions({\"constraints\":{\"isPublished\":{\"eq\":true}},\"first\":1})":{"__typename":"RevisionConnection","totalCount":8}},"Conversation:conversation:4280563":{"__typename":"Conversation","id":"conversation:4280563","solved":false,"topic":{"__ref":"BlogTopicMessage:message:4280563"},"lastPostingActivityTime":"2024-11-06T10:30:39.850-08:00","lastPostTime":"2024-10-28T13:20:58.649-07:00","unreadReplyCount":0,"isSubscribed":false},"ModerationData:moderation_data:4280563":{"__typename":"ModerationData","id":"moderation_data:4280563","status":"APPROVED","rejectReason":null,"isReportedAbuse":false,"rejectUser":null,"rejectTime":null,"rejectActorType":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMzI2NGk1QzVGQzlBRjlGNzg0NzIx?revision=8\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMzI2NGk1QzVGQzlBRjlGNzg0NzIx?revision=8","title":"Screenshot 2024-10-28 124528.png","associationType":"TEASER","width":1201,"height":730,"altText":"Screenshot 2024-10-28 124528.png"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwMmk2RjE2QzQ0NTIxRTEzMzJF?revision=8\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwMmk2RjE2QzQ0NTIxRTEzMzJF?revision=8","title":"MilanKaur_0-1730079357485.png","associationType":"BODY","width":581,"height":334,"altText":"MilanKaur_0-1730079357485.png"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwNGk0QjY3OERCRTY2RUQwRUND?revision=8\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwNGk0QjY3OERCRTY2RUQwRUND?revision=8","title":"MilanKaur_1-1730079357502.png","associationType":"BODY","width":560,"height":49,"altText":"MilanKaur_1-1730079357502.png"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwM2kyRjhFMTc1NTUyMkRFRjg4?revision=8\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwM2kyRjhFMTc1NTUyMkRFRjg4?revision=8","title":"MilanKaur_2-1730079357465.png","associationType":"BODY","width":560,"height":358,"altText":"MilanKaur_2-1730079357465.png"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwNWlGMDc4MTc3NDYxQjQzQkVB?revision=8\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MjgwNTYzLTYzMjkwNWlGMDc4MTc3NDYxQjQzQkVB?revision=8","title":"MilanKaur_3-1730079357507.png","associationType":"BODY","width":560,"height":350,"altText":"MilanKaur_3-1730079357507.png"},"Revision:revision:4280563_8":{"__typename":"Revision","id":"revision:4280563_8","lastEditTime":"2024-11-06T10:30:39.850-08:00"},"CachedAsset:theme:customTheme1-1747128071333":{"__typename":"CachedAsset","id":"theme:customTheme1-1747128071333","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["default"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"favicon-1730836283320.png","imageLastModified":"1730836286415","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"favicon-1730836271365.png","imageLastModified":"1730836274203","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1300px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_BROWSER","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"3px","borderRadius":"3px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"16px","paddingXHero":"60px","fontStyle":"NORMAL","fontWeight":"700","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-200)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-200)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"LIGHT","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.16)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.12)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-link-color)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","forumColor":"#4099E2","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#148563","blogColor":"#1CBAA0","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#4C6B90","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#FF8000","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#D13A1F","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#333333","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#717171","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0069D4","secondary":"#333333","bodyText":"#1E1E1E","bodyBg":"#FFFFFF","info":"#409AE2","success":"#41C5AE","warning":"#FCC844","danger":"#BC341B","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#D3F5A4","#243A5E"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Segoe UI","fontStyle":"NORMAL","fontWeight":"400","h1FontSize":"34px","h2FontSize":"32px","h3FontSize":"28px","h4FontSize":"24px","h5FontSize":"20px","h6FontSize":"16px","lineHeight":"1.3","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":"","imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"40px","defaultMessageHeaderMarginBottom":"20px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"40px","specialMessageHeaderMarginBottom":"20px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Segoe UI","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.5","fontSizeBase":"16px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"14px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[{"source":"SERVER","name":"Segoe UI","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"},{"style":"NORMAL","weight":"300","__typename":"FontStyleData"},{"style":"NORMAL","weight":"600","__typename":"FontStyleData"},{"style":"NORMAL","weight":"700","__typename":"FontStyleData"},{"style":"ITALIC","weight":"400","__typename":"FontStyleData"}],"assetNames":["SegoeUI-normal-400.woff2","SegoeUI-normal-300.woff2","SegoeUI-normal-600.woff2","SegoeUI-normal-700.woff2","SegoeUI-italic-400.woff2"],"__typename":"CustomFont"},{"source":"SERVER","name":"MWF Fluent Icons","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"}],"assetNames":["MWFFluentIcons-normal-400.woff2"],"__typename":"CustomFont"}],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1745505307000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:quilt:o365.prod:pages/blogs/BlogMessagePage:board:AzureCommunicationServicesBlog-1747128069349":{"__typename":"CachedAsset","id":"quilt:o365.prod:pages/blogs/BlogMessagePage:board:AzureCommunicationServicesBlog-1747128069349","value":{"id":"BlogMessagePage","container":{"id":"Common","headerProps":{"backgroundImageProps":null,"backgroundColor":null,"addComponents":null,"removeComponents":["community.widget.bannerWidget"],"componentOrder":null,"__typename":"QuiltContainerSectionProps"},"headerComponentProps":{"community.widget.breadcrumbWidget":{"disableLastCrumbForDesktop":false}},"footerProps":null,"footerComponentProps":null,"items":[{"id":"blog-article","layout":"ONE_COLUMN","bgColor":null,"showTitle":null,"showDescription":null,"textPosition":null,"textColor":null,"sectionEditLevel":"LOCKED","bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"OneColumnQuiltSection","columnMap":{"main":[{"id":"blogs.widget.blogArticleWidget","className":"lia-blog-container","props":null,"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"}},{"id":"section-1729184836777","layout":"MAIN_SIDE","bgColor":"transparent","showTitle":false,"showDescription":false,"textPosition":"CENTER","textColor":"var(--lia-bs-body-color)","sectionEditLevel":null,"bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"MainSideQuiltSection","columnMap":{"main":[],"side":[],"__typename":"MainSideSectionColumns"}}],"__typename":"QuiltContainer"},"__typename":"Quilt","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1745505307000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/blogs/BlogMessagePage-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-pages/blogs/BlogMessagePage-1745505307000","value":{"title":"{contextMessageSubject} | {communityTitle}","errorMissing":"This blog post cannot be found","name":"Blog Message Page","section.blog-article.title":"Blog Post","archivedMessageTitle":"This Content Has Been Archived","section.section-1729184836777.title":"","section.section-1729184836777.description":"","section.CncIde.title":"Blog Post","section.tifEmD.description":"","section.tifEmD.title":""},"localOverride":false},"CachedAsset:quiltWrapper:o365.prod:Common:1747128008679":{"__typename":"CachedAsset","id":"quiltWrapper:o365.prod:Common:1747128008679","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"community.widget.navbarWidget","props":{"showUserName":true,"showRegisterLink":true,"useIconLanguagePicker":true,"useLabelLanguagePicker":true,"className":"QuiltComponent_lia-component-edit-mode__0nCcm","links":{"sideLinks":[],"mainLinks":[{"children":[],"linkType":"INTERNAL","id":"gxcuf89792","params":{},"routeName":"CommunityPage"},{"children":[],"linkType":"EXTERNAL","id":"external-link","url":"/Directory","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft365","params":{"categoryId":"microsoft365"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows","params":{"categoryId":"Windows"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"Common-microsoft365-copilot-link","params":{"categoryId":"Microsoft365Copilot"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-teams","params":{"categoryId":"MicrosoftTeams"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-securityand-compliance","params":{"categoryId":"microsoft-security"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"azure","params":{"categoryId":"Azure"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"Common-content_management-link","params":{"categoryId":"Content_Management"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"exchange","params":{"categoryId":"Exchange"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows-server","params":{"categoryId":"Windows-Server"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"outlook","params":{"categoryId":"Outlook"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-endpoint-manager","params":{"categoryId":"microsoftintune"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-2","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities","url":"/","target":"BLANK"},{"children":[{"linkType":"INTERNAL","id":"a-i","params":{"categoryId":"AI"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"education-sector","params":{"categoryId":"EducationSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"partner-community","params":{"categoryId":"PartnerCommunity"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"i-t-ops-talk","params":{"categoryId":"ITOpsTalk"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"healthcare-and-life-sciences","params":{"categoryId":"HealthcareAndLifeSciences"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-mechanics","params":{"categoryId":"MicrosoftMechanics"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"public-sector","params":{"categoryId":"PublicSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"s-m-b","params":{"categoryId":"MicrosoftforNonprofits"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"io-t","params":{"categoryId":"IoT"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"startupsat-microsoft","params":{"categoryId":"StartupsatMicrosoft"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"driving-adoption","params":{"categoryId":"DrivingAdoption"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-1","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities-1","url":"/","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external","url":"/Blogs","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external-1","url":"/Events","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft-learn-1","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-learn-blog","params":{"boardId":"MicrosoftLearnBlog","categoryId":"MicrosoftLearn"},"routeName":"BlogBoardPage"},{"linkType":"EXTERNAL","id":"external-10","url":"https://learningroomdirectory.microsoft.com/","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-3","url":"https://docs.microsoft.com/learn/dynamics365/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-4","url":"https://docs.microsoft.com/learn/m365/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-5","url":"https://docs.microsoft.com/learn/topics/sci/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-6","url":"https://docs.microsoft.com/learn/powerplatform/?wt.mc_id=techcom_header-webpage-powerplatform","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-7","url":"https://docs.microsoft.com/learn/github/?wt.mc_id=techcom_header-webpage-github","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-8","url":"https://docs.microsoft.com/learn/teams/?wt.mc_id=techcom_header-webpage-teams","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-9","url":"https://docs.microsoft.com/learn/dotnet/?wt.mc_id=techcom_header-webpage-dotnet","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-2","url":"https://docs.microsoft.com/learn/azure/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"}],"linkType":"INTERNAL","id":"microsoft-learn","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"community-info-center","params":{"categoryId":"Community-Info-Center"},"routeName":"CategoryPage"}]},"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","controllerHighlightColor":"hsla(30, 100%, 50%)","linkFontWeight":"400","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkBoxShadowHover":"none","linkFontSize":"14px","backgroundOpacity":0.8,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","hamburgerColor":"var(--lia-nav-controller-icon-color)","linkTextBorderBottom":"none","brandLogoHeight":"30px","linkBgHoverColor":"transparent","linkLetterSpacing":"normal","collapseMenuDividerOpacity":0.16,"dropdownPaddingBottom":"15px","paddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"1px solid var(--lia-bs-border-color)","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","collapseMenuDividerBg":"var(--lia-nav-link-color)","linkColor":"var(--lia-bs-body-color)","linkJustifyContent":"flex-start","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","controllerTextColor":"var(--lia-nav-controller-icon-color)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-body-color)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid var(--lia-bs-body-color)","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","linkPaddingX":"10px","linkPaddingY":"5px","paddingTop":"15px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkBgColor":"transparent","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkDropdownPaddingY":"9px","controllerIconColor":"var(--lia-bs-body-color)","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"var(--lia-bs-body-color)"},"showSearchIcon":false,"languagePickerStyle":"iconAndLabel"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"transparent","linkHighlightColor":"var(--lia-bs-primary)","visualEffects":{"showBottomBorder":true},"linkTextColor":"var(--lia-bs-gray-700)"},"__typename":"QuiltComponent"},{"id":"custom.widget.HeroBanner","props":{"widgetVisibility":"signedInOrAnonymous","usePageWidth":false,"useTitle":true,"cMax_items":3,"useBackground":false,"title":"","lazyLoad":false,"widgetChooser":"custom.widget.HeroBanner"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.MicrosoftFooter","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1745505307000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"QueryVariables:TopicReplyList:message:4280563:8":{"__typename":"QueryVariables","id":"TopicReplyList:message:4280563:8","value":{"id":"message:4280563","first":10,"sorts":{"postTime":{"direction":"DESC"}},"repliesFirst":3,"repliesFirstDepthThree":1,"repliesSorts":{"postTime":{"direction":"DESC"}},"useAvatar":true,"useAuthorLogin":true,"useAuthorRank":true,"useBody":true,"useKudosCount":true,"useTimeToRead":false,"useMedia":false,"useReadOnlyIcon":false,"useRepliesCount":true,"useSearchSnippet":false,"useAcceptedSolutionButton":false,"useSolvedBadge":false,"useAttachments":false,"attachmentsFirst":5,"useTags":true,"useNodeAncestors":false,"useUserHoverCard":false,"useNodeHoverCard":false,"useModerationStatus":true,"usePreviewSubjectModal":false,"useMessageStatus":true}},"ROOT_MUTATION":{"__typename":"Mutation"},"CachedAsset:component:custom.widget.HeroBanner-en-us-1747150703305":{"__typename":"CachedAsset","id":"component:custom.widget.HeroBanner-en-us-1747150703305","value":{"component":{"id":"custom.widget.HeroBanner","template":{"id":"HeroBanner","markupLanguage":"REACT","style":null,"texts":{"searchPlaceholderText":"Search this community","followActionText":"Follow","unfollowActionText":"Following","searchOnHoverText":"Please enter your search term(s) and then press return key to complete a search.","blogs.sidebar.pagetitle":"Latest Blogs | Microsoft Tech Community","followThisNode":"Follow this node","unfollowThisNode":"Unfollow this node"},"defaults":{"config":{"applicablePages":[],"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.HeroBanner","form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"__typename":"Component","localOverride":false},"globalCss":null,"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"}},"localOverride":false},"CachedAsset:component:custom.widget.MicrosoftFooter-en-us-1747150703305":{"__typename":"CachedAsset","id":"component:custom.widget.MicrosoftFooter-en-us-1747150703305","value":{"component":{"id":"custom.widget.MicrosoftFooter","template":{"id":"MicrosoftFooter","markupLanguage":"HANDLEBARS","style":".context-uhf {\n min-width: 280px;\n font-size: 15px;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.c-uhff-link {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.c-uhff {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.c-uhff-nav {\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n .c-heading-4 {\n color: #616161;\n word-break: break-word;\n font-size: 15px;\n line-height: 20px;\n padding: 36px 0 4px;\n font-weight: 600;\n }\n .c-uhff-nav-row {\n .c-uhff-nav-group {\n display: block;\n float: left;\n min-height: 1px;\n vertical-align: text-top;\n padding: 0 12px;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.c-list.f-bare {\n font-size: 11px;\n line-height: 16px;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 8px 0;\n margin: 0;\n }\n }\n }\n }\n}\n.c-uhff-base {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 30px 5% 16px;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.c-uhff-ccpa {\n font-size: 11px;\n line-height: 16px;\n float: left;\n margin: 3px 0;\n }\n a.c-uhff-ccpa:hover {\n text-decoration: underline;\n }\n ul.c-list {\n font-size: 11px;\n line-height: 16px;\n float: right;\n margin: 3px 0;\n color: #616161;\n li {\n padding: 0 24px 4px 0;\n display: inline-block;\n }\n }\n .c-list.f-bare {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 30px 24px 16px;\n }\n}\n\n.social-share {\n position: fixed;\n top: 60%;\n transform: translateY(-50%);\n left: 0;\n z-index: 1000;\n}\n\n.sharing-options {\n list-style: none;\n padding: 0;\n margin: 0;\n display: block;\n flex-direction: column;\n background-color: white;\n width: 43px;\n border-radius: 0px 7px 7px 0px;\n}\n.linkedin-icon {\n border-top-right-radius: 7px;\n}\n.linkedin-icon:hover {\n border-radius: 0;\n}\n.social-share-rss-image {\n border-bottom-right-radius: 7px;\n}\n.social-share-rss-image:hover {\n border-radius: 0;\n}\n\n.social-link-footer {\n position: relative;\n display: block;\n margin: -2px 0;\n transition: all 0.2s ease;\n}\n.social-link-footer:hover .linkedin-icon {\n border-radius: 0;\n}\n.social-link-footer:hover .social-share-rss-image {\n border-radius: 0;\n}\n\n.social-link-footer img {\n width: 40px;\n height: auto;\n transition: filter 0.3s ease;\n}\n\n.social-share-list {\n width: 40px;\n}\n.social-share-rss-image {\n width: 40px;\n}\n\n.share-icon {\n border: 2px solid transparent;\n display: inline-block;\n position: relative;\n}\n\n.share-icon:hover {\n opacity: 1;\n border: 2px solid white;\n box-sizing: border-box;\n}\n\n.share-icon:hover .label {\n opacity: 1;\n visibility: visible;\n border: 2px solid white;\n box-sizing: border-box;\n border-left: none;\n}\n\n.label {\n position: absolute;\n left: 100%;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n color: white;\n border-radius: 0 10 0 10px;\n top: 50%;\n transform: translateY(-50%);\n height: 40px;\n border-radius: 0 6px 6px 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px 5px 20px 8px;\n margin-left: -1px;\n}\n.linkedin {\n background-color: #0474b4;\n}\n.facebook {\n background-color: #3c5c9c;\n}\n.twitter {\n background-color: white;\n color: black;\n}\n.reddit {\n background-color: #fc4404;\n}\n.mail {\n background-color: #848484;\n}\n.bluesky {\n background-color: white;\n color: black;\n}\n.rss {\n background-color: #ec7b1c;\n}\n#RSS {\n width: 40px;\n height: 40px;\n}\n\n@media (max-width: 991px) {\n .social-share {\n display: none;\n }\n}\n","texts":{"New tab":"What's New","New 1":"Surface Laptop Studio 2","New 2":"Surface Laptop Go 3","New 3":"Surface Pro 9","New 4":"Surface Laptop 5","New 5":"Surface Studio 2+","New 6":"Copilot in Windows","New 7":"Microsoft 365","New 8":"Windows 11 apps","Store tab":"Microsoft Store","Store 1":"Account Profile","Store 2":"Download Center","Store 3":"Microsoft Store Support","Store 4":"Returns","Store 5":"Order tracking","Store 6":"Certified Refurbished","Store 7":"Microsoft Store Promise","Store 8":"Flexible Payments","Education tab":"Education","Edu 1":"Microsoft in education","Edu 2":"Devices for education","Edu 3":"Microsoft Teams for Education","Edu 4":"Microsoft 365 Education","Edu 5":"How to buy for your school","Edu 6":"Educator Training and development","Edu 7":"Deals for students and parents","Edu 8":"Azure for students","Business tab":"Business","Bus 1":"Microsoft Cloud","Bus 2":"Microsoft Security","Bus 3":"Dynamics 365","Bus 4":"Microsoft 365","Bus 5":"Microsoft Power Platform","Bus 6":"Microsoft Teams","Bus 7":"Microsoft Industry","Bus 8":"Small Business","Developer tab":"Developer & IT","Dev 1":"Azure","Dev 2":"Developer Center","Dev 3":"Documentation","Dev 4":"Microsoft Learn","Dev 5":"Microsoft Tech Community","Dev 6":"Azure Marketplace","Dev 7":"AppSource","Dev 8":"Visual Studio","Company tab":"Company","Com 1":"Careers","Com 2":"About Microsoft","Com 3":"Company News","Com 4":"Privacy at Microsoft","Com 5":"Investors","Com 6":"Diversity and inclusion","Com 7":"Accessiblity","Com 8":"Sustainibility"},"defaults":{"config":{"applicablePages":[],"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.MicrosoftFooter","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":{"css":".custom_widget_MicrosoftFooter_context-uhf_105bp_1 {\n min-width: 17.5rem;\n font-size: 0.9375rem;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-link_105bp_12 {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff_105bp_12 {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.custom_widget_MicrosoftFooter_c-uhff-nav_105bp_35 {\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n .custom_widget_MicrosoftFooter_c-heading-4_105bp_49 {\n color: #616161;\n word-break: break-word;\n font-size: 0.9375rem;\n line-height: 1.25rem;\n padding: 2.25rem 0 0.25rem;\n font-weight: 600;\n }\n .custom_widget_MicrosoftFooter_c-uhff-nav-row_105bp_57 {\n .custom_widget_MicrosoftFooter_c-uhff-nav-group_105bp_58 {\n display: block;\n float: left;\n min-height: 0.0625rem;\n vertical-align: text-top;\n padding: 0 0.75rem;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.custom_widget_MicrosoftFooter_c-list_105bp_78.custom_widget_MicrosoftFooter_f-bare_105bp_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 0.5rem 0;\n margin: 0;\n }\n }\n }\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff-base_105bp_94 {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 1.875rem 5% 1rem;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_105bp_107 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: left;\n margin: 0.1875rem 0;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_105bp_107:hover {\n text-decoration: underline;\n }\n ul.custom_widget_MicrosoftFooter_c-list_105bp_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: right;\n margin: 0.1875rem 0;\n color: #616161;\n li {\n padding: 0 1.5rem 0.25rem 0;\n display: inline-block;\n }\n }\n .custom_widget_MicrosoftFooter_c-list_105bp_78.custom_widget_MicrosoftFooter_f-bare_105bp_78 {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 1.875rem 1.5rem 1rem;\n }\n}\n.custom_widget_MicrosoftFooter_social-share_105bp_138 {\n position: fixed;\n top: 60%;\n transform: translateY(-50%);\n left: 0;\n z-index: 1000;\n}\n.custom_widget_MicrosoftFooter_sharing-options_105bp_146 {\n list-style: none;\n padding: 0;\n margin: 0;\n display: block;\n flex-direction: column;\n background-color: white;\n width: 2.6875rem;\n border-radius: 0 0.4375rem 0.4375rem 0;\n}\n.custom_widget_MicrosoftFooter_linkedin-icon_105bp_156 {\n border-top-right-radius: 7px;\n}\n.custom_widget_MicrosoftFooter_linkedin-icon_105bp_156:hover {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162 {\n border-bottom-right-radius: 7px;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162:hover {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169 {\n position: relative;\n display: block;\n margin: -0.125rem 0;\n transition: all 0.2s ease;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169:hover .custom_widget_MicrosoftFooter_linkedin-icon_105bp_156 {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169:hover .custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162 {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169 img {\n width: 2.5rem;\n height: auto;\n transition: filter 0.3s ease;\n}\n.custom_widget_MicrosoftFooter_social-share-list_105bp_188 {\n width: 2.5rem;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162 {\n width: 2.5rem;\n}\n.custom_widget_MicrosoftFooter_share-icon_105bp_195 {\n border: 2px solid transparent;\n display: inline-block;\n position: relative;\n}\n.custom_widget_MicrosoftFooter_share-icon_105bp_195:hover {\n opacity: 1;\n border: 2px solid white;\n box-sizing: border-box;\n}\n.custom_widget_MicrosoftFooter_share-icon_105bp_195:hover .custom_widget_MicrosoftFooter_label_105bp_207 {\n opacity: 1;\n visibility: visible;\n border: 2px solid white;\n box-sizing: border-box;\n border-left: none;\n}\n.custom_widget_MicrosoftFooter_label_105bp_207 {\n position: absolute;\n left: 100%;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n color: white;\n border-radius: 0 10 0 0.625rem;\n top: 50%;\n transform: translateY(-50%);\n height: 2.5rem;\n border-radius: 0 0.375rem 0.375rem 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.25rem 0.3125rem 1.25rem 0.5rem;\n margin-left: -0.0625rem;\n}\n.custom_widget_MicrosoftFooter_linkedin_105bp_156 {\n background-color: #0474b4;\n}\n.custom_widget_MicrosoftFooter_facebook_105bp_237 {\n background-color: #3c5c9c;\n}\n.custom_widget_MicrosoftFooter_twitter_105bp_240 {\n background-color: white;\n color: black;\n}\n.custom_widget_MicrosoftFooter_reddit_105bp_244 {\n background-color: #fc4404;\n}\n.custom_widget_MicrosoftFooter_mail_105bp_247 {\n background-color: #848484;\n}\n.custom_widget_MicrosoftFooter_bluesky_105bp_250 {\n background-color: white;\n color: black;\n}\n.custom_widget_MicrosoftFooter_rss_105bp_254 {\n background-color: #ec7b1c;\n}\n#custom_widget_MicrosoftFooter_RSS_105bp_1 {\n width: 2.5rem;\n height: 2.5rem;\n}\n@media (max-width: 991px) {\n .custom_widget_MicrosoftFooter_social-share_105bp_138 {\n display: none;\n }\n}\n","tokens":{"context-uhf":"custom_widget_MicrosoftFooter_context-uhf_105bp_1","c-uhff-link":"custom_widget_MicrosoftFooter_c-uhff-link_105bp_12","c-uhff":"custom_widget_MicrosoftFooter_c-uhff_105bp_12","c-uhff-nav":"custom_widget_MicrosoftFooter_c-uhff-nav_105bp_35","c-heading-4":"custom_widget_MicrosoftFooter_c-heading-4_105bp_49","c-uhff-nav-row":"custom_widget_MicrosoftFooter_c-uhff-nav-row_105bp_57","c-uhff-nav-group":"custom_widget_MicrosoftFooter_c-uhff-nav-group_105bp_58","c-list":"custom_widget_MicrosoftFooter_c-list_105bp_78","f-bare":"custom_widget_MicrosoftFooter_f-bare_105bp_78","c-uhff-base":"custom_widget_MicrosoftFooter_c-uhff-base_105bp_94","c-uhff-ccpa":"custom_widget_MicrosoftFooter_c-uhff-ccpa_105bp_107","social-share":"custom_widget_MicrosoftFooter_social-share_105bp_138","sharing-options":"custom_widget_MicrosoftFooter_sharing-options_105bp_146","linkedin-icon":"custom_widget_MicrosoftFooter_linkedin-icon_105bp_156","social-share-rss-image":"custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162","social-link-footer":"custom_widget_MicrosoftFooter_social-link-footer_105bp_169","social-share-list":"custom_widget_MicrosoftFooter_social-share-list_105bp_188","share-icon":"custom_widget_MicrosoftFooter_share-icon_105bp_195","label":"custom_widget_MicrosoftFooter_label_105bp_207","linkedin":"custom_widget_MicrosoftFooter_linkedin_105bp_156","facebook":"custom_widget_MicrosoftFooter_facebook_105bp_237","twitter":"custom_widget_MicrosoftFooter_twitter_105bp_240","reddit":"custom_widget_MicrosoftFooter_reddit_105bp_244","mail":"custom_widget_MicrosoftFooter_mail_105bp_247","bluesky":"custom_widget_MicrosoftFooter_bluesky_105bp_250","rss":"custom_widget_MicrosoftFooter_rss_105bp_254","RSS":"custom_widget_MicrosoftFooter_RSS_105bp_1"}},"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1745505307000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBanner-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBanner-1745505307000","value":{"messageMarkedAsSpam":"This post has been marked as spam","messageMarkedAsSpam@board:TKB":"This article has been marked as spam","messageMarkedAsSpam@board:BLOG":"This post has been marked as spam","messageMarkedAsSpam@board:FORUM":"This discussion has been marked as spam","messageMarkedAsSpam@board:OCCASION":"This event has been marked as spam","messageMarkedAsSpam@board:IDEA":"This idea has been marked as spam","manageSpam":"Manage Spam","messageMarkedAsAbuse":"This post has been marked as abuse","messageMarkedAsAbuse@board:TKB":"This article has been marked as abuse","messageMarkedAsAbuse@board:BLOG":"This post has been marked as abuse","messageMarkedAsAbuse@board:FORUM":"This discussion has been marked as abuse","messageMarkedAsAbuse@board:OCCASION":"This event has been marked as abuse","messageMarkedAsAbuse@board:IDEA":"This idea has been marked as abuse","preModCommentAuthorText":"This comment will be published as soon as it is approved","preModCommentModeratorText":"This comment is awaiting moderation","messageMarkedAsOther":"This post has been rejected due to other reasons","messageMarkedAsOther@board:TKB":"This article has been rejected due to other reasons","messageMarkedAsOther@board:BLOG":"This post has been rejected due to other reasons","messageMarkedAsOther@board:FORUM":"This discussion has been rejected due to other reasons","messageMarkedAsOther@board:OCCASION":"This event has been rejected due to other reasons","messageMarkedAsOther@board:IDEA":"This idea has been rejected due to other reasons","messageArchived":"This post was archived on {date}","relatedUrl":"View Related Content","relatedContentText":"Showing related content","archivedContentLink":"View Archived Content"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewStandard-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewStandard-1745505307000","value":{"anonymous":"Anonymous","author":"{messageAuthorLogin}","authorBy":"{messageAuthorLogin}","board":"{messageBoardTitle}","replyToUser":" to {parentAuthor}","showMoreReplies":"Show More","replyText":"Reply","repliesText":"Replies","markedAsSolved":"Marked as Solution","movedMessagePlaceholder.BLOG":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.TKB":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.FORUM":"{count, plural, =0 {This reply has been} other {These replies have been} }","movedMessagePlaceholder.IDEA":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.OCCASION":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholderUrlText":"moved.","messageStatus":"Status: ","statusChanged":"Status changed: {previousStatus} to {currentStatus}","statusAdded":"Status added: {status}","statusRemoved":"Status removed: {status}","labelExpand":"expand replies","labelCollapse":"collapse replies","unhelpfulReason.reason1":"Content is outdated","unhelpfulReason.reason2":"Article is missing information","unhelpfulReason.reason3":"Content is for a different Product","unhelpfulReason.reason4":"Doesn't match what I was searching for"},"localOverride":false},"CachedAsset:text:en_US-components/messages/ThreadedReplyList-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/ThreadedReplyList-1745505307000","value":{"title":"{count, plural, one{# Reply} other{# Replies}}","title@board:BLOG":"{count, plural, one{# Comment} other{# Comments}}","title@board:TKB":"{count, plural, one{# Comment} other{# Comments}}","title@board:IDEA":"{count, plural, one{# Comment} other{# Comments}}","title@board:OCCASION":"{count, plural, one{# Comment} other{# Comments}}","noRepliesTitle":"No Replies","noRepliesTitle@board:BLOG":"No Comments","noRepliesTitle@board:TKB":"No Comments","noRepliesTitle@board:IDEA":"No Comments","noRepliesTitle@board:OCCASION":"No Comments","noRepliesDescription":"Be the first to reply","noRepliesDescription@board:BLOG":"Be the first to comment","noRepliesDescription@board:TKB":"Be the first to comment","noRepliesDescription@board:IDEA":"Be the first to comment","noRepliesDescription@board:OCCASION":"Be the first to comment","messageReadOnlyAlert:BLOG":"Comments have been turned off for this post","messageReadOnlyAlert:TKB":"Comments have been turned off for this article","messageReadOnlyAlert:IDEA":"Comments have been turned off for this idea","messageReadOnlyAlert:FORUM":"Replies have been turned off for this discussion","messageReadOnlyAlert:OCCASION":"Comments have been turned off for this event"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyCallToAction-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyCallToAction-1745505307000","value":{"leaveReply":"Leave a reply...","leaveReply@board:BLOG@message:root":"Leave a comment...","leaveReply@board:TKB@message:root":"Leave a comment...","leaveReply@board:IDEA@message:root":"Leave a comment...","leaveReply@board:OCCASION@message:root":"Leave a comment...","repliesTurnedOff.FORUM":"Replies are turned off for this topic","repliesTurnedOff.BLOG":"Comments are turned off for this topic","repliesTurnedOff.TKB":"Comments are turned off for this topic","repliesTurnedOff.IDEA":"Comments are turned off for this topic","repliesTurnedOff.OCCASION":"Comments are turned off for this topic","infoText":"Stop poking me!"},"localOverride":false},"Category:category:Exchange":{"__typename":"Category","id":"category:Exchange","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Outlook":{"__typename":"Category","id":"category:Outlook","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Community-Info-Center":{"__typename":"Category","id":"category:Community-Info-Center","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:EducationSector":{"__typename":"Category","id":"category:EducationSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:DrivingAdoption":{"__typename":"Category","id":"category:DrivingAdoption","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows-Server":{"__typename":"Category","id":"category:Windows-Server","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftTeams":{"__typename":"Category","id":"category:MicrosoftTeams","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PublicSector":{"__typename":"Category","id":"category:PublicSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft365":{"__typename":"Category","id":"category:microsoft365","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:IoT":{"__typename":"Category","id":"category:IoT","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:HealthcareAndLifeSciences":{"__typename":"Category","id":"category:HealthcareAndLifeSciences","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:ITOpsTalk":{"__typename":"Category","id":"category:ITOpsTalk","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftLearn":{"__typename":"Category","id":"category:MicrosoftLearn","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Blog:board:MicrosoftLearnBlog":{"__typename":"Blog","id":"board:MicrosoftLearnBlog","blogPolicies":{"__typename":"BlogPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:AI":{"__typename":"Category","id":"category:AI","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftMechanics":{"__typename":"Category","id":"category:MicrosoftMechanics","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftforNonprofits":{"__typename":"Category","id":"category:MicrosoftforNonprofits","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:StartupsatMicrosoft":{"__typename":"Category","id":"category:StartupsatMicrosoft","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PartnerCommunity":{"__typename":"Category","id":"category:PartnerCommunity","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Microsoft365Copilot":{"__typename":"Category","id":"category:Microsoft365Copilot","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows":{"__typename":"Category","id":"category:Windows","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Content_Management":{"__typename":"Category","id":"category:Content_Management","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft-security":{"__typename":"Category","id":"category:microsoft-security","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoftintune":{"__typename":"Category","id":"category:microsoftintune","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"CachedAsset:text:en_US-components/community/Navbar-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1745505307000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","gxcuf89792":"Tech Community","external-1":"Events","s-m-b":"Nonprofit Community","windows-server":"Windows Server","education-sector":"Education Sector","driving-adoption":"Driving Adoption","Common-content_management-link":"Content Management","microsoft-learn":"Microsoft Learn","s-q-l-server":"Content Management","partner-community":"Microsoft Partner Community","microsoft365":"Microsoft 365","external-9":".NET","external-8":"Teams","external-7":"Github","products-services":"Products","external-6":"Power Platform","communities-1":"Topics","external-5":"Microsoft Security","planner":"Outlook","external-4":"Microsoft 365","external-3":"Dynamics 365","azure":"Azure","healthcare-and-life-sciences":"Healthcare and Life Sciences","external-2":"Azure","microsoft-mechanics":"Microsoft Mechanics","microsoft-learn-1":"Community","external-10":"Learning Room Directory","microsoft-learn-blog":"Blog","windows":"Windows","i-t-ops-talk":"ITOps Talk","external-link-1":"View All","microsoft-securityand-compliance":"Microsoft Security","public-sector":"Public Sector","community-info-center":"Lounge","external-link-2":"View All","microsoft-teams":"Microsoft Teams","external":"Blogs","microsoft-endpoint-manager":"Microsoft Intune","startupsat-microsoft":"Startups at Microsoft","exchange":"Exchange","a-i":"AI and Machine Learning","io-t":"Internet of Things (IoT)","Common-microsoft365-copilot-link":"Microsoft 365 Copilot","outlook":"Microsoft 365 Copilot","external-link":"Community Hubs","communities":"Products"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1745505307000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1745505307000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1745505307000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1745505307000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1745505307000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCoverImage-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCoverImage-1745505307000","value":{"coverImageTitle":"Cover Image"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeTitle-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeTitle-1745505307000","value":{"nodeTitle":"{nodeTitle, select, community {Community} other {{nodeTitle}}} "},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTimeToRead-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTimeToRead-1745505307000","value":{"minReadText":"{min} MIN READ"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1745505307000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1745505307000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserRank-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserRank-1745505307000","value":{"rankName":"{rankName}","userRank":"Author rank {rankName}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1745505307000","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1745505307000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCustomFields-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCustomFields-1745505307000","value":{"CustomField.default.label":"Value of {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRevision-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRevision-1745505307000","value":{"lastUpdatedDatePublished":"{publishCount, plural, one{Published} other{Updated}} {date}","lastUpdatedDateDraft":"Created {date}","version":"Version {major}.{minor}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1745505307000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyButton-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyButton-1745505307000","value":{"repliesCount":"{count}","title":"Reply","title@board:BLOG@message:root":"Comment","title@board:TKB@message:root":"Comment","title@board:IDEA@message:root":"Comment","title@board:OCCASION@message:root":"Comment"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageAuthorBio-1745505307000","value":{"sendMessage":"Send Message","actionMessage":"Follow this blog board to get notified when there's new activity","coAuthor":"CO-PUBLISHER","contributor":"CONTRIBUTOR","userProfile":"View Profile","iconlink":"Go to {name} {type}"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1745505307000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1745505307000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/ranks/UserRankLabel-1745505307000","value":{"altTitle":"Icon for {rankName} rank"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagView/TagViewChip-1745505307000","value":{"tagLabelName":"Tag name {tagName}"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserRegistrationDate-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserRegistrationDate-1745505307000","value":{"noPrefix":"{date}","withPrefix":"Joined {date}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeAvatar-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeAvatar-1745505307000","value":{"altTitle":"Node avatar for {nodeTitle}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeDescription-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeDescription-1745505307000","value":{"description":"{description}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1745505307000","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false}}}},"page":"/blogs/BlogMessagePage/BlogMessagePage","query":{"boardId":"azurecommunicationservicesblog","messageSubject":"part-2---multichannel-notification-system-using-azure-communication-services-and","messageId":"4280563"},"buildId":"YK32GCbhJqbL-HLk4DLXM","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"o365","openTelemetryServiceVersion":"25.3.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/customComponent/CustomComponent/CustomComponent.tsx","./components/blogs/BlogArticleWidget/BlogArticleWidget.tsx","./components/messages/MessageView/MessageViewStandard/MessageViewStandard.tsx","./components/messages/ThreadedReplyList/ThreadedReplyList.tsx","./components/external/components/ExternalComponent.tsx","../shared/client/components/common/List/UnwrappedList/UnwrappedList.tsx","./components/tags/TagView/TagView.tsx","./components/tags/TagView/TagViewChip/TagViewChip.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx"],"appGip":true,"scriptLoader":[{"id":"analytics","src":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/pagescripts/1730819800000/analytics.js?page.id=BlogMessagePage&entity.id=board%3Aazurecommunicationservicesblog&entity.id=message%3A4280563","strategy":"afterInteractive"}]}