-
Notifications
You must be signed in to change notification settings - Fork 28
/
send-server-email.ts
109 lines (93 loc) 路 2.71 KB
/
send-server-email.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import {NextAuthOptions, Theme} from 'next-auth'
import {createHash} from 'crypto'
import type {
HTMLEmailParams,
MagicLinkEmailType,
TextEmailParams,
} from './send-verification-request'
import {sendVerificationRequest} from './send-verification-request'
import {v4} from 'uuid'
const baseUrl = process.env.NEXTAUTH_URL || process.env.VERCEL_URL
function hashToken(token: string, options: any) {
const {provider, secret} = options
return (
createHash('sha256')
// Prefer provider specific secret, but use default secret if none specified
.update(`${token}${provider.secret ?? secret}`)
.digest('hex')
)
}
export async function createVerificationUrl({
email,
nextAuthOptions,
callbackUrl,
expiresAt,
}: {
email: string
nextAuthOptions: NextAuthOptions | undefined
callbackUrl?: string
expiresAt?: Date
}) {
if (!nextAuthOptions) return
const emailProvider: any = nextAuthOptions.providers.find(
(provider) => provider.id === 'email',
)
callbackUrl = (callbackUrl || baseUrl) as string
const token = (await emailProvider.generateVerificationToken?.()) ?? v4()
const ONE_DAY_IN_SECONDS = 86400
const durationInMilliseconds =
(emailProvider.maxAge ?? ONE_DAY_IN_SECONDS) * 1000
const expires = expiresAt || new Date(Date.now() + durationInMilliseconds)
await nextAuthOptions?.adapter?.createVerificationToken?.({
identifier: email,
token: hashToken(token, {
provider: emailProvider,
secret: nextAuthOptions.secret,
}),
expires,
})
const params = new URLSearchParams({callbackUrl, token, email})
const verificationUrl = `${baseUrl}/api/auth/callback/${emailProvider.id}?${params}`
return {url: verificationUrl, token, expires}
}
export async function sendServerEmail({
email,
callbackUrl,
nextAuthOptions,
type = 'login',
html,
text,
expiresAt,
}: {
email: string
callbackUrl?: string
nextAuthOptions: NextAuthOptions
type?: MagicLinkEmailType
html?: (options: HTMLEmailParams, theme: Theme) => string
text?: (options: TextEmailParams) => string
expiresAt?: Date | null
}) {
const verificationDetails = await createVerificationUrl({
email,
nextAuthOptions,
callbackUrl,
expiresAt: expiresAt || undefined,
})
if (!verificationDetails) return
const {url, token, expires} = verificationDetails
const emailProvider: any = nextAuthOptions.providers.find(
(provider) => provider.id === 'email',
)
console.log('%%% about to sendVerificationRequest %%%')
await sendVerificationRequest({
identifier: email,
url,
theme: nextAuthOptions.theme || {colorScheme: 'auto'},
provider: emailProvider.options,
token: token as string,
expires,
type,
html,
text,
})
}