Skip to main content
Glama
index.ts5.93 kB
import type { Transporter } from "nodemailer"; import nodemailer from "nodemailer"; import { render } from "@react-email/render"; import AWSVerifyEmail from "./emails/aws-verify-email"; import VerifySubscriptionEmail from "./emails/verify-subscription"; const isDevelopment = process.env.NODE_ENV === "development"; // 开发环境使用 MailHog const devTransporter: Transporter = nodemailer.createTransport({ host: "localhost", port: 1025, secure: false, auth: { user: "test", pass: "test", }, }); // 生产环境使用 Nodemailer const prodTransporter: Transporter = nodemailer.createTransport({ host: process.env.MAIL_HOST, port: Number(process.env.MAIL_PORT), secure: true, auth: { user: process.env.MAIL_USER, pass: process.env.MAIL_PASSWORD, }, }); interface SendMagicLinkParams { to: string; subject: string; html: string; text: string; } interface SendAwsVerificationEmailParams { to: string; verificationCode: string; } export async function sendAwsVerificationEmail(params: SendAwsVerificationEmailParams) { const { to, verificationCode } = params; const subject = "OpenMCP 账户验证"; const emailHtml = await render(AWSVerifyEmail({ verificationCode })); const emailText = `您的 OpenMCP 验证码是:${verificationCode}。此验证码将在 10 分钟后过期。`; const transporter = isDevelopment ? devTransporter : prodTransporter; try { await transporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html: emailHtml, text: emailText, }); return { success: true }; } catch (error) { console.error(`${isDevelopment ? "开发" : "生产"}环境发送验证邮件失败:`, error); throw new Error("发送验证邮件失败"); } } export async function sendMagicLink(params: SendMagicLinkParams) { const { to, subject, html, text } = params; if (isDevelopment) { // 开发环境使用 MailHog try { await devTransporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html, text, }); return { success: true }; } catch (error) { console.error("开发环境发送邮件失败:", error); throw new Error("发送邮件失败"); } } else { // 生产环境使用 Nodemailer try { await prodTransporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html, text, }); return { success: true }; } catch (error) { console.error("生产环境发送邮件失败:", error); throw new Error("发送邮件失败"); } } } interface SendValidationEmailParams { to: string; subject: string; code: string } export async function sendValidationEmail(params: SendValidationEmailParams) { const { to, subject, code } = params; if (isDevelopment) { await devTransporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html: `<p>您的验证码是:${code}</p>`, text: `您的验证码是:${code}`, }); } else { await prodTransporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html: `<p>您的验证码是:${code}</p>`, text: `您的验证码是:${code}`, }); } } interface SendMagicLinkEmailParams { to: string; code: string; subject: string; magicLink: string; } export async function sendMagicLinkEmail(params: SendMagicLinkEmailParams) { const { to, magicLink, code, subject } = params; // const subject = "OpenMCP 一键登录"; const emailHtml = await render(AWSVerifyEmail({ magicLink })); const emailText = `点击此链接登录 OpenMCP:${magicLink}。此链接将在 10 分钟后过期。`; const transporter = isDevelopment ? devTransporter : prodTransporter; try { await transporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html: emailHtml, text: emailText, }); return { success: true }; } catch (error) { console.error(`${isDevelopment ? "开发" : "生产"}环境发送魔法链接邮件失败:`, error); throw new Error("发送魔法链接邮件失败"); } } /** * 只发送验证码的邮件 * @param params * @returns */ export async function sendMagicCodeEmail(params: { to: string; code: string; subject: string; }) { const { to, code, subject } = params; // const subject = "OpenMCP 一键登录"; const emailHtml = await render(AWSVerifyEmail({ verificationCode: code, subject })); const transporter = isDevelopment ? devTransporter : prodTransporter; try { await transporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html: emailHtml, text: emailHtml, }); return { success: true }; } catch (error) { console.error(`${isDevelopment ? "开发" : "生产"}环境发送魔法链接邮件失败:`, error); throw new Error("发送魔法链接邮件失败"); } } export async function sendVerificationEmail(to: string, token: string) { const verifyUrl = `${process.env.BETTER_AUTH_URL}/auth/verify?token=${token}`; const unsubscribeUrl = `${process.env.BETTER_AUTH_URL}/web/unsubscribe?email=${encodeURIComponent(to)}&token=${token}`; const subject = "验证您的邮箱订阅"; const html = await render( VerifySubscriptionEmail({ verifyUrl, unsubscribeUrl, }) ); const transporter = isDevelopment ? devTransporter : prodTransporter; await transporter.sendMail({ from: process.env.MAIL_FROM || "OpenMCP <noreply@julianshuke.com>", to, subject, html: html, text: html, }); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/metacode0602/open-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server