Skip to content

Lettermint transport#23

Merged
dahlia merged 14 commits into
mainfrom
transports/lettermint
May 18, 2026
Merged

Lettermint transport#23
dahlia merged 14 commits into
mainfrom
transports/lettermint

Conversation

@dahlia

@dahlia dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds a new Lettermint transport package for Upyo, available as @upyo/lettermint.

The new package in packages/lettermint includes configuration helpers, message conversion, HTTP API delivery, idempotency keys, retry handling, timeout handling, and batch sending. It also includes cross-runtime unit tests and optional E2E tests guarded by Lettermint environment variables.

The implementation preserves Upyo attachment MIME types when converting to Lettermint’s content_type field, retries internal request timeouts according to the configured retry count, and streams sendMany() input in 500-message chunks instead of buffering the whole iterable before sending.

Documentation

This also documents the transport in packages/lettermint/README.md and docs/transports/lettermint.md, adds it to the root package list in README.md, wires it into the VitePress navigation in docs/.vitepress/config.mts, and records the change in CHANGES.md.

Verification

  • deno task -c packages/lettermint/deno.json test-all
  • deno task check
  • cd docs && pnpm build

Add a new @upyo/lettermint package with configuration helpers,
message conversion, HTTP API delivery, batching, retry handling, and
cross-runtime tests.  The transport preserves attachment MIME types,
retries provider request timeouts, and streams sendMany() input in
Lettermint-sized chunks.

Document the new transport in the package README, the VitePress docs,
the root package table, and CHANGES.md, and wire it into the workspace
and documentation build.

Fixes #22

Assisted-by: Codex:gpt-5.5
@dahlia dahlia added this to the Upyo 0.5.0 milestone May 17, 2026
@dahlia dahlia self-assigned this May 17, 2026
@dahlia dahlia added the enhancement New feature or request label May 17, 2026
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@codecov

codecov Bot commented May 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.61525% with 83 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.57%. Comparing base (50b9f2d) to head (30581a9).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/lettermint/src/http-client.ts 77.07% 30 Missing and 17 partials ⚠️
packages/lettermint/src/lettermint-transport.ts 88.69% 9 Missing and 10 partials ⚠️
packages/lettermint/src/message-converter.ts 93.00% 7 Missing and 3 partials ⚠️
packages/lettermint/src/test-utils/test-config.ts 84.09% 5 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #23      +/-   ##
==========================================
+ Coverage   75.80%   76.57%   +0.77%     
==========================================
  Files          76       81       +5     
  Lines        6767     7344     +577     
  Branches     1065     1205     +140     
==========================================
+ Hits         5130     5624     +494     
- Misses       1310     1361      +51     
- Partials      327      359      +32     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding support for the Lettermint transactional email provider to the Upyo library. The implementation includes a LettermintTransport class that handles single and batch sends, idempotency, and provider-specific features like routes and metadata. Feedback focuses on simplifying the sendMany implementation, improving reliability by retrying on rate-limit errors (HTTP 429), ensuring RFC 5322 compliance by escaping backslashes in email addresses, and optimizing performance by moving the standard headers set to a module-level constant.

Comment thread packages/lettermint/src/lettermint-transport.ts Outdated
Comment thread packages/lettermint/src/http-client.ts Outdated
Comment thread packages/lettermint/src/message-converter.ts Outdated
Comment thread packages/lettermint/src/message-converter.ts
Retry rate-limited Lettermint responses so transient 429 errors follow the configured retry policy.  Also simplify sendMany() to use one async iteration path, escape backslashes in display names, and reuse the standard-header set across message conversions.

#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, providing a transport implementation for the Lettermint HTTP API with support for single and batch sends, idempotency, and tracking settings. The review feedback identifies several technical improvements, including simplifying signal combination using native AbortSignal.any, addressing a memory leak in the sleep utility by ensuring event listeners are removed, and optimizing base64 encoding for attachments to improve performance.

