Pandatech.Communicator
4.0.0
dotnet add package Pandatech.Communicator --version 4.0.0
NuGet\Install-Package Pandatech.Communicator -Version 4.0.0
<PackageReference Include="Pandatech.Communicator" Version="4.0.0" />
<PackageVersion Include="Pandatech.Communicator" Version="4.0.0" />
<PackageReference Include="Pandatech.Communicator" />
paket add Pandatech.Communicator --version 4.0.0
#r "nuget: Pandatech.Communicator, 4.0.0"
#:package Pandatech.Communicator@4.0.0
#addin nuget:?package=Pandatech.Communicator&version=4.0.0
#tool nuget:?package=Pandatech.Communicator&version=4.0.0
Pandatech.Communicator
Send email via SMTP and SMS via Dexatel or Twilio through a DI-friendly, multi-channel API. Supports both
appsettings.json and programmatic configuration, named channels per transport, and a fake mode for local development.
Targets net8.0, net9.0, and net10.0.
Table of Contents
Features
- Email over SMTP using MailKit — TLS negotiation, optional authentication, CC/BCC, attachments, HTML body
- SMS via Dexatel and Twilio with a unified
GeneralSmsResponse - Named channels — configure multiple senders per transport (e.g.
TransactionalSender,MarketingSender) and pick the right one per message - Validation on every send call — recipients, addresses, and phone numbers are checked before any network call
- Fake mode — logs messages at
Criticalinstead of sending; zero external calls in development or test environments - Supports both
WebApplicationBuilderand plainIServiceCollectionregistration
Installation
dotnet add package Pandatech.Communicator
Registration
WebApplicationBuilder
builder.AddCommunicator(); // reads from appsettings.json "Communicator" section
// or
builder.AddCommunicator(options => { /* programmatic setup */ });
IServiceCollection
services.AddCommunicator(configuration);
// or
services.AddCommunicator(configuration, options => { /* programmatic setup */ });
Both register IEmailService and ISmsService into DI as scoped services.
Configuration
appsettings.json
{
"Communicator": {
"EmailFake": false,
"SmsFake": false,
"EmailConfigurations": {
"TransactionalSender": {
"SmtpServer": "smtp.gmail.com",
"SmtpPort": 587,
"SmtpUsername": "you@example.com",
"SmtpPassword": "app-password",
"SenderEmail": "no-reply@example.com",
"SenderName": "My App",
"TimeoutMs": 10000
},
"MarketingSender": {
"SmtpServer": "smtp.sendgrid.net",
"SmtpPort": 587,
"SmtpUsername": "apikey",
"SmtpPassword": "SG.xxx",
"SenderEmail": "marketing@example.com",
"TimeoutMs": 10000
}
},
"SmsConfigurations": {
"TransactionalSender": {
"Provider": "Dexatel",
"From": "MyApp",
"TimeoutMs": 10000,
"Properties": {
"X-Dexatel-Key": "your-dexatel-api-key"
}
},
"NotificationSender": {
"Provider": "Twilio",
"From": "+15550001234",
"TimeoutMs": 10000,
"Properties": {
"SID": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"AUTH_TOKEN": "your-auth-token"
}
}
}
}
}
Programmatic
builder.AddCommunicator(options =>
{
options.EmailConfigurations = new Dictionary<string, EmailConfiguration>
{
["TransactionalSender"] = new()
{
SmtpServer = "smtp.gmail.com",
SmtpPort = 587,
SmtpUsername = "you@example.com",
SmtpPassword = "app-password",
SenderEmail = "no-reply@example.com",
SenderName = "My App"
}
};
options.SmsConfigurations = new Dictionary<string, SmsConfiguration>
{
["TransactionalSender"] = new()
{
Provider = "Dexatel",
From = "MyApp",
Properties = new() { ["X-Dexatel-Key"] = "your-key" }
}
};
});
Channels
Channel names are validated at startup against a fixed set of supported names:
GeneralSender
TransactionalSender
NotificationSender
MarketingSender
SupportSender
Each channel maps to exactly one configuration entry. The Channel property on EmailMessage and SmsMessage
selects which configuration is used for that send call.
Sending Email
public class NotificationService(IEmailService emailService)
{
public async Task SendWelcomeAsync(string userEmail, CancellationToken ct)
{
var message = new EmailMessage
{
Recipients = [userEmail],
Subject = "Welcome!",
Body = "<h1>Thanks for signing up.</h1>",
IsBodyHtml = true,
Channel = EmailChannels.TransactionalSender,
Cc = ["manager@example.com"],
Attachments = [new EmailAttachment("terms.pdf", pdfBytes)]
};
var response = await emailService.SendAsync(message, ct);
}
}
SendBulkAsync accepts a list of messages, opens one SMTP connection per channel, and sends all messages for that
channel on the same connection before moving to the next.
Sending SMS
public class OtpService(ISmsService smsService)
{
public async Task SendOtpAsync(string phoneNumber, string code, CancellationToken ct)
{
var message = new SmsMessage
{
Recipients = [phoneNumber],
Message = $"Your code is {code}",
Channel = SmsChannels.TransactionalSender
};
var responses = await smsService.SendAsync(message, ct);
}
}
Phone numbers are normalized before sending — +, (, ), and spaces are stripped, and Panda-formatted numbers
like (374)91123456 are handled automatically.
Provider-specific Properties
| Provider | Required Properties |
|---|---|
| Dexatel | X-Dexatel-Key |
| Twilio | SID, AUTH_TOKEN |
Fake Mode
Set EmailFake: true or SmsFake: true (or both) to replace the real services with fake implementations that log
at Critical instead of making any network calls. The same validation still runs.
{
"Communicator": {
"EmailFake": true,
"SmsFake": true
}
}
Useful in local development and CI environments where you want to confirm messages are being sent without delivering them.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.0 | 0 | 2/28/2026 |
| 3.0.1 | 102 | 1/27/2026 |
| 3.0.0 | 113 | 12/29/2025 |
| 2.2.2 | 183 | 12/23/2025 |
| 2.2.1 | 186 | 12/23/2025 |
| 2.2.0 | 188 | 12/23/2025 |
| 2.1.4 | 204 | 8/16/2025 |
| 2.1.3 | 246 | 6/1/2025 |
| 2.1.2 | 191 | 2/17/2025 |
| 2.1.1 | 198 | 12/5/2024 |
| 2.1.0 | 194 | 11/26/2024 |
| 2.0.0 | 178 | 11/21/2024 |
| 1.0.6 | 246 | 8/15/2024 |
| 1.0.5 | 248 | 6/3/2024 |
| 1.0.4 | 207 | 5/30/2024 |
| 1.0.3 | 229 | 4/17/2024 |
| 1.0.2 | 256 | 2/23/2024 |
| 1.0.1 | 223 | 2/23/2024 |
| 1.0.0 | 233 | 2/23/2024 |
| 0.0.1 | 246 | 2/8/2024 |
Multi-target net8.0/net9.0/net10.0, source-generated logging, removed unused OpenAPI reference