import NextAuth, { NextAuthOptions, Theme } from "next-auth";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/lib/db/prisma";
import EmailProvider from "next-auth/providers/email";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import { createTransport } from "nodemailer";
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID as string,
clientSecret: process.env.GITHUB_SECRET as string,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
}),
EmailProvider({
server: process.env.EMAIL_SERVER,
from: process.env.EMAIL_FROM,
maxAge: 10 * 60, // 10min, 邮箱链接失效时间,默认24小时
async sendVerificationRequest({
identifier: email,
url,
provider,
theme,
}) {
const { host } = new URL(url);
const transport = createTransport(provider.server);
const result = await transport.sendMail({
to: email,
from: provider.from,
subject: `You are logging in to Inke`,
text: text({ url, host }),
html: html({ url, host, theme }),
});
const failed = result.rejected.concat(result.pending).filter(Boolean);
if (failed.length) {
throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
}
},
}),
],
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
/**
*使用HTML body 代替正文内容
*/
function html(params: { url: string; host: string; theme: Theme }) {
const { url, host, theme } = params;
const escapedHost = host.replace(/\./g, ".");
const brandColor = theme.brandColor || "#346df1";
const color = {
background: "#f9f9f9",
text: "#444",
mainBackground: "#fff",
buttonBackground: brandColor,
buttonBorder: brandColor,
buttonText: theme.buttonText || "#fff",
};
return `
Welcome to Inke 🎉
|
|
Button click without response? Try open this link in your browser. If you did not request this email you can safely ignore it.
|
`;
}
/** 不支持HTML 的邮件客户端会显示下面的文本信息 */
function text({ url, host }: { url: string; host: string }) {
return `Welcome to Inke! This is a magic link, click on it to log in ${url}\n`;
}