Skip to content

feat: add mailto SMTP support and parity coverage#32

Merged
elibosley merged 1 commit intomainfrom
feat/mailto-support
Jan 31, 2026
Merged

feat: add mailto SMTP support and parity coverage#32
elibosley merged 1 commit intomainfrom
feat/mailto-support

Conversation

@elibosley
Copy link
Copy Markdown
Member

@elibosley elibosley commented Jan 31, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added email notification support via mailto: and mailtos: URL schemes, enabling SMTP-based message delivery with configurable encryption modes, authentication credentials, and multiple recipient fields (to, cc, bcc, reply-to).
  • Tests

    • Added comprehensive test coverage including parity validation between implementations to ensure consistency and reliability of email notifications.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 31, 2026

📝 Walkthrough

Walkthrough

This pull request adds mailto and mailtos URL scheme support for SMTP-based email notifications. It includes a complete SMTP client implementation with TLS/encryption support, schema registration, test infrastructure for SMTP message capture, and comprehensive parity testing against Python Apprise behavior.

Changes

Cohort / File(s) Summary
Core Notification Implementation
internal/cli/cli.go, internal/notify/mailto_target.go, internal/notify/registry_email.go
Adds mailto/mailtos handler in CLI dispatcher, implements MailtoTarget SMTP client with URL parsing, TLS modes (insecure/STARTTLS/SSL), PLAIN authentication, MIME message construction with quoted-printable encoding, and per-recipient delivery. Registers both schemes in email schema map.
Test Infrastructure
internal/testutil/smtp_capture.go, internal/testutil/scripts/capture_smtp.py
Introduces lightweight TCP-based SMTP server for test message capture with thread-safe access, and Python CLI wrapper for Apprise SMTP testing to enable cross-language parity validation.
Parity Testing
internal/parity/mailto_parity_test.go, internal/parity/non_http_schemas.go
Adds comprehensive parity test comparing Go mailto sender against Python Apprise SMTP behavior, including header parsing, content-transfer-encoding decoding, and message normalization. Provides helper for identifying non-HTTPS schemas.
Test Adjustments
internal/parity/e2e_parity_test.go, internal/parity/e2e_schema_exercise_test.go, internal/parity/provider_coverage_test.go
Adds guards to skip non-HTTPS schemas in three existing test suites, excluding mailto/mailtos from HTTPS-only test coverage.

Sequence Diagram

sequenceDiagram
    participant Client
    participant MailtoTarget
    participant SMTPConn as SMTP Connection
    participant SMTPServer as SMTP Server

    Client->>MailtoTarget: Send(body, title)
    MailtoTarget->>MailtoTarget: Parse mailto URL
    MailtoTarget->>MailtoTarget: Extract host, port, credentials<br/>from, to, cc, bcc, reply-to
    MailtoTarget->>SMTPConn: Dial SMTP server
    SMTPConn->>SMTPServer: TCP connect
    SMTPServer-->>SMTPConn: 220 SMTP ready
    
    MailtoTarget->>SMTPConn: Send EHLO
    SMTPServer-->>SMTPConn: 250 capabilities
    
    alt Use STARTTLS or SSL
        MailtoTarget->>SMTPConn: Upgrade TLS
        SMTPConn->>SMTPServer: STARTTLS/SSL handshake
        SMTPServer-->>SMTPConn: TLS established
    end
    
    alt Credentials provided
        MailtoTarget->>SMTPConn: AUTH PLAIN
        SMTPServer-->>SMTPConn: 235 authenticated
    end
    
    loop For each recipient
        MailtoTarget->>MailtoTarget: Build MIME message<br/>(subject, from, to, headers, body)
        MailtoTarget->>SMTPConn: MAIL FROM
        MailtoTarget->>SMTPConn: RCPT TO
        MailtoTarget->>SMTPConn: DATA + message payload
        SMTPServer-->>SMTPConn: 250 Message queued
    end
    
    MailtoTarget->>SMTPConn: QUIT
    SMTPConn->>SMTPServer: Close connection
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A rabbit's hop through SMTP's gate,

With mailto schemes configured just right,

TLS secured, credentials slate,

MIME-compliant messages take flight! ✉️

Parity tested from Python to Go,

This notification path steals the show! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding mailto SMTP support with parity test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/mailto-support

Comment @coderabbitai help to get the list of available commands and usage tips.

@elibosley elibosley changed the title Add mailto SMTP support and parity coverage feat: add mailto SMTP support and parity coverage Jan 31, 2026
@elibosley elibosley linked an issue Jan 31, 2026 that may be closed by this pull request
@elibosley elibosley merged commit d23bcf0 into main Jan 31, 2026
17 of 18 checks passed
@elibosley elibosley deleted the feat/mailto-support branch January 31, 2026 21:28
@knope-bot knope-bot Bot mentioned this pull request Jan 31, 2026
elibosley pushed a commit that referenced this pull request Jan 31, 2026
> [!IMPORTANT]
> Merging this pull request will create this release

## Features

- add mailto SMTP support and parity coverage (#32)

Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unsupported services

1 participant