Reaching People: Email, SMS, and Phone
Once the alert lifecycle has decided who to notify, something has to actually reach them. That's three services over Azure Communication Services — email, SMS, and outbound phone calls. Two of them come wired up by one registration call; the third doesn't, and that asymmetry is the thing to remember.
One call gives you two of the three
AddCommunicationServices registers the SmsClient and EmailClient (singletons, built from
the CommunicationServicesUrl), then ISmsService and IEmailService. Inject either and
send:
IEmailService.SendEmailsAsync— subject/body to a list of recipients, with optional CC/BCC, an optionalhtmlBody(falls back to HTML-encoded plain text), and attachments. Two overloads take eitherEntraUserEntityor the SQLUsermodel, so callers on either side of the data layer can use it directly.ISmsService.SendBulkAsync— one message to many phone numbers.
The Azure SDK accepts at most 100 messages per send. SendBulkAsync checks the count and,
above 100, splits the list into hundred-number chunks before sending:
if (phoneNumbers.Count() <= 100) { /* single send */ }
else { var chunks = CommunicationServicesUtilities.ChunkOversizedListByHundreds(phoneNumbers); /* … */ }
This is handled for you — but it means a 250-recipient blast is three SDK calls, not one. If you're rate-limited or partially failing on large sends, the chunk boundary is where to look; a failure in chunk two doesn't roll back chunk one.
The third channel you have to wire yourself
PhoneCallService places outbound calls via the ACS CallAutomationClient, with Cognitive
Services for text-to-speech. It is not registered by AddCommunicationServices — if you
inject IPhoneCallService without registering it yourself, you get a DI resolution error, not
a silent no-op.
CallTargetAsync(phoneNumber, hostAppCallbackUri) starts a call, and ACS posts call events
back to hostAppCallbackUri — the host app then uses GetCallConnection(callEvent) to drive
the in-progress call (play text-to-speech, hang up). That callback URL must be publicly
reachable by Azure; a localhost URL means the call connects and then nothing further happens,
because the events can't be delivered.
Wrapping up
Three outbound channels ride on Azure Communication Services. AddCommunicationServices wires
email and SMS; phone calls are opt-in because they're stateful and need a reachable callback
plus Cognitive Services. The one operational surprise is SMS auto-chunking at 100 recipients —
convenient, but it turns one logical blast into several independent sends.
Next, the services that guard the doors — API keys, tokens, and encryption: Guarding the Doors.