Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Platform email: outbound-only custom domain for an apex whose MX belongs to another provider

オープン
#510 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript

調査の方向性

Start with connection-service.ts and connection-schema.ts, then trace the setup steps and outbound refusal handling described in the issue. Check the migration and compatibility digest flow, operator route and CLI entry points, and the named integration tests. Done means outbound-only routes can send without enabling inbound routing, existing managed routes retain their behavior, and the CLI, documentation, status, and sync handle the new mode.

索引モデルが issue の本文から書いたものです。

説明

Use case

We run a self-hosted Void platform serving several brands whose apex domains use Microsoft 365 for mail. Each brand wants its apps to send as [email protected], with the brand's existing mailboxes left alone. Inbound mail for that address must keep going to Microsoft 365; Void should never receive it.

Today the only ways to send from a custom domain on the platform are to give Void the whole apex (including inbound) or to use the shared sender domain. For these brands the first is impossible and the second changes the visible sender address. The same applies to apexes hosted on Google Workspace.

Problem

Platform-managed custom domains are all-or-nothing:

  • Registration refuses any apex that has MX records, including Cloudflare's own Email Routing MX on a fresh assignment: connection-service.ts L1459-L1474 ("already has MX records; use an unused domain apex or a platform shared email address").
  • Even without that check, setup enables Email Routing and a catch-all for the apex (SETUP_STEPS, L104-L115: routing_enable, catchall_ensure, inbound_probe, ...). Enabling Email Routing makes Cloudflare publish its own MX records, which would collide with the mailbox provider's.

The refusal is the right default for inbound. The gap is that there is no way to say "outbound only": Email Sending onboarding and the sender check do not need inbound at all.

Proposal

Add a per-route inbound mode, additive and defaulting to today's behaviour:

  • email_domain_routes.inbound_mode text not null default 'managed', with values 'managed' | 'none', through a new additive migration. drizzle/compatibility.json records schema digests, so it would need the usual entry.
  • For inbound_mode = 'none', setup runs ['sending_onboard', 'publish']. It skips the MX/routing preflight, routing_enable, catchall_ensure, inbound_probe and the ingress and secret steps.
  • Admin-only, since the domain's mail then lives outside Void's checks. CLI: void platform email domain-add <apex> --project <slug> --outbound-only. Owner-managed registration is unchanged.
  • The Email Sending refusal path must change for these routes. Today a definitive refusal from Cloudflare is downgraded to outbound_status = 'verified_only' and setup continues (connection-service.ts L3265-L3303). That fallback makes sense when inbound is the point of the domain. For an outbound-only route it would leave a domain that can send only to verified recipients and does nothing else, so the operation should fail with the refusal instead.
  • Inbound stays closed without extra code. requireCurrentReceiptRoute requires route.inbound_status === 'ready' (admission.ts L885), and an outbound-only route never leaves pending. Sender admission already needs only an active route owned by the project, outbound_status of ready or verified_only, a healthy connection and a usable credential (admission.ts L392-L407), so it should work unchanged.

Touchpoints I would expect, with tests:

  • platform/packages/api/src/email/connection-schema.ts (column), a new drizzle/00NN_*.sql migration, and compatibility.json.
  • connection-service.ts: step selection, preflight bypass, and the sending_onboard failure mode. Also status and sync for these routes, so a missing inbound is not reported as an error.
  • domain-service.ts and the operator route and CLI (operator-args.ts, operator-cmd.ts), plus docs/reference/cli/platform-email.md and docs/guide/platform/administration/email.md, as AGENTS.md asks for new CLI flags.
  • Integration tests in email-connections.test.ts, email-admission.test.ts and operator-email-domains.test.ts, plus the migration/upgrade-compatibility unit test.

Happy to send a PR for this if the direction is acceptable.

Questions for maintainers

  1. Is inbound_mode: 'managed' | 'none' the shape you would want, or would you model it differently (for example a separate route kind)?
  2. Should owner-managed routes (the void email domain add flow) get this too, or should it stay administrator-only?
  3. DMARC handling on a fresh apex: a Microsoft 365 apex usually already publishes SPF and DMARC records, and the guide notes that existing DMARC or bounce-domain records can block Email Sending onboarding. Should the operation fail with a checklist, or is there a supported way to coexist? We would rather fail loudly than send unauthenticated mail.
  4. Should outbound-only also accept a subdomain of the zone? Custom inbound needs the apex because of the catch-all, but sending does not.

Related: #509 (the docs/behaviour mismatch for apexes with foreign MX).

主要言語
TypeScript
スター
402
フォーク
32
平均マージ
11時間 52分
マージ済み PR(30日)
88

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

voidzero-dev/void のほかの issue

voidzero-dev/void の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。