| Crates.io | nntp-rs |
| lib.rs | nntp-rs |
| version | 0.1.1 |
| created_at | 2026-01-22 10:15:34.815277+00 |
| updated_at | 2026-01-22 10:17:32.35663+00 |
| description | High-performance async NNTP client with compression and connection pooling |
| homepage | |
| repository | https://github.com/jvz-devx/nntp-rs |
| max_upload_size | |
| id | 2061273 |
| size | 1,186,588 |
High-performance async NNTP client library for Rust with compression and connection pooling.
Scope: This library is designed for reading and downloading from Usenet/NNTP servers (client-to-server). Server-to-server peering and article posting are out of scope.
Add to your Cargo.toml:
[dependencies]
nntp-rs = "0.1"
use nntp_rs::{NntpClient, ServerConfig};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ServerConfig::tls("news.example.com", "username", "password");
let mut client = NntpClient::connect(Arc::new(config)).await?;
client.authenticate().await?;
// Enable compression (optional, but recommended)
client.try_enable_compression().await?;
// Select a newsgroup
let (count, first, last) = client.select_group("alt.test").await?;
println!("Group has {} articles ({}-{})", count, first, last);
// Fetch article overview data
let entries = client.fetch_xover(&format!("{}-{}", last - 10, last)).await?;
for entry in entries {
println!("{}: {}", entry.article_number, entry.subject);
}
Ok(())
}
use nntp_rs::{NntpPool, ServerConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ServerConfig::tls("news.example.com", "username", "password");
// Create pool with 10 connections
let pool = NntpPool::new(config, 10).await?;
// Get connection from pool (automatically authenticated with compression)
let mut conn = pool.get().await?;
let (count, _, _) = conn.select_group("alt.test").await?;
println!("Group has {} articles", count);
// Connection returns to pool when dropped
Ok(())
}
This library supports two compression modes with automatic fallback:
Compression is automatically negotiated when using the connection pool, or can be manually enabled:
let enabled = client.try_enable_compression().await?;
if enabled {
let (compressed, decompressed) = client.get_bandwidth_stats();
println!("Saved {} bytes", decompressed - compressed);
}
nntp-rs uses modern TLS with strong security defaults:
// Secure connection (recommended)
let config = ServerConfig::tls("news.example.com", "username", "password");
// Plaintext connection (not recommended)
let config = ServerConfig::plain("news.example.com", "username", "password");
nntp-rs provides comprehensive article parsing with validation and international character support:
use nntp_rs::{Article, ValidationConfig};
// Parse an article
let article = Article::parse(article_text)?;
// Access headers
println!("From: {}", article.headers.from);
println!("Subject: {}", article.headers.subject); // RFC 2047 encoded words automatically decoded
println!("Message-ID: {}", article.headers.message_id);
// Validate article format
let config = ValidationConfig::strict();
article.headers.validate(&config)?;
// Check MIME type
if article.is_mime() {
println!("Content-Type: {:?}", article.content_type());
println!("Charset: {:?}", article.charset());
}
// Parse path
let servers = article.headers.parse_path();
println!("Article routed through {} servers", servers.len());
| RFC | Title | Status | Test Coverage |
|---|---|---|---|
| RFC 3977 | NNTP Core Protocol | Reader commands | ~600 tests |
| RFC 4642 | TLS with NNTP | Implicit TLS only | Verified |
| RFC 4643 | Authentication | USER/PASS + SASL PLAIN | ~100 tests |
| RFC 5536 | Netnews Article Format | Complete | ~156 tests |
| RFC 8054 | Compression | Complete | ~30 tests |
| RFC 8143 | TLS Best Practices | Compliant | Verified |
| RFC 7525 | BCP 195 TLS | Compliant | Verified |
| RFC 8996 | Deprecate TLS 1.0/1.1 | Compliant | Verified |
| RFC 4644 | Streaming Feeds | Out of scope | - |
Total test coverage: ~1,400 tests (>95% real behavioral tests)
Note: RFC 4644 (streaming feeds) is for server-to-server peering and is out of scope for this client library.
This library focuses on client-to-server reading/downloading. The following server-to-server and posting features are intentionally not implemented:
connect(config) - Connect to NNTP serverauthenticate() - Authenticate with username/passwordauthenticate_sasl(mechanism) - SASL authenticationtry_enable_compression() - Enable compression (returns true if successful)select_group(name) - Select a newsgroupfetch_article(id) - Fetch full articlefetch_head(id) - Fetch article headers onlyfetch_body(id) - Fetch article body onlyfetch_xover(range) - Fetch article overview dataquit() - Close connection gracefullynew(config, max_size) - Create pool with default retry configwith_retry_config(config, max_size, retry_config) - Create pool with custom retryget() - Get connection with automatic retryget_no_retry() - Get connection without retrystate() - Get pool statisticsMIT License - see LICENSE for details.