@nxgt/janus-mail 0.2.0 → 0.3.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.
- package/README.md +48 -13
- package/dist/generated/mail.d.ts +10 -0
- package/dist/generated/mail.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -12
- package/dist/index.js.map +5 -5
- package/dist/notice-mails.d.ts +5 -5
- package/dist/notice-mails.d.ts.map +1 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/templates.d.ts +1 -1
- package/dist/templates.d.ts.map +1 -1
- package/dist/types.d.ts +33 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +2 -2
- package/docs/guide/building.md +26 -2
- package/docs/guide/locales.md +9 -3
- package/docs/guide/sending.md +28 -0
- package/docs/guide/templates.md +24 -9
- package/docs/roadmap.md +16 -0
- package/docs/troubleshooting.md +46 -19
- package/mails/en/email-changed.html +20 -12
- package/mails/en/password-changed.html +20 -12
- package/mails/en/reset-password.html +19 -12
- package/mails/en/sign-in-code.html +19 -10
- package/mails/en/two-factor-disabled.html +49 -0
- package/mails/en/two-factor-disabled.txt +21 -0
- package/mails/en/two-factor-enabled.html +49 -0
- package/mails/en/two-factor-enabled.txt +21 -0
- package/mails/en/verify-email.html +19 -12
- package/mails/fr/email-changed.html +21 -13
- package/mails/fr/password-changed.html +20 -12
- package/mails/fr/reset-password.html +20 -12
- package/mails/fr/sign-in-code.html +17 -10
- package/mails/fr/two-factor-disabled.html +49 -0
- package/mails/fr/two-factor-disabled.txt +21 -0
- package/mails/fr/two-factor-enabled.html +49 -0
- package/mails/fr/two-factor-enabled.txt +21 -0
- package/mails/fr/verify-email.html +19 -12
- package/mails/mail-manifest.json +48 -0
- package/package.json +8 -8
package/docs/guide/sending.md
CHANGED
|
@@ -178,6 +178,33 @@ through JSON on its way to a queue holds a string — or is already past, is
|
|
|
178
178
|
a `TypeError`, and nothing reaches the mailer: revive the date with
|
|
179
179
|
`new Date(issued.expiresAt)` when the job runs, or pass `expiresIn`.
|
|
180
180
|
|
|
181
|
+
### `twoFactorEnabled(to)` and `twoFactorDisabled(to)`
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// On the user events @nxgt/janus sends once the write landed:
|
|
185
|
+
const auth = janus({
|
|
186
|
+
...config,
|
|
187
|
+
async events(event) {
|
|
188
|
+
if (event.type !== 'user.secondFactorEnabled' && event.type !== 'user.secondFactorDisabled') return;
|
|
189
|
+
const user = await auth.get(event.userId);
|
|
190
|
+
const to = { name: user.name, locale: user.locale, email: user.email };
|
|
191
|
+
await (event.type === 'user.secondFactorEnabled' ? mail.twoFactorEnabled(to) : mail.twoFactorDisabled(to));
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Two notices: two-factor authentication was turned on, or off, for the
|
|
197
|
+
account at `to.email`, each with a link to `links.secureAccount()` — the
|
|
198
|
+
user's security settings — for a user who did not make the change. Send
|
|
199
|
+
`twoFactorEnabled` on the `user.secondFactorEnabled` event, which
|
|
200
|
+
`auth.secondFactor.activate` sends once the factor is active, and
|
|
201
|
+
`twoFactorDisabled` on `user.secondFactorDisabled`, which
|
|
202
|
+
`auth.secondFactor.disable` sends only when it removed an active factor: a
|
|
203
|
+
`disable` on a user who had none tells nobody anything. The event names the
|
|
204
|
+
user by id alone, so read the name, the locale and the address from the
|
|
205
|
+
user. Calling them right after `activate` or `disable` answered works as
|
|
206
|
+
well — without the events, check `hasSecondFactor` before the `disable`.
|
|
207
|
+
|
|
181
208
|
## Where each e-mail goes
|
|
182
209
|
|
|
183
210
|
| Method | To | Never to |
|
|
@@ -187,6 +214,7 @@ a `TypeError`, and nothing reaches the mailer: revive the date with
|
|
|
187
214
|
| `signInCode` | `issued.email` | the `email` passed to `request` |
|
|
188
215
|
| `passwordChanged` | `to.email` | — |
|
|
189
216
|
| `emailChanged` | `to.formerEmail` | `to.newEmail` |
|
|
217
|
+
| `twoFactorEnabled`, `twoFactorDisabled` | `to.email` | — |
|
|
190
218
|
|
|
191
219
|
`issued.email` is the address the user's record holds, as they registered
|
|
192
220
|
it; what the visitor typed may differ in case or spacing. The recipient is a
|
package/docs/guide/templates.md
CHANGED
|
@@ -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
|
|
4
|
+
is given and answers, replacing some of the seven, 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
|
|
25
|
+
The sign-in code e-mail is now yours; the six others stay the defaults.
|
|
26
26
|
|
|
27
27
|
## What a template is
|
|
28
28
|
|
|
@@ -64,10 +64,12 @@ e-mail.
|
|
|
64
64
|
| `signInCode` | `brand`, `code`, `expiresIn` | `mail.signInCode(issued, to?, options?)` |
|
|
65
65
|
| `passwordChanged` | `brand`, `name`, `link` | `mail.passwordChanged(to)` |
|
|
66
66
|
| `emailChanged` | `brand`, `name`, `link`, `newEmail` | `mail.emailChanged(to)` |
|
|
67
|
+
| `twoFactorEnabled` | `brand`, `name`, `link` | `mail.twoFactorEnabled(to)` |
|
|
68
|
+
| `twoFactorDisabled` | `brand`, `name`, `link` | `mail.twoFactorDisabled(to)` |
|
|
67
69
|
|
|
68
70
|
Every one also gets `locale`, one of `locales`. Every value is a string:
|
|
69
71
|
`brand` from the options, `name` from the recipient, `link` from `links` —
|
|
70
|
-
`links.secureAccount()` for the
|
|
72
|
+
`links.secureAccount()` for the four notices — `code` and `newEmail` from the
|
|
71
73
|
call, and `expiresIn` derived from the flow's `expiresAt` in the locale, or
|
|
72
74
|
the send's own `expiresIn` ([Sending](sending.md#the-expiry)).
|
|
73
75
|
|
|
@@ -101,11 +103,11 @@ methods live on its prototype and are refused — see
|
|
|
101
103
|
[troubleshooting](../troubleshooting.md#janusmail-templatesname-is-not-an-own-enumerable-property--pass-a-plain-object-as--name-variables--rendered-).
|
|
102
104
|
|
|
103
105
|
`templates` is `Partial` while `locales` stays within `en` and `fr`: give
|
|
104
|
-
any of the
|
|
105
|
-
another locale, it takes **all
|
|
106
|
+
any of the seven, and the defaults render the rest. Once `locales` holds
|
|
107
|
+
another locale, it takes **all seven** — see
|
|
106
108
|
[Adding a locale](locales.md#adding-a-locale).
|
|
107
109
|
|
|
108
|
-
`mail.templates` answers the
|
|
110
|
+
`mail.templates` answers the seven in use — yours, and the defaults for the
|
|
109
111
|
rest — frozen:
|
|
110
112
|
|
|
111
113
|
```ts
|
|
@@ -127,7 +129,7 @@ const { subject, html, text } = await defaults.resetPassword({
|
|
|
127
129
|
});
|
|
128
130
|
```
|
|
129
131
|
|
|
130
|
-
It answers the
|
|
132
|
+
It answers the seven defaults, typed for `'en' | 'fr'`, without a mailer:
|
|
131
133
|
to preview an e-mail, to wrap one — add a line to the default text, say — or
|
|
132
134
|
to send one through something other than `janusMail()`. A default reused for
|
|
133
135
|
a wider set of locales is a compile error: it could not render the one it
|
|
@@ -153,7 +155,7 @@ them renders: that is when the package's `mails/` folder is read, once.
|
|
|
153
155
|
## What the defaults say
|
|
154
156
|
|
|
155
157
|
The defaults are [`@nxgt/mail-presets`](https://www.npmjs.com/package/@nxgt/mail-presets)
|
|
156
|
-
0.
|
|
158
|
+
0.4.0, built with a neutral grey theme and no logo:
|
|
157
159
|
|
|
158
160
|
| Template | Built from | Subject (`en`) | Subject (`fr`) |
|
|
159
161
|
| --- | --- | --- | --- |
|
|
@@ -162,16 +164,29 @@ The defaults are [`@nxgt/mail-presets`](https://www.npmjs.com/package/@nxgt/mail
|
|
|
162
164
|
| `signInCode` | `sign-in-code` | Your sign-in code: `042817` | Votre code de connexion : `042817` |
|
|
163
165
|
| `passwordChanged` | `password-changed` | Your password was changed | Votre mot de passe a été modifié |
|
|
164
166
|
| `emailChanged` | `email-changed` | Your e-mail address was changed | Votre adresse e-mail a été modifiée |
|
|
167
|
+
| `twoFactorEnabled` | `two-factor-enabled` | Two-factor authentication was turned on | L'authentification à deux facteurs a été activée |
|
|
168
|
+
| `twoFactorDisabled` | `two-factor-disabled` | Two-factor authentication was turned off | L'authentification à deux facteurs a été désactivée |
|
|
165
169
|
|
|
166
170
|
Each has a header and a footer with the brand, a heading, a greeting by name
|
|
167
171
|
(but `signInCode`), a button with its link and the link again in text for a
|
|
168
|
-
client that shows no button, and a text part. The
|
|
172
|
+
client that shows no button, and a text part. The four notices add a warning:
|
|
169
173
|
*if this was not you, secure your account now*.
|
|
170
174
|
|
|
171
175
|
`verifyEmail`, `resetPassword` and `signInCode` also say how long the link
|
|
172
176
|
or the code lasts: "This link expires in 1 hour.", "Ce code expire dans
|
|
173
177
|
10 minutes." The text part keeps each paragraph on one line.
|
|
174
178
|
|
|
179
|
+
**The HTML follows dark mode.** Each HTML part declares
|
|
180
|
+
`color-scheme: light dark`. A client that reads `prefers-color-scheme`, or
|
|
181
|
+
Outlook's `[data-ogsc]`, shows a dark page, a dark card and light text to a
|
|
182
|
+
reader in dark mode; Gmail always shows the light e-mail. The dark palette
|
|
183
|
+
is `@nxgt/mail-ui`'s default, a deep navy, since the build sets only the
|
|
184
|
+
primary colour; the primary has no dark value, so the button keeps its
|
|
185
|
+
near-black in both modes. Nothing is passed for it, the text part has no
|
|
186
|
+
colours, and a template of your own gets none of it. `@nxgt/mail-ui`'s
|
|
187
|
+
[Dark mode](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-ui/docs/guide/dark-mode.md)
|
|
188
|
+
guide has the technique, client by client.
|
|
189
|
+
|
|
175
190
|
**The brand is text.** It is written in the header, the body and the footer,
|
|
176
191
|
escaped — no logo and no link, which would need absolute URLs known when the
|
|
177
192
|
package is built. A logo takes a template of your own; the
|
package/docs/roadmap.md
CHANGED
|
@@ -13,6 +13,9 @@ Nothing between releases.
|
|
|
13
13
|
`invitation` from `@nxgt/mail-presets`, each once `@nxgt/janus` has a flow
|
|
14
14
|
that sends it: a sign-in link, a sign-in from a new device, a user created,
|
|
15
15
|
an invitation to a user type.
|
|
16
|
+
- **The other presets of `@nxgt/mail-presets` 0.4.0** — `account-deleted`,
|
|
17
|
+
after a user is deleted, once `@nxgt/janus` has a deletion a link can
|
|
18
|
+
undo; and `invitation-accepted`, once it has invitations.
|
|
16
19
|
|
|
17
20
|
## Later
|
|
18
21
|
|
|
@@ -44,6 +47,19 @@ Nothing between releases.
|
|
|
44
47
|
|
|
45
48
|
Newest first; from the first release on, the package's CHANGELOG holds every one.
|
|
46
49
|
|
|
50
|
+
- **The two-factor notices, v0.3.0.** `twoFactorEnabled(to)` and
|
|
51
|
+
`twoFactorDisabled(to)`, built from `@nxgt/mail-presets` 0.4.0's
|
|
52
|
+
`two-factor-enabled` and `two-factor-disabled` in English and French, each
|
|
53
|
+
linking to `links.secureAccount()`: send them on `@nxgt/janus` 0.9's
|
|
54
|
+
`user.secondFactorEnabled` and `user.secondFactorDisabled` events. Seven
|
|
55
|
+
e-mails now, and seven templates to pass for a locale beyond `en` and `fr`.
|
|
56
|
+
- **Dark mode, v0.3.0.** The e-mails follow the reader's dark mode in
|
|
57
|
+
every client that supports it, Gmail excepted: a dark page, a dark card and
|
|
58
|
+
light text. Built from `@nxgt/mail-ui` 0.4.0, `@nxgt/mail-presets` 0.4.0
|
|
59
|
+
and `@nxgt/mail-i18n` 0.5.0; the text parts, subjects and variables are
|
|
60
|
+
unchanged, the manifest is still format 1, and the `@nxgt/mail` peer stays
|
|
61
|
+
`>=0.1.0 <1`.
|
|
62
|
+
|
|
47
63
|
- **The expiry in the e-mail, v0.2.0.** The verification, reset and sign-in
|
|
48
64
|
code e-mails say how long the link or code lasts — "1 hour", "1 heure" —
|
|
49
65
|
derived from the flow's `expiresAt` in the recipient's locale, measured
|
package/docs/troubleshooting.md
CHANGED
|
@@ -28,13 +28,13 @@ How the messages are shaped:
|
|
|
28
28
|
- [`janusMail: links must be an object, as { verifyEmail, resetPassword, secureAccount }`](#janusmail-links-must-be-an-object-as--verifyemail-resetpassword-secureaccount-)
|
|
29
29
|
- [`janusMail: links.<name> must be a function`](#janusmail-linksname-must-be-a-function)
|
|
30
30
|
- [`janusMail: locales must list at least one locale, as ['en', 'fr']`](#janusmail-locales-must-list-at-least-one-locale-as-en-fr)
|
|
31
|
+
- [`janusMail: locales must be BCP 47 language tags, as 'fr-CA'`](#janusmail-locales-must-be-bcp-47-language-tags-as-fr-ca)
|
|
31
32
|
- [`janusMail: locales holds the same locale twice`](#janusmail-locales-holds-the-same-locale-twice)
|
|
32
33
|
- [`janusMail: fallbackLocale must be one of locales`](#janusmail-fallbacklocale-must-be-one-of-locales)
|
|
33
34
|
- [`janusMail: templates must be an object of functions, as { verifyEmail: (variables) => rendered }`](#janusmail-templates-must-be-an-object-of-functions-as--verifyemail-variables--rendered-)
|
|
34
|
-
- [`janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, passwordChanged, emailChanged`](#janusmail-templates-has-no-template-name--name-one-of-verifyemail-resetpassword-signincode-passwordchanged-emailchanged)
|
|
35
|
+
- [`janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled`](#janusmail-templates-has-no-template-name--name-one-of-verifyemail-resetpassword-signincode-passwordchanged-emailchanged-twofactorenabled-twofactordisabled)
|
|
35
36
|
- [`janusMail: templates.<name> must be a function`](#janusmail-templatesname-must-be-a-function)
|
|
36
37
|
- [`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-)
|
|
37
|
-
- [`janusMail: locales must be BCP 47 language tags, with hyphens, as 'fr-CA'`](#janusmail-locales-must-be-bcp-47-language-tags-with-hyphens-as-fr-ca)
|
|
38
38
|
- [`janusMail: clock must be a Clock — an object with a now function`](#janusmail-clock-must-be-a-clock--an-object-with-a-now-function)
|
|
39
39
|
- [`janusMail: the default templates are built in en and fr only — with another locale in locales, pass every template in templates; <names> missing`](#janusmail-the-default-templates-are-built-in-en-and-fr-only--with-another-locale-in-locales-pass-every-template-in-templates-names-missing)
|
|
40
40
|
|
|
@@ -51,6 +51,7 @@ How the messages are shaped:
|
|
|
51
51
|
- [`MAIL_FAILED` — `MailFailure`](#mail_failed--mailfailure)
|
|
52
52
|
- [`createMailRenderer: …/mails/mail-manifest.json cannot be read — run maizzle build, and deploy its output folder`](#createmailrenderer-mailsmail-manifestjson-cannot-be-read--run-maizzle-build-and-deploy-its-output-folder)
|
|
53
53
|
- [`Could not resolve "node:fs"` on an edge runtime](#could-not-resolve-nodefs-on-an-edge-runtime)
|
|
54
|
+
- [An e-mail stays light in dark mode](#an-e-mail-stays-light-in-dark-mode)
|
|
54
55
|
|
|
55
56
|
**Compile errors**
|
|
56
57
|
- [`TS2345: Argument of type '(IssuedToken & { user: … }) | null' is not assignable to parameter of type 'IssuedToken'.`](#ts2345-argument-of-type-issuedtoken---user----null-is-not-assignable-to-parameter-of-type-issuedtoken)
|
|
@@ -122,6 +123,19 @@ links: {
|
|
|
122
123
|
`locales: []`, `locales: 'en'`, or a list holding something that is not a
|
|
123
124
|
non-empty string. Leave it out for `['en', 'fr']`.
|
|
124
125
|
|
|
126
|
+
### `janusMail: locales must be BCP 47 language tags, as 'fr-CA'`
|
|
127
|
+
|
|
128
|
+
A `TypeError` when `janusMail()` is called: a locale in `locales` is one
|
|
129
|
+
`Intl` refuses — `de_DE` with an underscore, a grandfathered `i-klingon`, a
|
|
130
|
+
bare private-use `x-…`. The expiry is formatted by `Intl` in the locale
|
|
131
|
+
picked, so a locale it cannot parse would fail at the first send; it is
|
|
132
|
+
refused here instead. Write a tag `Intl` takes — `de-DE`, not `de_DE`; `tlh`,
|
|
133
|
+
not `i-klingon`:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
janusMail({ mailer, from, brand: 'Acme', links, locales: ['en', 'fr', 'de-DE'], templates });
|
|
137
|
+
```
|
|
138
|
+
|
|
125
139
|
### `janusMail: locales holds the same locale twice`
|
|
126
140
|
|
|
127
141
|
`['en', 'en']`. List each once.
|
|
@@ -136,9 +150,9 @@ A `fallbackLocale` the list does not hold — `'de'` with the default
|
|
|
136
150
|
|
|
137
151
|
`templates` given as a list or a function. Key each template by its name.
|
|
138
152
|
|
|
139
|
-
### `janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, passwordChanged, emailChanged`
|
|
153
|
+
### `janusMail: templates has no template <name> — name one of verifyEmail, resetPassword, signInCode, passwordChanged, emailChanged, twoFactorEnabled, twoFactorDisabled`
|
|
140
154
|
|
|
141
|
-
A key that is not one of the
|
|
155
|
+
A key that is not one of the seven — `welcome`, or the e-mail's file name
|
|
142
156
|
`'verify-email'` rather than the template's, `verifyEmail`. Other e-mails are
|
|
143
157
|
on the [roadmap](roadmap.md); send them with `@nxgt/mail` directly meanwhile.
|
|
144
158
|
|
|
@@ -172,22 +186,10 @@ as it is: fields are own properties.
|
|
|
172
186
|
### `janusMail: the default templates are built in en and fr only — with another locale in locales, pass every template in templates; <names> missing`
|
|
173
187
|
|
|
174
188
|
`locales` holds a locale beyond `en` and `fr`, and `templates` leaves some
|
|
175
|
-
out: the defaults could not render them in that locale. Pass all
|
|
189
|
+
out: the defaults could not render them in that locale. Pass all seven — see
|
|
176
190
|
[Adding a locale](guide/locales.md#adding-a-locale) — or drop the locale.
|
|
177
191
|
The message lists the templates missing.
|
|
178
192
|
|
|
179
|
-
### `janusMail: locales must be BCP 47 language tags, with hyphens, as 'fr-CA'`
|
|
180
|
-
|
|
181
|
-
A `TypeError` when `janusMail()` is called: a locale in `locales` is one
|
|
182
|
-
`Intl` refuses — `de_DE` with an underscore, a grandfathered `i-klingon`, a
|
|
183
|
-
bare private-use `x-…`. The expiry is formatted by `Intl` in the locale
|
|
184
|
-
picked, so a locale it cannot parse would fail at the first send; it is
|
|
185
|
-
refused here instead. Write the tag with hyphens:
|
|
186
|
-
|
|
187
|
-
```ts
|
|
188
|
-
janusMail({ mailer, from, brand: 'Acme', links, locales: ['en', 'fr', 'de-DE'], templates });
|
|
189
|
-
```
|
|
190
|
-
|
|
191
193
|
### `janusMail: clock must be a Clock — an object with a now function`
|
|
192
194
|
|
|
193
195
|
`clock` is `@nxgt/janus`'s `Clock`, `{ now(): Date }` — pass the one given to
|
|
@@ -222,6 +224,15 @@ string` is the third argument's `expiresIn` given as something else — a
|
|
|
222
224
|
number of seconds: pass the text to show, `{ expiresIn: '1 hour' }`, or
|
|
223
225
|
leave it out.
|
|
224
226
|
|
|
227
|
+
`janusMail.twoFactorEnabled: email must be a string` (or `twoFactorDisabled`)
|
|
228
|
+
is the user event itself given to the notice: an event names the user by id
|
|
229
|
+
alone. Read the user first:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
const user = await auth.get(event.userId);
|
|
233
|
+
await mail.twoFactorDisabled({ name: user.name, locale: user.locale, email: user.email });
|
|
234
|
+
```
|
|
235
|
+
|
|
225
236
|
### `janusMail.<method>: expiresAt must be a Date`
|
|
226
237
|
|
|
227
238
|
A `TypeError` from `verifyEmail`, `resetPassword` or `signInCode`: the e-mail
|
|
@@ -368,7 +379,23 @@ avoids the read altogether. (In this repository: run `bun run build`.)
|
|
|
368
379
|
|
|
369
380
|
The default templates read `mails/` with `node:fs`, through
|
|
370
381
|
`@nxgt/mail/renderer`: Node, Bun or Deno only. On an edge runtime, pass all
|
|
371
|
-
|
|
382
|
+
seven templates yourself; an inlined build is on the [roadmap](roadmap.md).
|
|
383
|
+
|
|
384
|
+
### An e-mail stays light in dark mode
|
|
385
|
+
|
|
386
|
+
Two causes, neither an error:
|
|
387
|
+
|
|
388
|
+
- **Gmail.** Its web and mobile clients cannot be targeted from CSS and
|
|
389
|
+
always show the light e-mail. Every other client that reads
|
|
390
|
+
`prefers-color-scheme`, or Outlook's `[data-ogsc]`, shows the dark one.
|
|
391
|
+
- **A template of your own.** The dark rules are in the default HTML, built
|
|
392
|
+
by `@nxgt/mail-ui`. An override that returns its own `html` has none of
|
|
393
|
+
them; build it with `@nxgt/mail-ui` 0.4.0 or later to follow dark mode:
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
janusMail({ mailer, from, brand, links, templates: { verifyEmail: myVerifyEmail } });
|
|
397
|
+
// myVerifyEmail's html needs its own color-scheme and dark rules
|
|
398
|
+
```
|
|
372
399
|
|
|
373
400
|
## Compile errors
|
|
374
401
|
|
|
@@ -398,7 +425,7 @@ whole.
|
|
|
398
425
|
### `TS2739: Type '{ … }' is missing the following properties from type 'JanusMailTemplates<…>'`
|
|
399
426
|
|
|
400
427
|
`locales` holds a locale beyond `en` and `fr`, and `templates` does not give
|
|
401
|
-
all
|
|
428
|
+
all seven. See [Adding a locale](guide/locales.md#adding-a-locale).
|
|
402
429
|
|
|
403
430
|
### `TS2322: Type '"de"' is not assignable to type '"en" | "fr"'.`
|
|
404
431
|
|
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en" dir="ltr" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
|
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
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="x-apple-disable-message-reformatting">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
-
<meta name="color-scheme" content="light">
|
|
8
|
-
<meta name="supported-color-schemes" content="light">
|
|
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-light-only{display:none!important;}[data-ogsb] .nx-light-only{display:none!important;}[data-ogsc] .nx-dark-only{display:
|
|
12
|
+
inline-block!important;}[data-ogsb] .nx-dark-only{display:inline-block!important;}
|
|
13
|
+
@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
|
|
14
|
+
!important;} }
|
|
15
|
+
</style>
|
|
9
16
|
</head>
|
|
10
|
-
<body xml:lang="en" dir="ltr" style="margin:0;padding:0;width:100%;height:100%;word-break:break-word;background-color:#f4f4f4;"><div style="display:none;">Your account now signs in with a new address. ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
17
|
+
<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;">Your account now signs in with a new address. ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
11
18
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
12
19
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
13
20
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
14
21
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
15
22
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
16
23
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
17
|
-
 ͏  ͏  ͏ </div><span style="display:none">
|
|
24
|
+
 ͏  ͏  ͏  ͏ </div><span style="display:none">
|
|
18
25
|
<!--[if mso]><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings><w:WordDocument><w:DontUseAdvancedTypographyReadingMail/></w:WordDocument></xml>
|
|
19
26
|
<![endif]--></span><div role="article" aria-roledescription="email" lang="en" dir="ltr" style="font-size:medium;font-size:max(16px,1rem)">
|
|
20
|
-
<table role="presentation" cellpadding="0" cellspacing="0" 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;">
|
|
27
|
+
<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;">
|
|
21
28
|
<!--[if mso]>
|
|
22
29
|
<table role="none" cellpadding="0" cellspacing="0" style="width:600px" align="center"><tr><td>
|
|
23
30
|
<![endif]--><div style="margin:0 auto;max-width:600px;">
|
|
24
|
-
<table role="presentation" cellpadding="0" cellspacing="0" style="width:100%;"><tr><td style="padding-bottom:24px;text-align:center;"><span style="font-size:18px;line-height:28px;font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">{{ brand }}</span>
|
|
25
|
-
</td></tr><tr><td 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,
|
|
26
|
-
font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">Your e-mail address was changed</h1><p style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686 -8.51797);">Hello {{ name }},</p><p style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686
|
|
27
|
-
|
|
28
|
-
<table role="presentation" cellpadding="0" cellspacing="0" style="width:100%;"><tr><td style="
|
|
31
|
+
<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>
|
|
32
|
+
</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,
|
|
33
|
+
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);">Your e-mail address was changed</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
|
|
34
|
+
-8.51797);">Your {{ brand }} account now uses {{ newEmail }}. We send this notice to your former address.</p>
|
|
35
|
+
<table role="presentation" cellpadding="0" cellspacing="0" dir="ltr" style="margin-bottom:16px;width:100%;"><tr><td style="border-width:0;border-left-style:solid;border-left-width:8px;border-style:solid;border-color:#f05100;border-color:lab(57.1026% 64.2584 89.8886);background-color:#fef6f2;padding:16px;">
|
|
36
|
+
<table role="presentation" cellpadding="0" cellspacing="0" dir="ltr" style="width:100%;"><tr><td style="vertical-align:top;"><p style="margin:0;font-size:14px;line-height:20px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If this was not you, secure your account now.</p>
|
|
29
37
|
</td></tr></table>
|
|
30
38
|
</td></tr></table><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 -1.05966);text-decoration:none;" href="{{ link }}">
|
|
31
39
|
<!--[if mso]><i style="mso-font-width:114%;mso-text-raise:19px;" hidden> </i>
|
|
32
40
|
<![endif]--> <span style="mso-text-raise:10px;">Undo this change</span>
|
|
33
41
|
<!--[if mso]><i style="mso-font-width:114%;" hidden> ​</i>
|
|
34
|
-
<![endif]--></a></div><div role="separator" style="line-height:24px;">‍</div><p style="margin:0 0 16px;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If the button does not work, open this link: <a href="{{ link }}" style="color:#54a2ff;color:lab(65.0361% -1.42065 -56.9802);text-decoration:underline;">{{ link }}</a></p>
|
|
42
|
+
<![endif]--></a></div><div role="separator" style="line-height:24px;">‍</div><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If the button does not work, open this link: <a href="{{ link }}" style="color:#54a2ff;color:lab(65.0361% -1.42065 -56.9802);text-decoration:underline;">{{ link }}</a></p>
|
|
35
43
|
</td></tr><tr><td style="padding-left:24px;padding-right:24px;padding-top:24px;text-align:center;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);"><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>
|
|
36
44
|
</td></tr></table></div>
|
|
37
45
|
<!--[if mso]>
|
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en" dir="ltr" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
|
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
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="x-apple-disable-message-reformatting">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
-
<meta name="color-scheme" content="light">
|
|
8
|
-
<meta name="supported-color-schemes" content="light">
|
|
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-light-only{display:none!important;}[data-ogsb] .nx-light-only{display:none!important;}[data-ogsc] .nx-dark-only{display:
|
|
12
|
+
inline-block!important;}[data-ogsb] .nx-dark-only{display:inline-block!important;}
|
|
13
|
+
@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
|
|
14
|
+
!important;} }
|
|
15
|
+
</style>
|
|
9
16
|
</head>
|
|
10
|
-
<body xml:lang="en" dir="ltr" style="margin:0;padding:0;width:100%;height:100%;word-break:break-word;background-color:#f4f4f4;"><div style="display:none;">The password of your account was just changed. ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
17
|
+
<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;">The password of your account was just changed. ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
11
18
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
12
19
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
13
20
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
14
21
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
15
22
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
16
23
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
17
|
-
 ͏  ͏ </div><span style="display:none">
|
|
24
|
+
 ͏  ͏  ͏ </div><span style="display:none">
|
|
18
25
|
<!--[if mso]><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings><w:WordDocument><w:DontUseAdvancedTypographyReadingMail/></w:WordDocument></xml>
|
|
19
26
|
<![endif]--></span><div role="article" aria-roledescription="email" lang="en" dir="ltr" style="font-size:medium;font-size:max(16px,1rem)">
|
|
20
|
-
<table role="presentation" cellpadding="0" cellspacing="0" 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;">
|
|
27
|
+
<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;">
|
|
21
28
|
<!--[if mso]>
|
|
22
29
|
<table role="none" cellpadding="0" cellspacing="0" style="width:600px" align="center"><tr><td>
|
|
23
30
|
<![endif]--><div style="margin:0 auto;max-width:600px;">
|
|
24
|
-
<table role="presentation" cellpadding="0" cellspacing="0" style="width:100%;"><tr><td style="padding-bottom:24px;text-align:center;"><span style="font-size:18px;line-height:28px;font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">{{ brand }}</span>
|
|
25
|
-
</td></tr><tr><td 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,
|
|
26
|
-
font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">Your password was changed</h1><p style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686 -8.51797);">Hello {{ name }},</p><p style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686
|
|
27
|
-
|
|
28
|
-
<table role="presentation" cellpadding="0" cellspacing="0" style="width:100%;"><tr><td style="
|
|
31
|
+
<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>
|
|
32
|
+
</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,
|
|
33
|
+
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);">Your password was changed</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
|
|
34
|
+
-8.51797);">The password of your {{ brand }} account was just changed.</p>
|
|
35
|
+
<table role="presentation" cellpadding="0" cellspacing="0" dir="ltr" style="margin-bottom:16px;width:100%;"><tr><td style="border-width:0;border-left-style:solid;border-left-width:8px;border-style:solid;border-color:#f05100;border-color:lab(57.1026% 64.2584 89.8886);background-color:#fef6f2;padding:16px;">
|
|
36
|
+
<table role="presentation" cellpadding="0" cellspacing="0" dir="ltr" style="width:100%;"><tr><td style="vertical-align:top;"><p style="margin:0;font-size:14px;line-height:20px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If this was not you, secure your account now.</p>
|
|
29
37
|
</td></tr></table>
|
|
30
38
|
</td></tr></table><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 -1.05966);text-decoration:none;" href="{{ link }}">
|
|
31
39
|
<!--[if mso]><i style="mso-font-width:114%;mso-text-raise:19px;" hidden> </i>
|
|
32
40
|
<![endif]--> <span style="mso-text-raise:10px;">Secure my account</span>
|
|
33
41
|
<!--[if mso]><i style="mso-font-width:114%;" hidden> ​</i>
|
|
34
|
-
<![endif]--></a></div><div role="separator" style="line-height:24px;">‍</div><p style="margin:0 0 16px;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If the button does not work, open this link: <a href="{{ link }}" style="color:#54a2ff;color:lab(65.0361% -1.42065 -56.9802);text-decoration:underline;">{{ link }}</a></p>
|
|
42
|
+
<![endif]--></a></div><div role="separator" style="line-height:24px;">‍</div><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If the button does not work, open this link: <a href="{{ link }}" style="color:#54a2ff;color:lab(65.0361% -1.42065 -56.9802);text-decoration:underline;">{{ link }}</a></p>
|
|
35
43
|
</td></tr><tr><td style="padding-left:24px;padding-right:24px;padding-top:24px;text-align:center;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);"><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>
|
|
36
44
|
</td></tr></table></div>
|
|
37
45
|
<!--[if mso]>
|
|
@@ -1,35 +1,42 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en" dir="ltr" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
|
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
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="x-apple-disable-message-reformatting">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
-
<meta name="color-scheme" content="light">
|
|
8
|
-
<meta name="supported-color-schemes" content="light">
|
|
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-light-only{display:none!important;}[data-ogsb] .nx-light-only{display:none!important;}[data-ogsc] .nx-dark-only{display:
|
|
12
|
+
inline-block!important;}[data-ogsb] .nx-dark-only{display:inline-block!important;}
|
|
13
|
+
@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
|
|
14
|
+
!important;} }
|
|
15
|
+
</style>
|
|
9
16
|
</head>
|
|
10
|
-
<body xml:lang="en" dir="ltr" style="margin:0;padding:0;width:100%;height:100%;word-break:break-word;background-color:#f4f4f4;"><div style="display:none;">Choose a new password for your account. ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
17
|
+
<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;">Choose a new password for your account. ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
11
18
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
12
19
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
13
20
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
14
21
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
15
22
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
16
23
|
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏
|
|
17
|
-
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏ </div><span style="display:none">
|
|
24
|
+
 ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏  ͏ </div><span style="display:none">
|
|
18
25
|
<!--[if mso]><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings><w:WordDocument><w:DontUseAdvancedTypographyReadingMail/></w:WordDocument></xml>
|
|
19
26
|
<![endif]--></span><div role="article" aria-roledescription="email" lang="en" dir="ltr" style="font-size:medium;font-size:max(16px,1rem)">
|
|
20
|
-
<table role="presentation" cellpadding="0" cellspacing="0" 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;">
|
|
27
|
+
<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;">
|
|
21
28
|
<!--[if mso]>
|
|
22
29
|
<table role="none" cellpadding="0" cellspacing="0" style="width:600px" align="center"><tr><td>
|
|
23
30
|
<![endif]--><div style="margin:0 auto;max-width:600px;">
|
|
24
|
-
<table role="presentation" cellpadding="0" cellspacing="0" style="width:100%;"><tr><td style="padding-bottom:24px;text-align:center;"><span style="font-size:18px;line-height:28px;font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">{{ brand }}</span>
|
|
25
|
-
</td></tr><tr><td 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,
|
|
26
|
-
font-weight:600;color:#020918;color:lab(2.35721% .367686 -8.51797);">Reset your password</h1><p style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686 -8.51797);">Hello {{ name }},</p><p style="margin:0 0 16px;font-size:14px;line-height:20px;color:#020918;color:lab(2.35721% .367686 -8.51797);">
|
|
27
|
-
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 -1.05966);text-decoration:none;" href="{{ link }}">
|
|
31
|
+
<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>
|
|
32
|
+
</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,
|
|
33
|
+
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);">Reset your password</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 -8.51797);">
|
|
34
|
+
Someone asked to reset the password of your {{ brand }} account. Choose a new one with the button below.</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 -1.05966);text-decoration:none;" href="{{ link }}">
|
|
28
35
|
<!--[if mso]><i style="mso-font-width:114%;mso-text-raise:19px;" hidden> </i>
|
|
29
36
|
<![endif]--> <span style="mso-text-raise:10px;">Choose a new password</span>
|
|
30
37
|
<!--[if mso]><i style="mso-font-width:114%;" hidden> ​</i>
|
|
31
|
-
<![endif]--></a></div><div role="separator" style="line-height:24px;">‍</div><p 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 style="margin:0 0 16px;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If the button does not work, open this link: <a href="{{ link }}" style="color:#54a2ff;
|
|
32
|
-
link }}</a></p><p style="margin:0 0 16px;font-size:10px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If you did not ask for this, you can ignore this e-mail.</p>
|
|
38
|
+
<![endif]--></a></div><div role="separator" style="line-height:24px;">‍</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:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If the button does not work, open this link: <a href="{{ link }}" style="color:#54a2ff;
|
|
39
|
+
color:lab(65.0361% -1.42065 -56.9802);text-decoration:underline;">{{ link }}</a></p><p class="nx-dark-text-foreground" style="margin:0 0 16px;font-size:10px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);">If you did not ask for this, you can ignore this e-mail.</p>
|
|
33
40
|
</td></tr><tr><td style="padding-left:24px;padding-right:24px;padding-top:24px;text-align:center;font-size:12px;line-height:16px;color:#62748e;color:lab(48.0876% -2.03595 -16.5814);"><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>
|
|
34
41
|
</td></tr></table></div>
|
|
35
42
|
<!--[if mso]>
|