重新启动 - 如何将电子邮件API提供商添加到NOVU
#javascript #编程 #email #notification

tl; dr:有这样一个流行的俗话: 您永远不会真正知道某事,直到您向别人教

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

简介诺夫

novu是一项开源服务,可提供统一的API和组件,可通过多个渠道发送通知,包括应用程序内,推送,电子邮件,SMS和聊天。

使用novu,您无需自己滚动自己的in-app notification或在您的应用中手动整合数十个通信API。

In-app Notification Center

开始

前往github,克隆Novu repo。当您使用时,请随时播放回购。 ð

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

git checkout -b add-resend-email-provider next

在Novu项目中安装软件包:

npm install

设置新的电子邮件提供商

运行下面的命令以无缝创建添加新电子邮件提供商所需的模板。

npm run generate:provider

它生成了这样的提示:

> generate:provider
> npx hygen provider new

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

在键盘上击中ReturnEnter后,将生成模板。您应该像这样在终端中看到它们:

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

这些文件位于apps/providers/resend目录中。导航到编辑器中的apps/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'
    };
  }
}

apps/provers/resend/src/lib/resend.provider.ts

写代码发送电子邮件

值得庆幸的是,我们有一个很棒的模板可以启动。我们将继续编写代码。

注意:我已经在重新启动时注册并可以访问我的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,
      };
    }
  }
}

这是上述代码的细分:

  • 从重新发送库中导入重新汇总。
import { Resend } from 'resend';

注意:确保您将电子邮件API客户端库安装在电子邮件提供者文件夹的根部。在这种情况下:/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);
  }
...
  • sendMessage方法包含发送电子邮件并返回响应所需的代码。

  • checkIntegration方法几乎是sendMessage方法的副本。测试电子邮件集成起作用是需要的。

添加电子邮件提供商徽标

我们需要新的电子邮件提供商出现在Novu仪表板上的集成商店中。黑暗模式徽标应存在。

分别转到apps/web/public/static/images/providers/darkapps/web/public/static/images/providers/light目录以及黑暗和光模式徽标。徽标的名称应为提供商的名称。可能的格式是 svg png

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

Light Mode
apps/web/public/static/images/provers/light/resend.svg

Dark Mode
apps/web/public/static/images/provers/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,
];

提供商 - 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' },
}];

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

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

导航到apps/api目录。

  • 我们将从开始,将提供商的依赖性添加到API

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

为了在本地使用它,请转到apps/api/package.json中的json。

"@novu/resend": "^0.11.0"

apps/api/package.json

版本的值应该是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);
  }
}

resend.handler.ts

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

处理程序/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(),
  ];

  ...
}

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

构建并运行Novu

成功地运行项目,从Novu目录的根部构建:

pnpm build
  • 导航到/apps/api并在一个终端运行pnpm启动
  • 导航到/apps/web并在另一个终端运行pnpm启动。

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

打电话给开源的电话

这是my PR to add Resend to Novu

就个人而言,开源改变了我的生活和职业。因此,如果您是:

  • 寻找磨练您技能的方法,
  • 寻找您的第一个OSS项目
  • 经验丰富,想在OSS中做一些有意义的事情,
  • 想为OSS做出贡献

..然后我建议您为Novu贡献。

结论

我希望您喜欢写这本指南,就像我喜欢写这本指南一样。它涵盖了将电子邮件提供商添加到Novu所需的一切。也可以采用此流程来添加SMS和推送通知提供商。

Novu提供了最简单,最简单的方法来帮助开发人员使用单个API管理多通道通知。

另外一件事。我想知道您当前如何处理通过多个渠道向用户发送通知的方式。请让我在下面的评论部分中知道!