Comment thread packages/lettermint/src/http-client.ts
Comment thread packages/lettermint/src/http-client.ts
Comment thread packages/lettermint/src/message-converter.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4973b6e8f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/lettermint/src/http-client.ts Outdated
Comment thread packages/lettermint/src/http-client.ts
dahlia added 2 commits May 17, 2026 16:58
Exercise Lettermint attachment delivery alongside the existing text, HTML, and batch scenarios.  The E2E tests now run serially, wait briefly between API calls, and include API error details when a real delivery attempt fails.

Assisted-by: Codex:gpt-5.5
Pass the Lettermint API token, sender, and recipient secrets into
the Node, Deno, and Bun test jobs so the Lettermint transport integration
tests run when those secrets are configured.

Assisted-by: Codex:gpt-5.5
@dahlia dahlia force-pushed the transports/lettermint branch from 10cb46c to c1602ae Compare May 17, 2026 08:15
Remove the unsupported Lettermint validateSsl option instead of
advertising a setting that standard fetch cannot honor portably.  The
HTTP client now relies on AbortSignal.any for combined request signals
and removes retry backoff abort listeners when timers settle.

#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

Collect base64 output characters in an array and join once at the end.
This avoids repeated intermediate string allocation for larger
attachments while preserving the encoded output.

#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding support for the Lettermint transactional email provider to the Upyo library. The implementation includes the LettermintTransport class, comprehensive configuration handling, and a message converter that supports single and batch sending, idempotency, and attachments. Feedback focuses on ensuring runtime compatibility by increasing the minimum Node.js version to 20.3.0 to support AbortSignal.any() and optimizing the Base64 encoding logic to improve performance when handling large attachments.

Comment thread packages/lettermint/package.json
Comment thread packages/lettermint/src/message-converter.ts

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding a new transport for the Lettermint HTTP API to the Upyo email library. The implementation supports single and batch sending, idempotency keys, attachments, and provider-specific settings such as routes and tracking. Feedback indicates a compatibility issue where AbortSignal.any() requires a higher Node.js version than the minimum specified in package.json. Additionally, it is recommended to improve error handling in batch sends to ensure that a single message conversion failure does not invalidate the entire batch or result in misleading error reports.

Comment thread packages/lettermint/src/http-client.ts Outdated
Comment thread packages/lettermint/src/lettermint-transport.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Keep the Lettermint package compatible with its declared Node 20.0
runtime floor by using a cleanup-aware fallback when AbortSignal.any is
not available.  Batch conversion now reports per-message conversion
errors instead of failing the whole chunk before valid messages are sent.

#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, providing a new transport implementation for the Lettermint HTTP API. The implementation supports single and batch email sending, idempotency, attachments, and provider-specific features like routes and tracking settings. Documentation and extensive tests have also been added. Review feedback suggests improving the robustness of idempotency key handling by ensuring empty strings are treated as missing values and enhancing cross-runtime compatibility by using globalThis.crypto for UUID generation.

Comment thread packages/lettermint/src/lettermint-transport.ts Outdated
Comment thread packages/lettermint/src/lettermint-transport.ts Outdated
Comment thread packages/lettermint/src/message-converter.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e73db5d27a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/lettermint/src/lettermint-transport.ts Outdated
Treat empty idempotency keys as missing so Lettermint requests always
receive a usable generated key.  Generate keys through globalThis.crypto
when available, then fall back to the timestamp and random string path.

#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Map Lettermint responses through a shared receipt helper so statuses that
already indicate non-delivery produce failed receipts even when the API
includes a message ID.  This keeps single and batch sends from reporting
suppressed, rejected, blocked, bounced, or failed messages as successful.

#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding a new transport implementation for the Lettermint HTTP API. The implementation supports single and batch message sending, idempotency, and provider-specific features such as routes and tracking. Feedback focuses on enhancing the reliability and performance of the transport by adding jitter to the exponential backoff logic, including HTTP 408 errors in the retry mechanism, and utilizing native Base64 encoding instead of a manual implementation.

