docs: add README and register it in Cargo.toml

This commit is contained in:
2026-04-29 18:44:08 -05:00
parent 08ae561bae
commit 645d829193
2 changed files with 122 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
<div align="center">
# plunk-rs
**An async Rust client for [Plunk](https://www.useplunk.com/) transactional email.**
*Send HTML, templates, and template variables (the `data` object) with validation, typed errors, and a small dependency footprint (reqwest + rustls).*
[![License: MIT](https://img.shields.io/badge/License-MIT-5c6bc0.svg)](./LICENSE)
[![crates.io](https://img.shields.io/crates/v/plunk-rs.svg)](https://crates.io/crates/plunk-rs)
[![docs.rs](https://img.shields.io/docsrs/plunk-rs)](https://docs.rs/plunk-rs)
[Repository](https://git.coldspire.com/Antfroze/plunk-rs) · [Plunk API](https://docs.useplunk.com)
</div>
---
## Why this crate
| | |
| :--- | :--- |
| **Focused** | Covers `POST /v1/send`—HTML and template sends, with optional `from`, `reply`, headers, and `data` for template variables. |
| **Validates early** | `Email` and `EmailAddress` are built with checks so bad requests fail before the wire. |
| **Clean boundary** | Wire DTOs stay internal; your code uses `Email`, `SendResponse`, and `Error`. |
| **TLS** | [reqwest](https://crates.io/crates/reqwest) with **rustls**—no OpenSSL at build time. |
## Installation
Add to `Cargo.toml`:
```toml
[dependencies]
plunk-rs = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
```
Or:
```text
cargo add plunk-rs
cargo add tokio --features rt-multi-thread,macros
```
## Quick start
```rust
use plunk_rs::{Client, Email, EmailAddress};
#[tokio::main]
async fn main() -> Result<(), plunk_rs::Error> {
let client = Client::new("sk_your_plunk_api_key")?;
let email = Email::html("user@example.com", "Welcome", "<h1>Hello</h1>")?
.from(EmailAddress::named("My app", "hello@yourdomain.com")?)?
.reply_to("support@yourdomain.com")?;
let response = client.send(&email).await?;
for delivery in response.deliveries() {
println!("{}{}", delivery.contact().email(), delivery.id());
}
Ok(())
}
```
**Template send** (with data for the template):
```rust
use plunk_rs::{Client, Email};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), plunk_rs::Error> {
let client = Client::new("sk_your_plunk_api_key")?;
let email = Email::template("user@example.com", "tpl_xxxxxxxx")?
.with_data(json!({ "first_name": "Ada" }))?;
client.send(&email).await?;
Ok(())
}
```
## Self-hosted or custom base URL
```rust
let client = Client::builder("sk_xxx")
.base_url("https://plunk.example.com/api")?
.build()?;
```
`base_url` is normalized: if the path does not end with `/`, one is added so `v1/send` joins correctly.
## API surface
- **`Client` / `ClientBuilder`** — Bearer API key, optional `reqwest::Client` injection.
- **`Email`**, **`EmailAddress`**, **`Recipients`** — Construction helpers for HTML vs template, headers, and JSON `data` (must serialize to a JSON object for templates).
- **`SendResponse`**, **`Delivery`**, **`Contact`** — Parsed success payload from the send response.
- **`Error`**, **`ApiError`**, **`Result<T>`** — Transport, validation, and Plunk error bodies (with status and raw body preserved).
## Requirements
Rust **2024** edition (use a current stable toolchain that supports it). Async code assumes a runtime such as **Tokio**.
## Docs
- [**docs.rs** — plunk-rs](https://docs.rs/plunk-rs)
- [Plunk documentation](https://docs.useplunk.com)
## License
[MIT](LICENSE)
---
<div align="center">
Made for sending mail through [Plunk](https://www.useplunk.com/) without the ceremony.
</div>