发布于 2026-01-06 2 阅读
0

重新发送 - 如何向 Novu 添加电子邮件 API 提供商

重新发送 - 如何向 Novu 添加电子邮件 API 提供商

TL;DR:有一句流行的说法是这样的:你只有把某件事教给别人,才真正了解它

在本教程中,我将向您展示如何向 Novu添加新的电子邮件 API 提供商。在本例中,我添加了Resend

Novu简介

Novu 是一项开源服务,提供统一的 API 和组件,可通过多种渠道发送通知,包括应用内、推送、电子邮件、短信和聊天。

使用 Novu,您再也不需要自己开发应用内通知,也不需要手动在应用中集成数十个通信 API。

应用内通知中心

开始使用

前往 GitHub 克隆Novu 代码库。顺便也给代码库点个星标吧。😉

接下来,从该next分支创建一个新分支。

git checkout -b add-resend-email-provider next
Enter fullscreen mode Exit fullscreen mode

安装 Novu 项目中的软件包:

npm install
Enter fullscreen mode Exit fullscreen mode

设置新的电子邮件服务提供商

运行以下命令,即可轻松创建添加新电子邮件提供商所需的模板。

npm run generate:provider
Enter fullscreen mode Exit fullscreen mode

它会生成如下提示:

> generate:provider
> npx hygen provider new

? What type of provider is this? …
❯ EMAIL
  SMS
  PUSH
  CHAT
Enter fullscreen mode Exit fullscreen mode
  • 选择电子邮件作为提供商类型。
  • 添加电子邮件 API 提供商的名称。这里,我添加了resend

按下键盘上Return的 或Enter键后,模板就会生成。你应该会在终端中看到它们,如下所示:

added: providers/resend/.czrc
added: providers/resend/.eslintrc.json
added: providers/resend/.gitignore
added: providers/resend/jest.config.js
added: providers/resend/package.json
added: providers/resend/README.md
added: providers/resend/src/index.ts
added: providers/resend/src/lib/repend.provider.ts
added: providers/resend/src/lib/repend.provider.spec.ts
added: providers/resend/tsconfig.json
added: providers/resend/tsconfig.module.json
Enter fullscreen mode Exit fullscreen mode

这些文件位于该/providers/resend目录中。在编辑器中导航到/providers/resend/src/lib/resend.provider.ts该目录,您应该会看到一个可供参考的模板代码:

import {
  ChannelTypeEnum,
  ISendMessageSuccessResponse,
  IEmailOptions,
  IEmailProvider,
} from '@novu/stateless';

export class ResendEmailProvider implements IEmailProvider {
  channelType = ChannelTypeEnum.EMAIL as ChannelTypeEnum.EMAIL;

  constructor(
    private config: {
      apiKey: string;
    }
  ) {
  }