Comment thread packages/lettermint/src/http-client.ts Outdated
Comment thread packages/lettermint/src/message-converter.ts
Comment thread packages/lettermint/src/http-client.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3ff4dcd33a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/lettermint/src/lettermint-transport.ts
Comment thread packages/lettermint/src/lettermint-transport.ts Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding a new transport for the Lettermint transactional email service. The implementation includes a LettermintTransport class supporting single and batch sends, idempotency, and provider-specific features such as routes and tracking settings. Feedback recommends enhancing the retry logic with jitter to prevent thundering herd issues, optimizing base64 encoding for attachments using native Buffer methods, and simplifying the idempotency key generation by relying on the globally available Web Crypto API.

Comment thread packages/lettermint/src/http-client.ts Outdated
Comment thread packages/lettermint/src/message-converter.ts
Comment thread packages/lettermint/src/message-converter.ts
Add jitter to retry backoff and retry HTTP 408 responses so transient
request timeouts follow the same recovery path as rate limits and server
errors.  Preserve caller cancellation as AbortError and keep local batch
validation failures when the remote batch request fails.

Attachment encoding now uses chunked native btoa, which avoids the manual
base64 table while remaining portable across Deno, Node.js, Bun, and edge
runtimes.  Idempotency keys now rely directly on Web Crypto randomUUID.

#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, providing a new transport for the Lettermint email service. The implementation includes the LettermintTransport class, a dedicated HTTP client with exponential backoff retry logic, and a message converter to map Upyo messages to the Lettermint API format. Feedback focuses on ensuring unique idempotency keys when chunking batch requests to prevent unintended deduplication, optimizing the base64 conversion to avoid inefficient string concatenation in loops, and refining the retry logic to exclude non-transient status codes like 3xx redirections.

Comment thread packages/lettermint/src/lettermint-transport.ts
Comment thread packages/lettermint/src/message-converter.ts
Comment thread packages/lettermint/src/http-client.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e24eb98e76

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/lettermint/src/lettermint-transport.ts
Preserve per-message idempotency in sendMany by sending keyed chunks
through the single-message endpoint, where each message can keep its own
Idempotency-Key header.  Unkeyed chunks still use Lettermint batch
requests with generated request keys.

Tighten retry classification so only transient HTTP statuses are retried,
and avoid repeated string concatenation while building base64 attachment
payloads.

#23 (comment)
#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding support for the Lettermint transactional email provider to the Upyo library. The implementation includes a LettermintTransport class, an HTTP client with retry logic and idempotency support, and a message converter that handles attachments and provider-specific features like routes and tags. Documentation and project-wide configurations have been updated to reflect the new transport. Feedback from the review suggests optimizing the base64 encoding of attachments by using the Buffer API and improving URL construction to handle potential trailing slashes in the base URL configuration.

Comment thread packages/lettermint/src/message-converter.ts
Comment thread packages/lettermint/src/http-client.ts
Comment thread packages/lettermint/src/http-client.ts
Normalize configured Lettermint base URLs once while resolving config so
single and batch send endpoints do not inherit trailing slash artifacts.

Prefer native Uint8Array base64 encoding when the runtime provides it, while
keeping the chunked btoa fallback for older runtimes.

#23 (comment)
#23 (comment)
#23 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@dahlia

dahlia commented May 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the @upyo/lettermint package, adding support for the Lettermint transactional email provider. The implementation includes a LettermintTransport class that supports single and batch sending (up to 500 messages), idempotency keys, attachments, and provider-specific features like routes, tags, and tracking settings. Comprehensive documentation and tests (unit and E2E) are also included. I have no feedback to provide as there are no review comments.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

dahlia added 2 commits May 18, 2026 07:46
The CI Deno type definitions already include Uint8Array.toBase64(), so the
previous type guard narrowed the fallback branch to never and failed the
repository check.

Use optional method lookup instead.  This keeps the native path when a runtime
supports it without making the chunked fallback unreachable to newer type
libraries.

https://github.com/dahlia/upyo/actions/runs/25988067832/job/76389109622

Assisted-by: Codex:gpt-5.5
@dahlia dahlia merged commit 2fa973c into main May 18, 2026
12 of 14 checks passed
@dahlia dahlia deleted the transports/lettermint branch May 18, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant