@@ -31,6 +31,15 @@ export interface SendingSubdomainProps {
3131 * `string` (not `string`) so it is statically knowable in `diff`.
3232 */
3333 name : string ;
34+ /**
35+ * Whether Cloudflare keeps a preview of each sent message in the activity
36+ * log (retained for about seven days). Subdomains onboarded on or after
37+ * 2026-07-02 start with previews on. Omit to leave the setting as
38+ * Cloudflare has it.
39+ *
40+ * @see https://developers.cloudflare.com/email-service/observability/logs/#message-preview
41+ */
42+ previewEnabled ?: boolean ;
3443}
3544
3645export interface SendingSubdomainAttributes {
@@ -50,6 +59,8 @@ export interface SendingSubdomainAttributes {
5059 dkimSelector : string | undefined ;
5160 /** The return-path domain used for bounce handling. */
5261 returnPathDomain : string | undefined ;
62+ /** Whether sent messages can be previewed in the activity log. */
63+ previewEnabled : boolean | undefined ;
5364 /** ISO8601 creation timestamp. */
5465 created : string | undefined ;
5566 /** ISO8601 last-modified timestamp. */
@@ -73,9 +84,8 @@ export type SendingSubdomain = Resource<
7384 * created automatically and `enabled` flips to `true` once they validate
7485 * (usually immediately).
7586 *
76- * The resource is existence-only: the API offers create, get, list, and
77- * delete but no update, so changing `name` or `zoneId` triggers a
78- * replacement.
87+ * Changing `name` or `zoneId` triggers a replacement; `previewEnabled` is
88+ * updated in place.
7989 *
8090 * Safety: sending subdomains carry no ownership markers. When there is no
8191 * prior state, `read` scans the zone for an existing subdomain with the
@@ -92,6 +102,16 @@ export type SendingSubdomain = Resource<
92102 * // sending.dkimSelector / sending.returnPathDomain — provisioned config
93103 * ```
94104 *
105+ * ### Message previews
106+ * **Example:** Keep no copies of sent messages in the activity log
107+ * ```typescript
108+ * const sending = yield* Cloudflare.Email.SendingSubdomain("Mail", {
109+ * zoneId: zone.zoneId,
110+ * name: "mail.example.com",
111+ * previewEnabled: false,
112+ * });
113+ * ```
114+ *
95115 * ### Externally-hosted zones
96116 * **Example:** Look up the DNS records to create manually
97117 * ```typescript
@@ -123,7 +143,7 @@ export const isSendingSubdomain = (value: unknown): value is SendingSubdomain =>
123143
124144export const SendingSubdomainProvider = ( ) =>
125145 Provider . succeed ( SendingSubdomain , {
126- // No update API exists — every attribute is stable across updates .
146+ // Only `previewEnabled` changes in place .
127147 stables : [ "subdomainId" , "zoneId" , "name" , "dkimSelector" , "returnPathDomain" , "created" ] ,
128148
129149 list : Effect . fn ( function * ( ) {
@@ -154,7 +174,7 @@ export const SendingSubdomainProvider = () =>
154174 diff : Effect . fn ( function * ( { olds = { } , news } ) {
155175 const o = olds as SendingSubdomainProps ;
156176 const n = news as SendingSubdomainProps ;
157- // The API has no update operation — any prop change is a replace .
177+ // `name` and `zoneId` are identity; `previewEnabled` updates in place .
158178 if ( o . name !== undefined && o . name !== n . name ) {
159179 return { action : "replace" } as const ;
160180 }
@@ -223,13 +243,20 @@ export const SendingSubdomainProvider = () =>
223243 ) ;
224244 }
225245
226- // 4. Sync — nothing is mutable; the only convergence left is DNS
227- // validation. Cloudflare auto-creates the records on CF-hosted
246+ // 4. Sync — converge `previewEnabled` when it is declared, then wait
247+ // for DNS validation. Cloudflare auto-creates the records on CF-hosted
228248 // zones but validation is eventually consistent: poll briefly
229249 // for `enabled` to flip, and return the observed state either
230250 // way (an externally-hosted zone stays disabled until the user
231251 // adds the records — that is not a deploy failure).
232- const ensured = observed ;
252+ const ensured =
253+ news . previewEnabled !== undefined && observed . previewEnabled !== news . previewEnabled
254+ ? yield * emailSending . editSubdomain ( {
255+ zoneId,
256+ subdomainId : observed . tag ,
257+ previewEnabled : news . previewEnabled ,
258+ } )
259+ : observed ;
233260 const final = ensured . enabled
234261 ? ensured
235262 : yield * getSubdomain ( zoneId , ensured . tag ) . pipe (
@@ -295,6 +322,7 @@ const toAttributes = (
295322 enabled : subdomain . enabled ,
296323 dkimSelector : subdomain . dkimSelector ?? undefined ,
297324 returnPathDomain : subdomain . returnPathDomain ?? undefined ,
325+ previewEnabled : subdomain . previewEnabled ?? undefined ,
298326 created : subdomain . created ?? undefined ,
299327 modified : subdomain . modified ?? undefined ,
300328} ) ;
0 commit comments