SMSwitch 10.2.1
dotnet add package SMSwitch --version 10.2.1
NuGet\Install-Package SMSwitch -Version 10.2.1
<PackageReference Include="SMSwitch" Version="10.2.1" />
<PackageVersion Include="SMSwitch" Version="10.2.1" />
<PackageReference Include="SMSwitch" />
paket add SMSwitch --version 10.2.1
#r "nuget: SMSwitch, 10.2.1"
#:package SMSwitch@10.2.1
#addin nuget:?package=SMSwitch&version=10.2.1
#tool nuget:?package=SMSwitch&version=10.2.1
SMSwitch
SMSwitch is an open-source C# class library that acts as a switchboard in front of multiple SMS providers. It sends one-time passwords (OTPs) and plain SMS messages through Twilio or Plivo, choosing the provider per destination country and automatically failing over to the next provider when one fails. All sessions and attempts are stored in your own MongoDB instance for auditing.
Features
- Multi-provider with failover — configure a provider priority per country phone code plus a global fallback; failed sends automatically retry with the next provider in the queue.
- OTP send & verify — delegates to the providers' hosted verification products (Twilio Verify, Plivo Verify), including localized OTP message templates.
- Plain SMS — with delivery-status confirmation and resend-cooldown deduplication.
DevConsoleprovider for local testing — prints the OTP to the console instead of sending a real SMS (see below).- Audit trail in your own MongoDB — every session, attempt, and delivery notification is stored in your database.
- Android SMS Retriever support — pass your app hash so OTP messages can be auto-read on Android.
How it works
For each phone number, SMSwitch builds a queue of providers from your configured priorities (PriorityBasedOnCountryPhoneCode, falling back to FallBackPriority), repeated MaxRoundRobinAttempts times. Each send works through the queue until a provider succeeds; verification is routed to the provider that sent the OTP. A verification session expires after SessionTimeoutInSeconds or MaximumFailedAttemptsToVerify failed attempts. Repeated sends inside the resend cooldown return the previous result instead of sending again.
Getting started
1. Install
dotnet add package SMSwitch
2. Prerequisites
SMSwitch builds on two companion packages that are installed automatically but need configuration:
- MongoDbService — provides the MongoDB connection. Requires a
MongoDbSettingssection (connection string + database name). - uSignIn.CommonSettings — provides your application's public base URL, which SMSwitch uses to build the Plivo delivery-notification callback URL. Requires a
Settingssection with aBaseUrl.
3. Configure
Add the following to your appsettings.json and adjust the values (keep real credentials in user secrets or environment variables):
{
"Settings": {
"BaseUrl": "https://your-public-hostname/"
},
"MongoDbSettings": {
"ConnectionString": "MovedToSecret",
"DatabaseName": "MyDatabase"
},
"SMSwitchSettings": {
"SupportedCountriesIsoCodes": [ "IN", "FI", "DK" ],
"Controls": {
"MaximumFailedAttemptsToVerify": 4,
"SessionTimeoutInSeconds": 240,
"MaxRoundRobinAttempts": 2,
"PriorityBasedOnCountryPhoneCode": {
"44": [ "Twilio", "Plivo" ],
"45": [ "Twilio", "Plivo" ],
"91": [ "Plivo", "Twilio" ]
},
"FallBackPriority": [ "Twilio", "Plivo" ]
},
"AndroidAppHash": "MovedToSecret",
"OtpLength": 6,
"Twilio": {
"AccountSid": "MovedToSecret",
"AuthToken": "MovedToSecret",
"ServiceSid": "MovedToSecret",
"RegisteredSenderPhoneNumber": "MovedToSecret"
},
"Plivo": {
"AuthId": "MovedToSecret",
"AuthToken": "MovedToSecret",
"AppUuid": "MovedToSecret",
"SourceNumber": "MovedToSecret",
"WebhookSecret": "MovedToSecret"
}
}
}
| Setting | Meaning |
|---|---|
SupportedCountriesIsoCodes |
Countries marked as supported in the country database. Empty list means all countries are supported. |
Controls:MaximumFailedAttemptsToVerify |
Failed verification attempts before a session expires (default 3). |
Controls:SessionTimeoutInSeconds |
Lifetime of an OTP session (default 240). |
Controls:MaxRoundRobinAttempts |
How many times the provider priority list is repeated in the retry queue (default 1). |
Controls:PriorityBasedOnCountryPhoneCode |
Provider order per country phone code. |
Controls:FallBackPriority |
Provider order for phone codes not listed above. Required. |
AndroidAppHash |
Your Android app hash for SMS Retriever auto-read. |
OtpLength |
OTP digit count. Applied to Twilio; Plivo is fixed at 6 (a warning is logged if they differ). |
Plivo:SourceNumber |
Sender number for plain SMS via Plivo (not needed for OTPs). |
Plivo:WebhookSecret |
Optional but recommended. Appended to the delivery-notification callback URL registered with Plivo; webhook calls without the matching secret are rejected with 401 Unauthorized. |
4. Register the services
using MongoDbService;
using SMSwitch;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMongoDbServices();
builder.Services.AddSMSwitchServices();
var app = builder.Build();
// Maps the Plivo delivery-notification webhook at /smswitch/plivonotification.
// Required if you use Plivo; harmless otherwise.
app.AddSMSwitchApiEndpoints();
app.Run();
5. Use it
Dependency-inject SMSwitchService wherever you need it:
using HumanLanguages;
using SMSwitch;
using SMSwitch.Common.DTOs;
public sealed class SignInFlow
{
private readonly SMSwitchService _smSwitch;
public SignInFlow(SMSwitchService smSwitch) => _smSwitch = smSwitch;
public async Task<bool> Demo()
{
var mobileNumber = new MobileNumber
{
CountryIsoCodeString = "DK",
CountryPhoneCode = "45",
PhoneNumber = "12345678"
};
var preferredLanguages = new HashSet<LanguageIsoCode> { HumanHelper.CreateLanguageIsoCode("en") };
// Send a one-time password (provider is picked from your configured priorities)
var sendResponse = await _smSwitch.SendOTP(mobileNumber, preferredLanguages, UserAgent.WebBrowser);
// sendResponse.IsSent, sendResponse.OtpLength
// Later, verify the OTP the user typed in
var verifyResponse = await _smSwitch.VerifyOTP(mobileNumber, "123456");
// verifyResponse.Verified, verifyResponse.Expired
// Or send a plain SMS
var smsSent = await _smSwitch.SendSMS(mobileNumber, "Hello from SMSwitch!");
return verifyResponse.Verified;
}
}
Local testing without real SMS
For local development you can route messages to the DevConsole provider instead of Twilio or Plivo, so no credits are spent and no credentials are needed. The OTP (or SMS text) is printed to the console via the logger, and OTPs are generated and verified through MongoDbTokenManager in your own MongoDB instance — the full SendOTP → VerifyOTP flow works end to end.
Put this in your appsettings.Development.json:
{
"SMSwitchSettings": {
"Controls": {
"PriorityBasedOnCountryPhoneCode": {
"45": [ "DevConsole" ]
},
"FallBackPriority": [ "DevConsole" ]
}
}
}
As a safety measure the DevConsole provider refuses to operate when the app runs in the Production environment: it logs a critical error and reports the send as failed, so the provider queue falls through to a real provider if one is configured.
Contributing
We welcome contributions! If you find a bug or have an idea for an improvement, please submit an issue or a pull request on GitHub. The repository includes a TestAPIs project — a minimal ASP.NET Core app with Swagger and ready-made .http requests for exercising the library locally.
License
This project is licensed under the GNU General Public License v3.0.
Happy coding! 🚀🌐📚
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- EarthCountriesInfo (>= 10.1.0)
- HumanLanguages (>= 10.2.0)
- Meyn.Utilities (>= 10.0.1)
- Microsoft.AspNetCore.OpenApi (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Microsoft.OpenApi (>= 2.11.0)
- MongoDbService (>= 10.0.0)
- MongoDbTokenManager (>= 10.1.0)
- Plivo (>= 5.52.2)
- SharpCompress (>= 0.50.0)
- Snappier (>= 1.3.1)
- Twilio (>= 7.14.9)
- uSignIn.CommonSettings (>= 10.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on SMSwitch:
| Package | Downloads |
|---|---|
|
EmailSwitch
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.2.1 | 44 | 7/16/2026 |
| 10.2.0 | 44 | 7/16/2026 |
| 10.1.0 | 284 | 11/25/2025 |
| 10.0.0 | 299 | 6/28/2025 |
| 9.2.0 | 323 | 4/16/2025 |
| 9.1.0 | 290 | 4/15/2025 |
| 9.0.0 | 285 | 4/15/2025 |
| 8.3.1 | 284 | 4/13/2025 |
| 8.3.0 | 294 | 4/2/2025 |
| 8.2.0 | 258 | 4/2/2025 |
| 8.1.0 | 432 | 1/8/2025 |
| 8.0.0 | 183 | 1/8/2025 |
| 7.0.0 | 288 | 8/11/2024 |
| 6.0.6 | 207 | 8/2/2024 |
| 6.0.5 | 184 | 8/2/2024 |
| 6.0.4 | 268 | 7/30/2024 |
| 6.0.3 | 221 | 7/30/2024 |
| 6.0.2 | 204 | 7/29/2024 |
| 6.0.1 | 421 | 7/21/2024 |
| 6.0.0 | 223 | 7/21/2024 |