@nxgt/janus-mail 0.9.8 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"template-types.d.ts","sourceRoot":"","sources":["../src/template-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"template-types.d.ts","sourceRoot":"","sources":["../src/template-types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { JanusMailTemplates } from './types';
2
2
  /**
3
- * The twelve default templates, in the locales they are built in. The
3
+ * The thirteen default templates, in the locales they are built in. The
4
4
  * renderer behind them is created on the first render, not here.
5
5
  *
6
6
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAgClD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CA6DnD"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAgClD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CAmEnD"}
package/dist/types.d.ts CHANGED
@@ -44,8 +44,8 @@ interface JanusMailBaseOptions<L extends string> {
44
44
  readonly clock?: Clock;
45
45
  }
46
46
  /**
47
- * What one send of `verifyEmail`, `resetPassword`, `signInCode`, `magicLink`
48
- * or `stepUp` may pass
47
+ * What one send of `verifyEmail`, `resetPassword`, `signInCode`, `magicLink`,
48
+ * `changeEmail` or `stepUp` may pass
49
49
  * besides the flow's answer and the recipient.
50
50
  */
51
51
  export interface JanusMailSendOptions {
@@ -95,6 +95,17 @@ export interface JanusMail<L extends string = JanusMailLocale> {
95
95
  * anything is rendered, when `janusMail()` was given no `links.magicLink`.
96
96
  */
97
97
  magicLink(issued: IssuedToken, to?: Pick<Recipient, 'locale'>, options?: JanusMailSendOptions): Promise<SentMail>;
98
+ /**
99
+ * What `auth.<type>.changeEmail.send(user, newEmail)` answered, to
100
+ * `issued.email` — the NEW address, which the account only moves to when
101
+ * the link is redeemed by `changeEmail.confirm(token)` — greeting
102
+ * `to.name`, its button and fallback link built by
103
+ * `links.changeEmail(issued.token)`, saying how long it stays valid. The
104
+ * former address is told afterwards, by `emailChanged`. A `TypeError`,
105
+ * before anything is rendered, when `janusMail()` was given no
106
+ * `links.changeEmail`.
107
+ */
108
+ changeEmail(issued: IssuedToken, to: Recipient, options?: JanusMailSendOptions): Promise<SentMail>;
98
109
  /**
99
110
  * The code `auth.stepUp.request(user)` answered, once narrowed to
100
111
  * `via: 'email'`, to `issued.email`, greeting `to.name`, saying how long
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/docs/README.md CHANGED
@@ -23,11 +23,11 @@ They mean the same here. These pages add:
23
23
 
24
24
  | Word | Means | Not |
25
25
  | --- | --- | --- |
26
- | **e-mail** | One of the twelve this package sends: `verify-email`, `reset-password`, `sign-in-code`, `magic-link`, `confirm-action`, `password-changed`, `email-changed`, `two-factor-enabled`, `two-factor-disabled`, `recovery-code-used`, `new-sign-in`, `welcome` — by the name of its built file | "mail", "message" — a *message* is what a mailer sends, addressed |
26
+ | **e-mail** | One of the thirteen this package sends: `verify-email`, `reset-password`, `sign-in-code`, `magic-link`, `confirm-action`, `confirm-new-email`, `password-changed`, `email-changed`, `two-factor-enabled`, `two-factor-disabled`, `recovery-code-used`, `new-sign-in`, `welcome` — by the name of its built file | "mail", "message" — a *message* is what a mailer sends, addressed |
27
27
  | **template** | The function that renders one e-mail: `(variables & { locale }) => Rendered`. Named in camelCase, after the method that sends it: `verifyEmail`, `signInCode` | "renderer" — the renderer is `@nxgt/mail`'s, and reads the build |
28
28
  | **default template** | A template of `janusTemplates()`: the prebuilt e-mail, filled by the renderer | "preset" — a preset is `@nxgt/mail-presets`' source, which the build compiles |
29
29
  | **override** | A template of yours, passed in `templates`, used instead of the default | "custom template" |
30
- | **issued** | What a flow answered: an `IssuedToken` from `verifyEmail.send`, `resetPassword.request` or `magicLink.request`, an `IssuedCode` from `signInCode.request`, a `StepUpByEmail` from `stepUp.request` once narrowed to `via: 'email'` | "result", "payload" |
30
+ | **issued** | What a flow answered: an `IssuedToken` from `verifyEmail.send`, `resetPassword.request`, `magicLink.request` or `changeEmail.send`, an `IssuedCode` from `signInCode.request`, a `StepUpByEmail` from `stepUp.request` once narrowed to `via: 'email'` | "result", "payload" |
31
31
  | **recipient** | Who an e-mail is for besides the address: a `Recipient`, `{ name, locale? }` | "user" — a user is a record of `@nxgt/janus`; "to" is the address |
32
32
  | **notice** | An e-mail that tells, and asks for nothing: `passwordChanged`, `emailChanged`, `twoFactorEnabled`, `twoFactorDisabled`, `recoveryCodeUsed`, `newSignIn`. It links to `links.secureAccount()` — `recoveryCodeUsed` to `links.recoveryCodes()` when given | "alert", "notification" |
33
33
  | **welcome** | The e-mail sent once a user was created, on `@nxgt/janus`'s `user.created`: `welcome`. It links to `links.getStarted()` — not a notice, since it warns of nothing | "onboarding", "greeting" |
@@ -55,7 +55,7 @@ packages/janus-mail/
55
55
  `src/generated/mail.ts` (`rendererTypes`), from the build.
56
56
  3. `scripts/build-mail.ts` reads the manifest and **fails unless its
57
57
  format is one every `@nxgt/mail` the peer admits reads** — see below —
58
- and **unless exactly the twelve e-mails were built**: a thirteenth from a new
58
+ and **unless exactly the thirteen e-mails were built**: a fourteenth from a new
59
59
  `@nxgt/mail-presets`, or one missing, stops the build.
60
60
  4. It writes `src/generated/locales.ts` from the manifest's locales, and
61
61
  `src/generated/codes-left.ts` — below — each only when its content
@@ -82,6 +82,7 @@ const templates: JanusMailTemplates<Locale> = {
82
82
  resetPassword: ({ name, link, expiresIn, locale }) => render('reset-password', locale, { name, link, expiresIn }),
83
83
  signInCode: ({ code, expiresIn, locale }) => render('sign-in-code', locale, { code, expiresIn }),
84
84
  magicLink: ({ link, expiresIn, locale }) => render('magic-link', locale, { link, expiresIn }),
85
+ changeEmail: ({ name, link, expiresIn, locale }) => render('confirm-new-email', locale, { name, link, expiresIn }),
85
86
  stepUp: ({ name, code, expiresIn, link, locale }) => render('confirm-action', locale, { name, code, expiresIn, link }),
86
87
  passwordChanged: ({ name, link, locale }) => render('password-changed', locale, { name, link }),
87
88
  emailChanged: ({ name, link, newEmail, locale }) => render('email-changed', locale, { name, link, newEmail }),
@@ -110,7 +111,7 @@ the text of a missing location is held in `en` and `fr` only, so pass
110
111
  where it matters.
111
112
  `recoveryCodeUsed` is the ninth template, since 0.5.0, `magicLink` the
112
113
  tenth, since 0.7.0, `stepUp` the eleventh, since 0.8.0, and `newSignIn` the
113
- twelfth, since 0.9.0: a `templates`
114
+ twelfth, since 0.9.0, and `changeEmail` the thirteenth, since 0.10.0: a `templates`
114
115
  written for an earlier version no longer
115
116
  compiles with a locale beyond `en` and `fr` — add the one it lacks. A
116
117
  renderer over a Maizzle build of your own, with
@@ -119,13 +120,13 @@ With only some templates, the call does not compile — the error lands on
119
120
  `templates`:
120
121
 
121
122
  ```text
122
- TS2740: Type '{ verifyEmail: () => Rendered; }' is missing the following properties from type 'JanusMailTemplates<"en" | "fr" | "de">': welcome, resetPassword, signInCode, magicLink, and 7 more.
123
+ TS2740: Type '{ verifyEmail: () => Rendered; }' is missing the following properties from type 'JanusMailTemplates<"en" | "fr" | "de">': welcome, resetPassword, signInCode, magicLink, and 8 more.
123
124
  ```
124
125
 
125
126
  and in JavaScript it throws when `janusMail()` is called:
126
127
 
127
128
  ```text
128
- TypeError: janusMail: the default templates are built in en and fr only — with another locale in locales, pass every template in templates; resetPassword, signInCode, magicLink, stepUp, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled, recoveryCodeUsed, newSignIn, welcome missing
129
+ TypeError: janusMail: the default templates are built in en and fr only — with another locale in locales, pass every template in templates; resetPassword, signInCode, magicLink, stepUp, changeEmail, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled, recoveryCodeUsed, newSignIn, welcome missing
129
130
  ```
130
131
 
131
132
  A default template is typed for `'en' | 'fr'`, so reusing one in a wider set
@@ -138,4 +139,4 @@ Built-in locales for more languages are on the [roadmap](../roadmap.md).
138
139
 
139
140
  - `@nxgt/mail`'s [locales guide](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail/docs/guide/locales.md)
140
141
  — `pickLocale` and `parseAcceptLanguage` in full.
141
- - [Templates](templates.md) — writing the twelve for a new locale.
142
+ - [Templates](templates.md) — writing the thirteen for a new locale.
@@ -49,6 +49,7 @@ time one is sent, and kept.
49
49
  | `links.secureAccount` | `() => string` | required | Where a user who made no change secures their account: the notices link to it — the new sign-in's included — and so does the step-up's code, for a user who asked for none |
50
50
  | `links.getStarted` | `() => string` | required | Where a new user starts — your home page, or your sign-in page for an account someone else created: the welcome's **Get started** button links to it |
51
51
  | `links.magicLink` | `(token) => string` | none: `magicLink` is a `TypeError` without it | The page a sign-in link opens, given the one-time token. That page spends nothing: its button posts the token to the route that calls `auth.magicLink.confirm` |
52
+ | `links.changeEmail` | `(token) => string` | none: `changeEmail` is a `TypeError` without it | The page that confirms a new address, given the one-time token. That page spends nothing: its button posts the token to the route that calls `auth.<type>.changeEmail.confirm` |
52
53
  | `links.recoveryCodes` | `() => string` | `links.secureAccount` | Where a user regenerates their recovery codes: the recovery code notice links to it, from its **Secure my account** button |
53
54
  | `locales` | `readonly L[]` | `['en', 'fr']` | The locales sent in — see [Locales](locales.md) |
54
55
  | `fallbackLocale` | one of `locales` | `'en'`, else the first of `locales` | The locale when the recipient wants none of `locales` |
@@ -145,6 +146,35 @@ nobody by name — and only its `locale` is read.
145
146
  visitor's secret, and no `token`: the compiler refuses it here, and
146
147
  JavaScript gets `janusMail.magicLink: token must be a string`.
147
148
 
149
+ ### `changeEmail(issued, to, options?)`
150
+
151
+ ```ts
152
+ const issued = await auth.changeEmail.send(user, newEmail); // gate it: assertFresh or a step-up
153
+ await mail.changeEmail(issued, { name: user.name, locale: user.locale });
154
+ ```
155
+
156
+ Sent to `issued.email`, which is the **new** address — the one the account
157
+ moves to, not the one it has — greeting `to.name`: "Confirm your new e-mail
158
+ address", a **Confirm my new address** button to
159
+ `links.changeEmail(issued.token)`, how long it lasts, and "ignore it if this
160
+ was not you: nothing changes". Nothing changes until `auth.changeEmail.confirm`
161
+ redeems the token; then `user.emailChanged` fires and
162
+ [`emailChanged`](#emailchangedto) tells the **former** address. Two
163
+ e-mails, two inboxes, both yours to send.
164
+
165
+ - **`links.changeEmail` is required to send it.** It is optional in
166
+ `janusMail()`, so links written before it keep compiling, and without it
167
+ `changeEmail` throws a `TypeError` —
168
+ `janusMail.changeEmail: links.changeEmail is missing — …` — before anything
169
+ is rendered. There is no fallback: only your page can carry the token.
170
+ - **Link to a page, never to the route that confirms.** Mail scanners open
171
+ every link in an e-mail; one that confirms on `GET` moves the account for
172
+ the scanner. The page's button posts the token to the route calling
173
+ `changeEmail.confirm`.
174
+ - **`verifyEmail` is not this e-mail.** Its link redeems a verification
175
+ (`TOKEN_UNKNOWN` for a change token) and it would tell the new address to
176
+ verify, not that the account moves there.
177
+
148
178
  ### `stepUp(issued, to, options?)`
149
179
 
150
180
  ```ts
@@ -403,7 +433,7 @@ it carries no request to describe the device from.
403
433
 
404
434
  ## The expiry
405
435
 
406
- `verifyEmail`, `resetPassword`, `signInCode`, `magicLink` and `stepUp` say
436
+ `verifyEmail`, `resetPassword`, `signInCode`, `magicLink`, `changeEmail` and `stepUp` say
407
437
  how long the link or the code lasts — "This link expires in 1 hour.", "Ce code expire dans
408
438
  10 minutes." The text is `expiresIn`, one of the template's variables,
409
439
  derived at send time from the flow's `issued.expiresAt`:
@@ -453,6 +483,7 @@ a `TypeError`, and nothing reaches the mailer: revive the date with
453
483
  | `resetPassword` | `issued.email` | the `email` passed to `request` |
454
484
  | `signInCode` | `issued.email` | the `email` passed to `request` |
455
485
  | `magicLink` | `issued.email` | the `email` passed to `request` |
486
+ | `changeEmail` | `issued.email` — the new address | the user's current address |
456
487
  | `stepUp` | `issued.email` | an address the client sent |
457
488
  | `passwordChanged` | `to.email` | — |
458
489
  | `emailChanged` | `to.formerEmail` | `to.newEmail` |
@@ -1,7 +1,7 @@
1
1
  # Templates
2
2
 
3
3
  This page is for changing what an e-mail says or looks like: what a template
4
- is given and answers, replacing some of the twelve, using the defaults on their
4
+ is given and answers, replacing some of the thirteen, using the defaults on their
5
5
  own, and what the defaults say.
6
6
 
7
7
  ```ts
@@ -22,7 +22,7 @@ const mail = janusMail({
22
22
  });
23
23
  ```
24
24
 
25
- The sign-in code e-mail is now yours; the eleven others stay the defaults.
25
+ The sign-in code e-mail is now yours; the twelve others stay the defaults.
26
26
 
27
27
  ## What a template is
28
28
 
@@ -63,6 +63,7 @@ e-mail.
63
63
  | `resetPassword` | `brand`, `name`, `link`, `expiresIn` | `mail.resetPassword(issued, to, options?)` |
64
64
  | `signInCode` | `brand`, `code`, `expiresIn` | `mail.signInCode(issued, to?, options?)` |
65
65
  | `magicLink` | `brand`, `link`, `expiresIn` | `mail.magicLink(issued, to?, options?)` |
66
+ | `changeEmail` | `brand`, `name`, `link`, `expiresIn` | `mail.changeEmail(issued, to, options?)` |
66
67
  | `stepUp` | `brand`, `name`, `code`, `expiresIn`, `link` | `mail.stepUp(issued, to, options?)` |
67
68
  | `passwordChanged` | `brand`, `name`, `link` | `mail.passwordChanged(to)` |
68
69
  | `emailChanged` | `brand`, `name`, `link`, `newEmail` | `mail.emailChanged(to)` |
@@ -130,12 +131,12 @@ methods live on its prototype and are refused — see
130
131
  [troubleshooting](../troubleshooting.md#janusmail-templatesname-is-not-an-own-enumerable-property--pass-a-plain-object-as--name-variables--rendered-).
131
132
 
132
133
  `templates` is `Partial` while `locales` stays within `en` and `fr`: give
133
- any of the twelve, and the defaults render the rest. Once `locales` holds
134
- another locale, it takes **all twelve** — `stepUp` included, since 0.8, and
135
- `newSignIn`, since 0.9 — see
134
+ any of the thirteen, and the defaults render the rest. Once `locales` holds
135
+ another locale, it takes **all thirteen** — `stepUp` included, since 0.8,
136
+ `newSignIn`, since 0.9, and `changeEmail`, since 0.10 — see
136
137
  [Adding a locale](locales.md#adding-a-locale).
137
138
 
138
- `mail.templates` answers the twelve in use — yours, and the defaults for the
139
+ `mail.templates` answers the thirteen in use — yours, and the defaults for the
139
140
  rest — frozen:
140
141
 
141
142
  ```ts
@@ -157,7 +158,7 @@ const { subject, html, text } = await defaults.resetPassword({
157
158
  });
158
159
  ```
159
160
 
160
- It answers the twelve defaults, typed for `'en' | 'fr'`, without a mailer:
161
+ It answers the thirteen defaults, typed for `'en' | 'fr'`, without a mailer:
161
162
  to preview an e-mail, to wrap one — add a line to the default text, say — or
162
163
  to send one through something other than `janusMail()`. A default reused for
163
164
  a wider set of locales is a compile error: it could not render the one it
@@ -191,6 +192,7 @@ The defaults are [`@nxgt/mail-presets`](https://www.npmjs.com/package/@nxgt/mail
191
192
  | `resetPassword` | `reset-password` | Reset your password | Réinitialisez votre mot de passe |
192
193
  | `signInCode` | `sign-in-code` | Your sign-in code: `042817` | Votre code de connexion : `042817` |
193
194
  | `magicLink` | `magic-link` | Your sign-in link | Votre lien de connexion |
195
+ | `changeEmail` | `confirm-new-email` | Confirm your new e-mail address | Confirmez votre nouvelle adresse e-mail |
194
196
  | `stepUp` | `confirm-action` | Your confirmation code | Votre code de confirmation |
195
197
  | `passwordChanged` | `password-changed` | Your password was changed | Votre mot de passe a été modifié |
196
198
  | `emailChanged` | `email-changed` | Your e-mail address was changed | Votre adresse e-mail a été modifiée |
@@ -219,7 +221,7 @@ on macOS` — with no blank line between rows. `welcome` has the brand in
219
221
  its heading — "Welcome to Acme" — and the recipient's name in its subject,
220
222
  filled at send time like the body; its button says **Get started**.
221
223
 
222
- `verifyEmail`, `resetPassword`, `signInCode`, `magicLink` and `stepUp` also
224
+ `verifyEmail`, `resetPassword`, `signInCode`, `magicLink`, `changeEmail` and `stepUp` also
223
225
  say how long the link or the code lasts: "This link expires in 1 hour.", "Ce code expire dans
224
226
  10 minutes." The text part keeps each paragraph on one line.
225
227
 
package/docs/roadmap.md CHANGED
@@ -9,10 +9,6 @@ Nothing between releases.
9
9
 
10
10
  ## Next
11
11
 
12
- - **A changeEmail link template** — the e-mail for the link
13
- `changeEmail.send` issues, to the new address: it says the account moves to
14
- this address, and to ignore it if the reader did not ask. Needs a preset in
15
- `@nxgt/mail-presets` first; until then send that link with your own mailer.
16
12
  - **The invitation** — `invitation` from `@nxgt/mail-presets`, once
17
13
  `@nxgt/janus` has a flow that sends it: an invitation to a user type.
18
14
  - **The other presets of `@nxgt/mail-presets` 0.4.0** — `account-deleted`,
@@ -50,6 +46,17 @@ Nothing between releases.
50
46
 
51
47
  Newest first; from the first release on, the package's CHANGELOG holds every one.
52
48
 
49
+ - **A changeEmail link template, v0.10.0.** `changeEmail(issued, to, options?)`,
50
+ built from `@nxgt/mail-presets` 1.2.0's `confirm-new-email` in English and
51
+ French: send what `@nxgt/janus` 0.23's `auth.<type>.changeEmail.send(user,
52
+ newEmail)` answered to `issued.email`, the new address — "Confirm your new
53
+ e-mail address", that the account moves there, how long the link lasts, and
54
+ to ignore it if the reader did not ask. Its link is the new, optional
55
+ `links.changeEmail(token)`; without it the send is a `TypeError`.
56
+ `emailChanged` still tells the former address once the link is redeemed.
57
+ Thirteen e-mails now, and thirteen templates to pass for a locale beyond
58
+ `en` and `fr`.
59
+
53
60
  - **A readable summary and a location in words, v0.9.1.** Built with
54
61
  `@nxgt/mail-config` 1.0.2 and `@nxgt/mail-presets` 1.1.1, the text part of
55
62
  `newSignIn` gives each row of its summary on one line — `Device Firefox on
@@ -29,12 +29,13 @@ How the messages are shaped:
29
29
  - [`janusMail: links.<name> must be a function`](#janusmail-linksname-must-be-a-function)
30
30
  - [`janusMail: links.recoveryCodes must be a function, or left out`](#janusmail-linksrecoverycodes-must-be-a-function-or-left-out)
31
31
  - [`janusMail: links.magicLink must be a function, or left out`](#janusmail-linksmagiclink-must-be-a-function-or-left-out)
32
+ - [`janusMail: links.changeEmail must be a function, or left out`](#janusmail-linkschangeemail-must-be-a-function-or-left-out)
32
33
  - [`janusMail: locales must list at least one locale, as ['en', 'fr']`](#janusmail-locales-must-list-at-least-one-locale-as-en-fr)
33
34
  - [`janusMail: locales must be BCP 47 language tags, as 'fr-CA'`](#janusmail-locales-must-be-bcp-47-language-tags-as-fr-ca)
34
35
  - [`janusMail: locales holds the same locale twice`](#janusmail-locales-holds-the-same-locale-twice)
35
36
  - [`janusMail: fallbackLocale must be one of locales`](#janusmail-fallbacklocale-must-be-one-of-locales)
36
37
  - [`janusMail: templates must be an object of functions, as { verifyEmail: (variables) => rendered }`](#janusmail-templates-must-be-an-object-of-functions-as--verifyemail-variables--rendered-)
37
- - [`janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, magicLink, stepUp, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled, recoveryCodeUsed, newSignIn, welcome`](#janusmail-templates-has-no-template-name--name-one-of-verifyemail-resetpassword-signincode-magiclink-stepup-passwordchanged-emailchanged-twofactorenabled-twofactordisabled-recoverycodeused-newsignin-welcome)
38
+ - [`janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, magicLink, stepUp, changeEmail, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled, recoveryCodeUsed, newSignIn, welcome`](#janusmail-templates-has-no-template-name--name-one-of-verifyemail-resetpassword-signincode-magiclink-stepup-changeemail-passwordchanged-emailchanged-twofactorenabled-twofactordisabled-recoverycodeused-newsignin-welcome)
38
39
  - [`janusMail: templates.<name> must be a function`](#janusmail-templatesname-must-be-a-function)
39
40
  - [`janusMail: templates.<name> is not an own enumerable property — pass a plain object, as { <name>: (variables) => rendered }`](#janusmail-templatesname-is-not-an-own-enumerable-property--pass-a-plain-object-as--name-variables--rendered-)
40
41
  - [`janusMail: clock must be a Clock — an object with a now function`](#janusmail-clock-must-be-a-clock--an-object-with-a-now-function)
@@ -42,6 +43,7 @@ How the messages are shaped:
42
43
 
43
44
  **Sending**
44
45
  - [`janusMail.magicLink: links.magicLink is missing — pass it to janusMail({ links }) to send sign-in links`](#janusmailmagiclink-linksmagiclink-is-missing--pass-it-to-janusmail-links--to-send-sign-in-links)
46
+ - [`janusMail.changeEmail: links.changeEmail is missing — pass it to janusMail({ links }) to send e-mail change links`](#janusmailchangeemail-linkschangeemail-is-missing--pass-it-to-janusmail-links--to-send-e-mail-change-links)
45
47
  - [`janusMail.stepUp: via must be 'email' — a step-up confirmed with the user's app sends no e-mail`](#janusmailstepup-via-must-be-email--a-step-up-confirmed-with-the-users-app-sends-no-e-mail)
46
48
  - [`janusMail.<method>: <field> must be a string`](#janusmailmethod-field-must-be-a-string)
47
49
  - [`janusMail.<method>: expiresAt must be a Date`](#janusmailmethod-expiresat-must-be-a-date)
@@ -71,6 +73,7 @@ How the messages are shaped:
71
73
  - [`TS2741: Property 'magicLink' is missing in type '{ … }' but required in type 'JanusMailTemplates<…>'.`](#ts2741-property-magiclink-is-missing-in-type----but-required-in-type-janusmailtemplates)
72
74
  - [`TS2741: Property 'stepUp' is missing in type '{ … }' but required in type 'JanusMailTemplates<…>'.`](#ts2741-property-stepup-is-missing-in-type----but-required-in-type-janusmailtemplates)
73
75
  - [`TS2741: Property 'newSignIn' is missing in type '{ … }' but required in type 'JanusMailTemplates<…>'.`](#ts2741-property-newsignin-is-missing-in-type----but-required-in-type-janusmailtemplates)
76
+ - [`TS2741: Property 'changeEmail' is missing in type '{ … }' but required in type 'JanusMailTemplates<…>'.`](#ts2741-property-changeemail-is-missing-in-type----but-required-in-type-janusmailtemplates)
74
77
  - [`TS2345: Argument of type 'StepUpByEmail<…> | StepUpByApp<…>' is not assignable to parameter of type 'Pick<StepUpByEmail<unknown>, …>'.`](#ts2345-argument-of-type-stepupbyemail--stepupbyapp-is-not-assignable-to-parameter-of-type-pickstepupbyemailunknown-)
75
78
  - [`TS2322: Type '"de"' is not assignable to type '"en" | "fr"'.`](#ts2322-type-de-is-not-assignable-to-type-en--fr)
76
79
  - [`TS2741: Property 'getStarted' is missing in type '{ … }' but required in type 'JanusMailLinks'.`](#ts2741-property-getstarted-is-missing-in-type----but-required-in-type-janusmaillinks)
@@ -122,7 +125,7 @@ janusMail({ mailer, from, brand: 'Acme', links });
122
125
  ### `janusMail: links must be an object, as { verifyEmail, resetPassword, secureAccount, getStarted }`
123
126
 
124
127
  No `links`. Four are required: the notices link to `secureAccount`, and
125
- the welcome to `getStarted`. Two more, `recoveryCodes` and `magicLink`, are
128
+ the welcome to `getStarted`. Three more, `recoveryCodes`, `magicLink` and `changeEmail`, are
126
129
  optional.
127
130
 
128
131
  ### `janusMail: links.<name> must be a function`
@@ -169,6 +172,17 @@ calling `auth.magicLink.confirm`:
169
172
  links: { …, magicLink: (token) => `https://acme.example/sign-in/link?token=${token}` },
170
173
  ```
171
174
 
175
+ ### `janusMail: links.changeEmail must be a function, or left out`
176
+
177
+ `links.changeEmail` given as a URL, or as anything but a function. It is
178
+ optional, but when given it takes the link's one-time token and answers **a
179
+ page of yours that spends nothing**, whose button posts the token to the route
180
+ calling `auth.<type>.changeEmail.confirm`:
181
+
182
+ ```ts
183
+ links: { …, changeEmail: (token) => `https://acme.example/account/email?token=${token}` },
184
+ ```
185
+
172
186
  ### `janusMail: locales must list at least one locale, as ['en', 'fr']`
173
187
 
174
188
  `locales: []`, `locales: 'en'`, or a list holding something that is not a
@@ -201,9 +215,9 @@ A `fallbackLocale` the list does not hold — `'de'` with the default
201
215
 
202
216
  `templates` given as a list or a function. Key each template by its name.
203
217
 
204
- ### `janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, magicLink, stepUp, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled, recoveryCodeUsed, newSignIn, welcome`
218
+ ### `janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, magicLink, stepUp, changeEmail, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled, recoveryCodeUsed, newSignIn, welcome`
205
219
 
206
- A key that is not one of the twelve — `invitation`, or the e-mail's file name
220
+ A key that is not one of the thirteen — `invitation`, or the e-mail's file name
207
221
  `'verify-email'` rather than the template's, `verifyEmail`. Other e-mails are
208
222
  on the [roadmap](roadmap.md); send them with `@nxgt/mail` directly meanwhile.
209
223
 
@@ -237,7 +251,7 @@ as it is: fields are own properties.
237
251
  ### `janusMail: the default templates are built in en and fr only — with another locale in locales, pass every template in templates; <names> missing`
238
252
 
239
253
  `locales` holds a locale beyond `en` and `fr`, and `templates` leaves some
240
- out: the defaults could not render them in that locale. Pass all twelve — see
254
+ out: the defaults could not render them in that locale. Pass all thirteen — see
241
255
  [Adding a locale](guide/locales.md#adding-a-locale) — or drop the locale.
242
256
  The message lists the templates missing.
243
257
 
@@ -272,6 +286,23 @@ const mail = janusMail({
272
286
 
273
287
  Sending again fails again: it is a bug, not an outage.
274
288
 
289
+ ### `janusMail.changeEmail: links.changeEmail is missing — pass it to janusMail({ links }) to send e-mail change links`
290
+
291
+ A `TypeError` from `mail.changeEmail`, before anything is rendered or sent:
292
+ `janusMail()` was given no `links.changeEmail`. It is optional, so
293
+ `janusMail()` accepts `links` without it — written before 0.10, or for an
294
+ application that lets no user change their address — and there is no page to
295
+ fall back on: only yours can carry the token. Add it:
296
+
297
+ ```ts
298
+ const mail = janusMail({
299
+ …,
300
+ links: { …, changeEmail: (token) => `https://acme.example/account/email?token=${token}` },
301
+ });
302
+ ```
303
+
304
+ Sending again fails again: it is a bug, not an outage.
305
+
275
306
  ### `janusMail.stepUp: via must be 'email' — a step-up confirmed with the user's app sends no e-mail`
276
307
 
277
308
  A `TypeError` from `mail.stepUp`, before anything is rendered or sent: it
@@ -533,7 +564,7 @@ avoids the read altogether. (In this repository: run `bun run build`.)
533
564
 
534
565
  The default templates read `mails/` with `node:fs`, through
535
566
  `@nxgt/mail/renderer`: Node, Bun or Deno only. On an edge runtime, pass all
536
- twelve templates yourself; an inlined build is on the [roadmap](roadmap.md).
567
+ thirteen templates yourself; an inlined build is on the [roadmap](roadmap.md).
537
568
 
538
569
  ### An e-mail stays light in dark mode
539
570
 
@@ -666,8 +697,8 @@ whole.
666
697
  ### `TS2739: Type '{ … }' is missing the following properties from type 'JanusMailTemplates<…>'`
667
698
 
668
699
  `locales` holds a locale beyond `en` and `fr`, and `templates` does not give
669
- all twelve. With five or more missing, the code is `TS2740` and the list ends
670
- `…, and <n> more.` — `…, and 7 more.` for a `templates` holding one
700
+ all thirteen. With five or more missing, the code is `TS2740` and the list ends
701
+ `…, and <n> more.` — `…, and 8 more.` for a `templates` holding one
671
702
  template. See [Adding a locale](guide/locales.md#adding-a-locale).
672
703
 
673
704
  ### `TS2741: Property 'recoveryCodeUsed' is missing in type '{ … }' but required in type 'JanusMailTemplates<…>'.`
@@ -707,6 +738,16 @@ yours. Add `newSignIn` — it is given `brand`, `name`, `device`, `location`,
707
738
  [`janusMail: the default templates are built in en and fr only — …; newSignIn missing`](#janusmail-the-default-templates-are-built-in-en-and-fr-only--with-another-locale-in-locales-pass-every-template-in-templates-names-missing).
708
739
  See [Templates](guide/templates.md#what-each-template-is-given).
709
740
 
741
+ ### `TS2741: Property 'changeEmail' is missing in type '{ … }' but required in type 'JanusMailTemplates<…>'.`
742
+
743
+ `templates` written before 0.10, with a locale beyond `en` and `fr`: since
744
+ 0.10.0 there are thirteen templates, and with such a locale every one is
745
+ yours. Add `changeEmail` — it is given `brand`, `name`, `link` and
746
+ `expiresIn`, like `verifyEmail` — even if you never send it; in JavaScript
747
+ the same `templates` is
748
+ [`janusMail: the default templates are built in en and fr only — …; changeEmail missing`](#janusmail-the-default-templates-are-built-in-en-and-fr-only--with-another-locale-in-locales-pass-every-template-in-templates-names-missing).
749
+ See [Templates](guide/templates.md#what-each-template-is-given).
750
+
710
751
  ### `TS2345: Argument of type 'StepUpByEmail<…> | StepUpByApp<…>' is not assignable to parameter of type 'Pick<StepUpByEmail<unknown>, …>'.`
711
752
 
712
753
  What `auth.stepUp.request(user)` answered, passed to `mail.stepUp` without
@@ -0,0 +1,51 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" dir="ltr" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" style="color-scheme:light dark;">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="x-apple-disable-message-reformatting">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <meta name="color-scheme" content="light dark">
8
+ <meta name="supported-color-schemes" content="light dark">
9
+ <style>[data-ogsc] .nx-dark-bg-paper{background-color:#040a19!important;}[data-ogsb] .nx-dark-bg-paper{background-color:#040a19!important;}[data-ogsc] .nx-dark-bg-card{background-color:#0f172b!important;background-color:lab(7.78673% 1.82345 -15.0537)!important;}[data-ogsb] .nx-dark-bg-card{background-color:#0f172b!important;background-color:lab(7.78673% 1.82345 -15.0537)!important;}[data-ogsc] .nx-dark-bg-background{background-color:#020918!important;background-color:lab(2.35721% .367686
10
+ -8.51797)!important;}[data-ogsb] .nx-dark-bg-background{background-color:#020918!important;background-color:lab(2.35721% .367686 -8.51797)!important;}[data-ogsc] .nx-dark-text-foreground{color:#f8fafc!important;color:lab(98.1434% -.369519 -1.05966)!important;}[data-ogsb] .nx-dark-text-foreground{color:#f8fafc!important;color:lab(98.1434% -.369519 -1.05966)!important;}[data-ogsc] .nx-dark-text-foreground-25{color:#404551!important;}[data-ogsb] .nx-dark-text-foreground-25{color:#404551!important;}
11
+ [data-ogsc] .nx-dark-text-card-foreground{color:#f8fafc!important;color:lab(98.1434% -.369519 -1.05966)!important;}[data-ogsb] .nx-dark-text-card-foreground{color:#f8fafc!important;color:lab(98.1434% -.369519 -1.05966)!important;}[data-ogsc] .nx-dark-border-border{border-color:#1c212f!important;}[data-ogsb] .nx-dark-border-border{border-color:#1c212f!important;}[data-ogsc] .nx-dark-bg-muted{background-color:#1e293b!important;}[data-ogsb] .nx-dark-bg-muted{background-color:#1e293b!important;}
12
+ [data-ogsc] .nx-dark-text-muted-foreground{color:#cbd5e1!important;}[data-ogsb] .nx-dark-text-muted-foreground{color:#cbd5e1!important;}[data-ogsc] .nx-dark-border-muted-foreground{border-color:#cbd5e1!important;}[data-ogsb] .nx-dark-border-muted-foreground{border-color:#cbd5e1!important;}[data-ogsc] .nx-dark-border-muted{border-color:#1e293b!important;}[data-ogsb] .nx-dark-border-muted{border-color:#1e293b!important;}[data-ogsc] .nx-dark-bg-primary{background-color:#fafafa!important;}
13
+ [data-ogsb] .nx-dark-bg-primary{background-color:#fafafa!important;}[data-ogsc] .nx-dark-text-primary{color:#fafafa!important;}[data-ogsb] .nx-dark-text-primary{color:#fafafa!important;}[data-ogsc] .nx-dark-text-primary-foreground{color:#18181b!important;}[data-ogsb] .nx-dark-text-primary-foreground{color:#18181b!important;}[data-ogsc] .nx-dark-text-info{color:#93c5fd!important;}[data-ogsb] .nx-dark-text-info{color:#93c5fd!important;}[data-ogsc] .nx-dark-border-primary{border-color:#fafafa
14
+ !important;}[data-ogsb] .nx-dark-border-primary{border-color:#fafafa!important;}[data-ogsc] .nx-dark-bg-primary-15{background-color:#272d3a!important;}[data-ogsb] .nx-dark-bg-primary-15{background-color:#272d3a!important;}[data-ogsc] .nx-dark-bg-primary-20{background-color:#343945!important;}[data-ogsb] .nx-dark-bg-primary-20{background-color:#343945!important;}[data-ogsc] .nx-dark-border-primary-40{border-color:#656972!important;}[data-ogsb] .nx-dark-border-primary-40{border-color:#656972
15
+ !important;}[data-ogsc] .nx-dark-border-primary-50{border-color:#7e8189!important;}[data-ogsb] .nx-dark-border-primary-50{border-color:#7e8189!important;}[data-ogsc] .nx-light-only{display:none!important;}[data-ogsb] .nx-light-only{display:none!important;}[data-ogsc] .nx-dark-only{display:inline-block!important;}[data-ogsb] .nx-dark-only{display:inline-block!important;}
16
+ @media (prefers-color-scheme:dark){html{--lightningcss-light:;--lightningcss-dark:initial;}.nx-dark-bg-paper{background-color:#040a19!important;}.nx-dark-bg-card{background-color:#0f172b!important;background-color:lab(7.78673% 1.82345 -15.0537)!important;}.nx-dark-text-foreground{color:#f8fafc!important;color:lab(98.1434% -.369519 -1.05966)!important;}.nx-dark-text-card-foreground{color:#f8fafc!important;color:lab(98.1434% -.369519 -1.05966)!important;}.nx-dark-border-border{border-color:#1c212f
17
+ !important;}.nx-dark-text-muted-foreground{color:#cbd5e1!important;}.nx-dark-bg-primary{background-color:#fafafa!important;}.nx-dark-text-primary-foreground{color:#18181b!important;}.nx-dark-text-info{color:#93c5fd!important;} }
18
+ </style>
19
+ </head>
20
+ <body xml:lang="en" dir="ltr" style="margin:0;padding:0;width:100%;height:100%;word-break:break-word;background-color:#f4f4f4;" class="nx-dark-bg-paper"><div style="display:none;">One click to move your account to this address.&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
21
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
22
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
23
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
24
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
25
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
26
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
27
+ &#8199;&#65279;&#847; &#8199;&#65279;&#847; &nbsp;</div><span style="display:none">
28
+ <!--[if mso]><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings><w:WordDocument><w:DontUseAdvancedTypographyReadingMail/></w:WordDocument></xml>
29
+ <![endif]--></span><div role="article" aria-roledescription="email" lang="en" dir="ltr" style="font-size:medium;font-size:max(16px,1rem)">
30
+ <table class="nx-dark-bg-paper" role="presentation" cellpadding="0" cellspacing="0" dir="ltr" style="width:100%;background-color:#f4f4f4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont, 'Segoe UI',Roboto, 'Noto Sans',Ubuntu,Cantarell, 'Helvetica Neue',sans-serif;"><tr><td align="center" style="padding:32px 16px;">
31
+ <!--[if mso]>
32
+ <table role="none" cellpadding="0" cellspacing="0" style="width:600px" align="center"><tr><td>
33
+ <![endif]--><div style="margin:0 auto;max-width:600px;">
34
+ <table role="presentation" cellpadding="0" cellspacing="0" dir="ltr" style="width:100%;"><tr><td style="padding-bottom:24px;text-align:center;"><span class="nx-dark-text-foreground" style="font-size:18px;line-height:28px;font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">{{ brand }}</span>
35
+ </td></tr><tr><td class="nx-dark-border-border nx-dark-bg-card nx-dark-text-card-foreground" style="border-radius:14px;border-color:#e2e8f0;border-style:solid;border-width:1px;border-color:lab(91.7353% -.998765 -4.76968);background-color:#fff;background-color:lab(100% 0 0);padding:32px;font-size:14px;line-height:20px;color:#020618;color:lab(1.76974% 1.32743 -9.28855);box-shadow:0 0 rgba(0,0,0,0),0 0 rgba(0,0,0,0),0 0 rgba(0,0,0,0),0 0 rgba(0,0,0,0),0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,
36
+ 0,0,.1);"><h1 class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:24px;line-height:32px;font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">Confirm your new e-mail address</h1><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686 -8.51797);">Hello {{ name }},</p><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686
37
+ -8.51797);">Someone, we hope you, asked to move an existing {{ brand }} account to this address. Confirm it to make this address the account's sign-in address.</p><div><a style="display:inline-block;border-radius:9999px;background-color:#27272a;padding:10px 16px;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont, 'Segoe UI',Roboto, 'Noto Sans',Ubuntu,Cantarell, 'Helvetica Neue',sans-serif;font-size:14px;line-height:16px;font-weight:500;color:#f8fafc;color:lab(98.1434% -.369519
38
+ -1.05966);text-decoration:none;" href="{{ link }}" class="nx-dark-bg-primary nx-dark-text-primary-foreground">
39
+ <!--[if mso]><i style="mso-font-width:114%;mso-text-raise:19px;" hidden>&emsp;</i>
40
+ <![endif]--> <span style="mso-text-raise:10px;">Confirm my new address</span>
41
+ <!--[if mso]><i style="mso-font-width:114%;" hidden>&emsp;&#8203;</i>
42
+ <![endif]--></a></div><div role="separator" style="line-height:24px;">&zwj;</div><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:12px;line-height:16px;color:#020918;color:lab(2.35721% .367686 -8.51797);">This link expires in {{ expiresIn }}.</p><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:12px;line-height:16px;color:#5f718a;">If the button does not work, open this link: <a href="{{ link }}" class="nx-dark-text-info" style="color:#1d4ed8;text-decoration:
43
+ underline;">{{ link }}</a></p><p class="nx-dark-text-muted-foreground" style="margin:0 0 16px;font-size:10px;color:#5f718a;">If this was not you, ignore this e-mail: nothing changes on the account.</p>
44
+ </td></tr><tr><td class="nx-dark-text-muted-foreground" style="padding-left:24px;padding-right:24px;padding-top:24px;text-align:center;font-size:12px;line-height:16px;color:#5f718a;"><p style="margin:0 0 8px;">You received this e-mail because you have an account with {{ brand }}.</p><p style="margin:0;">{{ brand }}</p>
45
+ </td></tr></table></div>
46
+ <!--[if mso]>
47
+ </td></tr></table>
48
+ <![endif]-->
49
+ </td></tr></table></div>
50
+ </body>
51
+ </html>
@@ -0,0 +1,23 @@
1
+ One click to move your account to this address.
2
+
3
+ {{ brand }}
4
+
5
+ Confirm your new e-mail address
6
+
7
+ Hello {{ name }},
8
+
9
+ Someone, we hope you, asked to move an existing {{ brand }} account to this address. Confirm it to make this address the account's sign-in address.
10
+
11
+ Confirm my new address
12
+
13
+ {{ link }}
14
+
15
+ This link expires in {{ expiresIn }}.
16
+
17
+ If the button does not work, open this link: {{ link }}
18
+
19
+ If this was not you, ignore this e-mail: nothing changes on the account.
20
+
21
+ You received this e-mail because you have an account with {{ brand }}.
22
+
23
+ {{ brand }}