Skip to content

feat: add smtp action - #49

Open
nicosammito wants to merge 85 commits into
mainfrom
feat/#20
Open

nicosammito wants to merge 85 commits into
mainfrom
feat/#20

Conversation

@nicosammito

Copy link
Copy Markdown
Member

Summary

Adds an SMTP action so Hercules flows can send transactional and notification emails (with attachments) through any SMTP server. Implements issue #20, mirroring the existing actions' conventions — specifically the function-only shape of the gls-action and the official-SDK + helpers.ts pattern of the twilio-action.

SDK / schema source (rule 1)

Uses nodemailer ^6.9, the de-facto standard SMTP client for Node.js, for all mail logic (transport creation, sendMail, attachment handling) rather than hand-rolling SMTP. The SMTP_SEND_RESULT data type is modeled directly on nodemailer's SentMessageInfo, and SMTP_ATTACHMENT on nodemailer's attachment object. Every value returned to a flow is validated with zod .parse() before being handed back.

Functions (3)

  • sendEmail(To, Subject, Text, Html?, From?, Cc?, Bcc?, ReplyTo?): SMTP_SEND_RESULT
  • sendEmailWithAttachments(To, Subject, Text, Attachments, Html?, From?, Cc?, Bcc?): SMTP_SEND_RESULT
  • createAttachment(Filename, Content, ContentType?, Encoding?): SMTP_ATTACHMENT — util builder (mirrors GLS create* utils)

To/Cc/Bcc accept comma-separated address lists. Errors are wrapped in RuntimeError with stable codes (MISSING_SMTP_HOST, INVALID_SMTP_PORT, MISSING_SMTP_SENDER, ERROR_SENDING_EMAIL).

Data types (3)

SMTP_SEND_RESULT, SMTP_ENVELOPE, SMTP_ATTACHMENT — one zod schema per file with @Identifier/@Name/@Schema decorators.

Triggers

None. SMTP is a send-only protocol, so — like gls-action — this action registers no events. (Inbound mail would require IMAP/POP3 and is out of scope for this issue.)

Config

host (required), port (default 587), secure (default false), username, password, from_address — all TEXT ConfigurationDefinitions on the Action, following the GLS/Twilio pattern. No provider-specific ENV vars beyond the shared HERCULES_* are required.

Registration

  • Added smtp-action to the .node-actions list in .gitlab-ci.yml.
  • Added an SMTP row to the "Available Actions" table in the root README.md.
  • Added a per-action README.md documenting config, functions, data types, and provider setup (Gmail app passwords, port/secure pairing, etc.).

Validation

Run in actions/smtp-action/:

  • npm install — OK (188 packages)
  • npm run typecheck — ✅ PASS (0 errors; typechecks against the real nodemailer / @types/nodemailer types)
  • npm run build — ✅ PASS (dist/index.js, 19.91 kB)
  • npm run test — ✅ PASS (4/4 vitest specs)

Notes / choices (autonomous run)

  • @types/nodemailer was added to devDependencies (nodemailer ships no bundled types). This is a small, necessary deviation from the otherwise-identical devDependency set.
  • package-lock.json is not included in this commit (too large to include via the automation). The CI test-node job runs npm ci, which requires it — please run npm install in actions/smtp-action/ and commit the lockfile before merge. The Dockerfile uses npm install, so the image build is unaffected.
  • Files were pushed in two commits (source/config, then registration) rather than one, due to payload-size limits of the push tooling.

⚠️ AI-generated — needs human review before merging.

Closes #20

claude and others added 9 commits July 23, 2026 12:53
Introduce a new stripe-action to the monorepo following the existing
Hercules action conventions (see gls-action, shopify-action).

v1 scope (payments core):
- Functions: createCustomer, createPaymentIntent, retrievePaymentIntent,
  createRefund
- Events: payment_intent.succeeded, charge.refunded (generic Rest webhook
  receiver, same pattern as shopify/woocommerce)
- Data types: STRIPE_CUSTOMER, STRIPE_PAYMENT_INTENT, STRIPE_REFUND plus the
  two webhook payload types
- Config: secret_key, api_version (optional), webhook_secret (optional)

All Stripe API calls go through the official `stripe` Node.js SDK via a
cached client in helpers.ts. Registers the action in .gitlab-ci.yml's
.node-actions matrix and adds it to the README actions table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuCVuBVi48HKcY6E8okUD9
`typescript` is not a field on Stripe.StripeConfig; drop it from the
client options in helpers.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuCVuBVi48HKcY6E8okUD9
The webhook payload files declared both an `export type` and an
`export class` with the same name (StripePaymentIntentSucceededWebhookPayload
and StripeChargeRefundedWebhookPayload), which triggers TS2300
"Duplicate identifier". A class already introduces a type, so the alias
collides. The alias was unused (events reference the name via the
@Signature string and index.ts imports the class), so remove it, matching
the woocommerce/shopify webhook payload convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuCVuBVi48HKcY6E8okUD9
Set up the openapi-zod-client pipeline used by woocommerce-action and
shopware-action so the Stripe data type schemas can be generated from
Stripe's official OpenAPI spec instead of maintained by hand:

- generate:stripe-schemas npm script (download spec3.sdk.json -> filter ->
  openapi-zod-client -> patch)
- scripts/filterStripeSpec.mjs reduces the ~6MB spec to the resources the
  action exposes (customer, payment_intent, refund, charge), stubbing
  foreign $refs to keep the generator tractable
- scripts/patchGeneratedSchemas.mjs applies the zod v4 record + z.lazy
  fix-ups
- openapi-zod-client devDependency
- README documents how to run generation and switch data types over

The hand-written schemas remain the active source until the generator is
run in an environment with network access to registry.npmjs.org and the
spec host, so the build stays green in the meantime.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuCVuBVi48HKcY6E8okUD9
Wire the @Schema data types to the zod schemas generated from Stripe's
official OpenAPI spec (src/generated/stripe-schemas.ts) instead of the
hand-written ones, matching the twilio-action pattern:

- STRIPE_CUSTOMER      -> schemas.customer
- STRIPE_PAYMENT_INTENT-> schemas.payment_intent
- STRIPE_REFUND        -> schemas.refund
- charge.refunded webhook data.object -> schemas.charge

The payment_intent.succeeded webhook wraps StripePaymentIntentSchema, which
now resolves to schemas.payment_intent, so it uses the generated type too.
README updated to describe the schemas as generated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuCVuBVi48HKcY6E8okUD9
… package-lock.json with new peer dependencies
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

GitLab Pipeline Action

General information

Link to pipeline: https://gitlab.com/code0-tech/development/centaurus/-/pipelines/2848028992

Status: Passed
Duration: 9 minutes

Job summaries

docs:preview

Documentation preview available at https://code0-tech.gitlab.io/-/development/telescopium/-/jobs/16491779670/artifacts/out/index.html

@raphael-goetz
raphael-goetz self-requested a review September 11, 2026 18:12
@raphael-goetz

Copy link
Copy Markdown
Member

@nicosammito @MarlonLange lets make a meeting for the review of this RP. We should get this merged asap

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.

Create SMTP Action

4 participants