  async sendMessage(
    options: IEmailOptions
  ): Promise<ISendMessageSuccessResponse> {


    return {
      id: 'PLACEHOLDER',
      date: 'PLACEHOLDER'
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

/providers/resend/src/lib/resend.provider.ts

编写代码发送电子邮件

幸好我们有一个很棒的模板可以作为起点。接下来我们将编写代码。

注意:我已经注册了 Resend 并获得了我的 API 密钥。如果您还没有在您的电子邮件服务提供商平台上创建帐户,现在是时候创建了。

我已将发送电子邮件所需的完整代码添加到此文件中,代码如下所示。

import {
  ChannelTypeEnum,
  ISendMessageSuccessResponse,
  ICheckIntegrationResponse,
  CheckIntegrationResponseEnum,
  IEmailOptions,
  IEmailProvider,
} from '@novu/stateless';
import { Resend } from 'resend';

export class ResendEmailProvider implements IEmailProvider {
  id = 'resend';
  channelType = ChannelTypeEnum.EMAIL as ChannelTypeEnum.EMAIL;
  private resendClient: Resend;

  constructor(
    private config: {
      apiKey: string;
      from: string;
    }
  ) {
    this.resendClient = new Resend(this.config.apiKey);
  }

  async sendMessage(
    options: IEmailOptions
  ): Promise<ISendMessageSuccessResponse> {
    const response: any = await this.resendClient.sendEmail({
      from: options.from || this.config.from,
      to: options.to,
      subject: options.subject,
      text: options.text,
      html: options.html,
      cc: options.cc,
      attachments: options.attachments?.map((attachment) => ({
        filename: attachment?.name,
        content: attachment.file,
      })),
      bcc: options.bcc,
    });

    return {
      id: response.id,
      date: new Date().toISOString(),
    };
  }

  async checkIntegration(
    options: IEmailOptions
  ): Promise<ICheckIntegrationResponse> {
    try {
      await this.resendClient.sendEmail({
        from: options.from || this.config.from,
        to: options.to,
        subject: options.subject,
        text: options.text,
        html: options.html,
        cc: options.cc,
        attachments: options.attachments?.map((attachment) => ({
          filename: attachment?.name,
          content: attachment.file,
        })),
        bcc: options.bcc,
      });

      return {
        success: true,
        message: 'Integrated successfully!',
        code: CheckIntegrationResponseEnum.SUCCESS,
      };
    } catch (error) {
      return {
        success: false,
        message: error?.message,
        code: CheckIntegrationResponseEnum.FAILED,
      };
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

以下是对上述代码的详细分析:

  • 从 resend 库导入 resend。
import { Resend } from 'resend';
Enter fullscreen mode Exit fullscreen mode

注意:请确保将电子邮件 API 客户端库安装在电子邮件提供商文件夹的根目录中。在本例中,请将其安装在NOVU 项目的根目录中/apps/providers/resend而不是 NOVU 项目的根目录中。

  • 设置id = 'resend'。这是 Novu 在项目的其他部分识别此提供商的标识符。

  • 初始化电子邮件客户端,并在构造函数中将其设置为接受 API 密钥。

...
private resendClient: Resend;

  constructor(
    private config: {
      apiKey: string;
      from: string;
    }
  ) {
    this.resendClient = new Resend(this.config.apiKey);
  }
...
Enter fullscreen mode Exit fullscreen mode
  • sendMessage方法包含发送电子邮件和返回响应所需的代码。

  • checkIntegration方法几乎是原方法的复制sendMessage。它用于测试电子邮件集成是否正常工作。

添加电子邮件服务提供商徽标

我们需要让新的邮件服务提供商出现在 Novu 控制面板的集成商店中。深色和浅色模式的图标都应该显示出来。

请前往apps/web/public/static/images/providers/dark相应apps/web/public/static/images/providers/light目录,分别查看深色和浅色模式的徽标。徽标名称应为提供商名称。支持的格式为svgpng

就我而言,我添加了resend.svg

浅色模式
apps/web/public/static/images/providers/light/resend.svg

深色模式
apps/web/public/static/images/providers/dark/resend.svg

构建 UI 集成商店

别担心,我们不需要编写任何 CSS 代码。😄

我们需要向 Novu 提供一些关于我们新邮件服务提供商的详细信息,以便它构建 UI 集成商店。信息分为两部分:

  • 创建凭据配置
  • 将提供商配置添加到提供商列表

创建凭据配置:

我们需要添加与服务提供商集成所需的凭据。请添加libs/shared/src/consts/providers/credentials/provider-credentials.ts如下所示的配置对象:

export const resendConfig: IConfigCredentials[] = [
  {
    key: CredentialsKeyEnum.ApiKey,
    displayName: 'API Key',
    type: 'string',
    required: true,
  },
  ...mailConfigBase,
];
Enter fullscreen mode Exit fullscreen mode

provider-credentials.ts

将提供商配置添加到提供商列表:

将新的电子邮件提供商数据添加到列表中libs/shared/src/consts/providers/channels/email.ts

注意: id是提供商的名称,displayName是提供商的 Pascal 命名法名称,credentials是您在上一步中创建的凭据,logoFileName应该与添加徽标步骤中的相同(包括格式类型)。


import {
  ...
  resendConfig,
} from '../credentials';

export const emailProviders: IProviderConfig[] = [
...
...
{
    id: EmailProviderIdEnum.Resend,
    displayName: 'Resend',
    channel: ChannelTypeEnum.EMAIL,
    credentials: resendConfig,
    docReference: 'https://resend.com/docs',
    logoFileName: { light: 'resend.svg', dark: 'resend.svg' },
}];
Enter fullscreen mode Exit fullscreen mode

libs/shared/src/consts/providers/channels/email.ts

在 API 中添加提供程序处理程序

导航至apps/api目录。

  • 我们将首先向API 添加提供商依赖项

在运行创建模板命令的步骤中,项目创建了一个独立的提供程序包,该包将发布到 NPM。在我们的开发环境中,该包尚未发布。

要在本地使用它,请前往位于 `<package_name>` 的 `package.json` 文件apps/api/package.json,并手动将其添加到依赖项列表中:`"@novu/": "^VERSION"`

"@novu/resend": "^0.11.0"
Enter fullscreen mode Exit fullscreen mode

apps/api/package.json

VERSION的值应该是当时 package.json 中的版本号。

完成后,运行命令npm build以使我们刚刚所做的更改生效!

  • 接下来,我们将在 API 中创建提供程序处理程序

为了在内部映射不同的提供商凭据,我们需要添加一个位于apps/api/src/app/events/services/mail-service/handlers目录中的提供商处理程序。

在此目录下创建一个resend.handler.ts文件,并将以下代码添加到该文件中。

import { ChannelTypeEnum } from '@novu/shared';
import { ICredentials } from '@novu/dal';
import { ResendEmailProvider } from '@novu/resend';
import { BaseHandler } from './base.handler';

export class ResendHandler extends BaseHandler {
  constructor() {
    super('resend', ChannelTypeEnum.EMAIL);
  }
  buildProvider(credentials: ICredentials, from?: string) {
    const config: { apiKey: string; from: string } = { from: from as string, apiKey: credentials.apiKey as string };

    this.provider = new ResendEmailProvider(config);
  }
}
Enter fullscreen mode Exit fullscreen mode

重新发送处理程序.ts

  • 将最近重新创建的处理程序导出到index.ts文件(仍在 handlers 目录中)
...
export * from './resend.handler';
Enter fullscreen mode Exit fullscreen mode

handlers/index.ts

  • 最后,我们将处理程序添加到工厂中

工厂位于apps/api/src/app/events/services/mail-service/mail.factory.ts

添加重发处理程序,如下所示:

import { IntegrationEntity } from '@novu/dal';
import {
  ...
  ...
  ResendHandler,
} from './handlers';

import { IMailHandler } from './interfaces/send.handler.interface';

export class MailFactory {
  handlers: IMailHandler[] = [
    ...
    ...
    new ResendHandler(),
  ];

  ...
}
Enter fullscreen mode Exit fullscreen mode

apps/api/src/app/events/services/mail-service/mail.factory.ts

构建和运行 Novu

要成功运行该项目,请从 Novu 目录的根目录进行构建:

pnpm build
Enter fullscreen mode Exit fullscreen mode
  • 在一个终端中导航到/apps/api并运行“pnpm start”命令。
  • /apps/web在另一个终端中导航并运行“pnpm start”。

您应该能够登录、激活新的电子邮件服务提供商并成功连接。

呼吁大家为开源软件做贡献

这是我提交的 PR,目的是为 Novu 添加 Resend 功能

就我个人而言,开源极大地改变了我的生活和职业生涯。所以,如果你也是:

  • 寻找提升技能的方法,
  • 正在寻找你的第一个开源软件项目?
  • 经验丰富,并且想在开源软件领域做一些有意义的事情。
  • 想为开源软件做贡献

那么我建议你为Novu做贡献。

结论

希望您和我一样喜欢这篇指南。它涵盖了向 Novu 添加电子邮件服务提供商所需的一切信息。此流程同样适用于添加短信和推送通知服务提供商。

Novu 提供了一种最简单便捷的方式,帮助开发者通过单个 API 管理多渠道通知。

还有一件事。我想了解一下您目前是如何通过多个渠道向用户发送通知的。请在下方评论区留言告诉我!

文章来源:https://dev.to/novu/resend-how-to-add-an-email-api-provider-to-novu-49cd