Skip to content

seemsindie/pidgn_mailer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pidgn_mailer

Email sending library for the pidgn web framework.

License: MIT Zig

A pluggable email delivery library built on the adapter pattern. Ships with adapters for SMTP, SendGrid, Mailgun, and several development/testing helpers. Supports MIME multipart, attachments, rate limiting, and telemetry hooks.

Features

  • Adapter pattern -- compile-time validated interface with init, deinit, and send
  • SMTP adapter -- direct SMTP delivery with STARTTLS and authentication
  • SendGrid adapter -- SendGrid v3 REST API integration
  • Mailgun adapter -- Mailgun REST API with multipart form encoding
  • Dev adapter -- in-memory ring buffer with a web UI for local development
  • Log adapter -- prints emails to stderr, always returns success
  • Test adapter -- in-memory store with assertion helpers (allSentCount, lastSentSubject, sentToAddress)
  • Email composition -- to, cc, bcc, reply-to, text/HTML bodies, attachments, custom headers
  • Attachments -- binary content with content type, disposition (inline or attachment), and content ID
  • Rate limiting -- token-bucket rate limiter with configurable max-per-second
  • Telemetry -- event hooks for email_sending, email_sent, email_failed, and rate_limited

Quick Start

Sending with SMTP

const pidgn_mailer = @import("pidgn_mailer");
const Mailer = pidgn_mailer.Mailer;
const SmtpAdapter = pidgn_mailer.SmtpAdapter;
const Email = pidgn_mailer.Email;

var mailer = Mailer(SmtpAdapter).init(.{
    .adapter = .{
        .host = "smtp.example.com",
        .port = 587,
        .username = "user",
        .password = "pass",
        .use_starttls = true,
    },
});
defer mailer.deinit();

const email = Email{
    .from = .{ .email = "noreply@example.com", .name = "My App" },
    .to = &.{.{ .email = "user@example.com" }},
    .subject = "Welcome!",
    .text_body = "Thanks for signing up.",
    .html_body = "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
};

const result = mailer.send(email, allocator);
if (!result.success) {
    std.log.err("Send failed: {s}", .{result.error_message orelse "unknown"});
}

Sending with SendGrid

var mailer = Mailer(pidgn_mailer.SendGridAdapter).init(.{
    .adapter = .{ .api_key = "SG.your-api-key" },
});
defer mailer.deinit();

_ = mailer.send(email, allocator);

Sending with Mailgun

var mailer = Mailer(pidgn_mailer.MailgunAdapter).init(.{
    .adapter = .{
        .api_key = "key-your-api-key",
        .domain = "mg.example.com",
    },
});
defer mailer.deinit();

_ = mailer.send(email, allocator);

Development Adapter

The dev adapter stores emails in memory so you can inspect them through a web UI during local development.

var mailer = Mailer(pidgn_mailer.DevAdapter).init(.{});
defer mailer.deinit();

_ = mailer.send(email, allocator);

// Query stored emails
const count = mailer.adapter.sentCount();
const stored = mailer.adapter.getEmail(0).?;
std.debug.print("Subject: {s}\n", .{stored.getSubject()});

Test Adapter

test "sends welcome email" {
    var mailer = Mailer(pidgn_mailer.TestAdapter).init(.{});
    defer mailer.deinit();

    _ = mailer.send(email, std.testing.allocator);

    try std.testing.expectEqual(@as(usize, 1), mailer.adapter.allSentCount());
    try std.testing.expectEqualStrings("Welcome!", mailer.adapter.lastSentSubject().?);
    try std.testing.expect(mailer.adapter.sentToAddress("user@example.com"));
}

Rate Limiting

var mailer = Mailer(SmtpAdapter).init(.{
    .adapter = .{ .host = "smtp.example.com" },
    .rate_limit = .{ .max_per_second = 10.0 },
});

Telemetry

var telemetry = pidgn_mailer.Telemetry{};
telemetry.attach(&myHandler);

var mailer = Mailer(SmtpAdapter).init(.{ .adapter = .{} });
mailer.telemetry = &telemetry;

Adapters

Adapter Use Case Config
SmtpAdapter Production SMTP delivery host, port, username, password, use_starttls
SendGridAdapter SendGrid v3 API api_key
MailgunAdapter Mailgun API api_key, domain
DevAdapter Local development with web UI (none)
LogAdapter Debug logging to stderr prefix
TestAdapter Unit test assertions (none)

Building

zig build        # Build
zig build test   # Run tests

Documentation

Full documentation available at docs.pidgn.indielab.link under the Mailer section.

Ecosystem

Package Description
pidgn.zig Core web framework
pidgn_db Database ORM (SQLite + PostgreSQL)
pidgn_jobs Background job processing
pidgn_mailer Email sending
pidgn_template Template engine
pidgn_cli CLI tooling

Requirements

  • Zig 0.16.0-dev.2535+b5bd49460 or later

License

MIT License -- Copyright (c) 2026 Ivan Stamenkovic

About

Email delivery for Zig - templates, attachments, and multi-provider support

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages