Sending SMS in Rust: API Library for Integration with SMS Services

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Sending SMS in Rust: A Complete Guide to Using the API Library



In the modern world of Rust development, sending SMS messages is becoming a standard task for many applications — from two-factor authentication systems to user notifications. In this article, we will thoroughly examine how to implement sending SMS in Rust using the HTTP API, employing popular libraries and approaches.



Why Rust is Ideal for SMS Integration?

Rust offers safe memory management, high performance, and excellent support for asynchronous programming. This makes it a great choice for creating reliable message sending services where stability and request processing speed are critical.



Main Libraries for Working with HTTP in Rust

To interact with SMS providers via REST API, the following crates are most commonly used:

  • reqwest — the most popular HTTP client for Rust. Supports asynchronous and synchronous requests, working with JSON, headers, and authorization.
  • serde — a library for data serialization and deserialization (necessary for processing JSON responses from the API).
  • tokio — an asynchronous runtime required for working with asynchronous reqwest.
  • dotenv — for securely storing API keys and configurations.


Basic Project Structure

Let's start by creating a new project and adding dependencies to Cargo.toml:



[package]name = "sms_sender"version = "0.1.0"edition = "2021"

[dependencies]reqwest = { version = "0.12", features = ["json"] }tokio = { version = "1", features = ["full"] }serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"dotenv = "0.15"


Connecting to an SMS Provider

Most SMS services (e.g., Twilio, Vonage, SMS-Center) provide a REST API. Let's look at a general connection template using a hypothetical provider as an example.



Let's create a .env file to store confidential data:

API_KEY=your_api_key_hereAPI_SECRET=your_api_secret_hereSENDER_NAME=MyApp


Data Structures for Request and Response

Let's define types for working with the API using Serde:



use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize)]struct SmsRequest { api_key: String, to: String, message: String, sender: String,}

#[derive(Debug, Deserialize)]struct SmsResponse { status: String, message_id: Option<String>, error: Option<String>,}


Implementing the SMS Sending Function

Now let's write the main function for sending a message:



use dotenv::dotenv;use std::env;

#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { dotenv().ok();

let api_key = env::var("API_KEY")?; let api_secret = env::var("API_SECRET")?; let sender = env::var("SENDER_NAME")?;

let client = reqwest::Client::new();

let sms_request = SmsRequest { api_key: api_key.clone(), to: "+79123456789".to_string(), message: "Hello! This is a test SMS from a Rust application.".to_string(), sender: sender.clone(), };

let response = client .post("https://api.smsprovider.com/v1/send") .basic_auth(&api_key, Some(&api_secret)) .json(&sms_request) .send() .await?;

let sms_response: SmsResponse = response.json().await?;

if sms_response.status == "success" { println!("SMS sent! ID: {:?}", sms_response.message_id); } else { eprintln!("Sending error: {:?}", sms_response.error); }

Ok(())}


Error Handling and Retries

In real applications, it is important to correctly

Recommendations