# @bernierllc/email-service 中文文档

规范地址：https://npmcn.com/package/%40bernierllc/email-service/

版本：6\.0\.10
npm 元数据更新时间：2026-11-05T01:26:56.969Z
中文译文更新时间：2026-11-07T23:50:14.873Z
软件包许可：PROPRIETARY

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40bernierllc/email-service
原文对照：https://npmcn.com/package/%40bernierllc/email-service/?lang=original
项目主页：https://github.com/BernierLLC/tools#readme
源码仓库：https://github.com/BernierLLC/tools

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：70 kB，10 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18\.0\.0
- 运行依赖：13 个
- peer 依赖：nodemailer ^6\.9\.0，@sendgrid/mail ^8\.0\.0
- 首次发布：2025-10-08T02:23:29.112Z
- 最新版本发布：2026-11-05T01:26:56.733Z
- 近 30 天下载量：1976（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：30（近 12 个月 28 个）

## 中文简介

综合电子邮件服务组织模板管理、多供应商交付、跟踪和用户管理

## 安装

```sh
npm install @bernierllc/email-service
```

也可以使用：`pnpm add @bernierllc/email-service`、`yarn add @bernierllc/email-service`、`bun add @bernierllc/email-service`

## README

# @bernierllc/电子邮件服务

综合电子邮件服务组织模板管理、多供应商交付、跟踪和用户管理.

## 特征

-   **多服务支持** - 发送Grid、Mailgun、AWSSES和SMTP
-   **模板管理** - 创建、更新和提供可变替代的电子邮件模板
-   **魔法链接认证** - 无密码登录的安全、有时间限制的认证链接
-   **自动重试逻辑** - 暂时性故障时与焦急的对照
-   **电子邮件验证** - 发送前验证收件人地址(语法、域名、MX记录)
-   **交货跟踪** - 跟踪电子邮件发送,打开、点击和回放
-   **订户管理** - 管理订阅者、名单和偏好
-   **队列集成** - 背景安排和发送电子邮件
-   **Webhook 处理** - 流程提供商为交付活动提供网点
-   **数据库持久性** - 储存模板、交付记录和订户
-   **分析** - 全面交付统计和报告

## 安装

```bash
npm install @bernierllc/email-service
```

### 同伴依赖关系

安装您需要的电子邮件提供者 :

```bash
# SendGrid
npm install @sendgrid/mail

# SMTP (included)
npm install nodemailer
```

## 使用量

### 快速启动

```typescript
import { EmailService } from '@bernierllc/email-service';

const service = new EmailService({
  providers: [
    {
      type: 'smtp',
      smtp: {
        host: 'smtp.gmail.com',
        port: 587,
        secure: false,
        auth: { user: 'you@gmail.com', pass: 'password' }
      }
    }
  ],
  defaultProvider: 'smtp',
  database: {
    type: 'sqlite',
    database: './data/email.db'
  },
  templates: {
    cacheEnabled: true,
    cacheTTL: 3600
  },
  tracking: {
    enabled: true,
    domain: 'yourdomain.com'
  }
});

await service.initialize();

// Send an email
const result = await service.send({
  from: 'noreply@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Welcome!',
  html: '<h1>Hello!</h1><p>Welcome to our service.</p>'
});

console.log(`Email sent: ${result.messageId}`);
```

## 核心概念

### 1\. 多服务电子邮件发送

```typescript
// Configure multiple providers
const service = new EmailService({
  providers: [
    {
      type: 'sendgrid',
      apiKey: process.env.SENDGRID_API_KEY
    },
    {
      type: 'mailgun',
      apiKey: process.env.MAILGUN_API_KEY,
      domain: 'mg.yourdomain.com'
    },
    {
      type: 'ses',
      region: 'us-east-1',
      apiKey: process.env.AWS_ACCESS_KEY,
      secretKey: process.env.AWS_SECRET_KEY
    },
    {
      type: 'smtp',
      smtp: {
        host: 'smtp.gmail.com',
        port: 587,
        secure: false,
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASS
        }
      }
    }
  ],
  defaultProvider: 'sendgrid',
  database: { type: 'sqlite', database: './email.db' }
});

// Send via specific provider
await service.send({
  from: 'noreply@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Test',
  html: '<p>Test</p>',
  provider: 'mailgun' // Override default
});
```

### 2\. 模板管理

```typescript
// Create template
const template = await service.createTemplate({
  name: 'welcome-email',
  subject: 'Welcome {{name}}!',
  html: `
    <h1>Hello {{name}}</h1>
    <p>Welcome to {{company}}!</p>
    <p>Your account email is: {{email}}</p>
  `,
  text: 'Hello {{name}}, welcome to {{company}}!'
});

// Send using template
await service.send({
  from: 'noreply@yourdomain.com',
  to: ['user@example.com'],
  templateId: template.id,
  templateData: {
    name: 'John Doe',
    company: 'Acme Corp',
    email: 'john@example.com'
  }
});

// Update template
await service.updateTemplate(template.id, {
  subject: 'Welcome to {{company}}, {{name}}!',
  html: '<h1>Welcome {{name}}!</h1>'
});

// Get template
const retrieved = await service.getTemplate(template.id);
console.log(retrieved.variables); // ['name', 'company', 'email']

// Delete template
await service.deleteTemplate(template.id);
```

### 3\. 魔法链接认证

发送安全,有时间限制的认证链接用于无密码登录,电子邮件验证,密码重置等.

```typescript
// Configure magic link support
const service = new EmailService({
  providers: [/* ... */],
  database: {/* ... */},
  magicLink: {
    secret: process.env.MAGIC_LINK_SECRET, // Required: Secret key for signing tokens
    expirationMinutes: 30,                  // Optional: Default 60 minutes
    issuer: 'YourApp'                       // Optional: Token issuer name
  }
});

await service.initialize();

// Send magic link for passwordless login
const result = await service.sendMagicLink({
  recipient: 'user@example.com',
  purpose: 'sign in',
  redirectUrl: 'https://app.example.com/auth/verify',
  subject: 'Your Login Link',              // Optional: Custom subject
  expirationMinutes: 15                    // Optional: Override default expiration
});

console.log(result.magicLink);  // https://app.example.com/auth/verify?token=eyJ...
console.log(result.token);      // eyJ... (signed JWT token)
console.log(result.expiresAt);  // 2025-01-15T12:45:00.000Z

// Send with custom data in token
const resetResult = await service.sendMagicLink({
  recipient: 'user@example.com',
  purpose: 'reset your password',
  redirectUrl: 'https://app.example.com/reset-password',
  customData: {
    userId: '12345',
    action: 'password-reset'
  }
});

// Use custom template for magic link email
const welcomeResult = await service.sendMagicLink({
  recipient: 'newuser@example.com',
  purpose: 'verify your email',
  redirectUrl: 'https://app.example.com/verify',
  template: 'welcome-verification',  // Use existing template
  templateData: {
    userName: 'John Doe',
    companyName: 'Acme Corp'
  }
});
```

**魔法链接特性**数字 :

-   使用安全签名符 `@bernierllc/crypto-utils`
-   \* 配置到期时间
-   QQ 自定义数据嵌入符号
-   QQ 默认专业电子邮件模板( 或使用自己的)
-   QQ 自动 URL 参数处理( 已保存查询参数)
-   QQ 对所有电子邮件提供者的支持

**正在校验魔法链接键**数字 :

```typescript
import { verifySignedToken } from '@bernierllc/crypto-utils';

// In your auth/verify endpoint
app.get('/auth/verify', async (req, res) => {
  const token = req.query.token as string;

  try {
    const payload = await verifySignedToken(
      token,
      process.env.MAGIC_LINK_SECRET!
    );

    // Token is valid - log user in
    console.log(payload.email);      // user@example.com
    console.log(payload.purpose);    // 'sign in'
    console.log(payload.customData); // Any custom data you included

    // Create session and redirect
    req.session.userId = payload.email;
    res.redirect('/dashboard');
  } catch (error) {
    // Token expired, invalid, or tampered with
    res.status(401).send('Invalid or expired link');
  }
});
```

### 4\. 重试逻辑和电子邮件验证

自动重试以指数回放和电子邮件地址验证 .

```typescript
const service = new EmailService({
  providers: [/* ... */],
  database: {/* ... */},

  // Retry configuration (optional)
  retry: {
    maxRetries: 3,                  // Number of retry attempts
    initialDelayMs: 1000,           // Initial delay between retries
    maxDelayMs: 30000,              // Maximum delay
    jitter: true,                   // Add randomness to delays
    enableMetrics: true             // Track retry metrics
  },

  // Email validation (optional)
  validation: {
    validateRecipients: true,       // Validate email addresses before sending
    strict: true                    // Use strict validation rules
  }
});

// Emails will automatically retry on transient failures
const result = await service.send({
  to: 'user@example.com',
  subject: 'Test',
  html: '<p>This will retry up to 3 times if it fails</p>'
});

console.log(result.retryCount); // Number of retries that occurred
```

**重试特性**数字 :

-   \* \* 与焦躁相呼应,避免雷鸣群
-   QQ 可配置的最大重试和延迟
-   QQ 在瞬态失败时自动重试
-   \* 重试指标跟踪(尝试、成功、失败)
-   与 `@bernierllc/retry-policy`, (中文(简体) ), `retry-state`,以及 `retry-metrics`

**验证特征**数字 :

-   语法验证(RFC 5322遵守)
-   QQ域验证( 启用严格模式时的 MX 记录检查)
-   QQ 可处理的电子邮件检测
-   ++ 多个收件人验证
-   与 `@bernierllc/email-validator`

### 5\. 交付跟踪

```typescript
// Send email
const result = await service.send({
  from: 'noreply@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Order Confirmation',
  html: '<h1>Thanks for your order!</h1>'
});

// Get delivery record
const delivery = await service.getDelivery(result.deliveryId);
console.log(delivery.status); // 'sent', 'delivered', 'opened', 'clicked', etc.

// Track opens
await service.trackOpen(result.deliveryId);

// Track clicks
await service.trackClick(result.deliveryId);

// Get statistics
const stats = await service.getDeliveryStats();
console.log(`Open rate: ${stats.openRate}%`);
console.log(`Click rate: ${stats.clickRate}%`);
console.log(`Bounce rate: ${stats.bounceRate}%`);

// Get statistics for date range
const monthStats = await service.getDeliveryStats(
  new Date('2025-01-01'),
  new Date('2025-01-31')
);
```

### 4\. 订户管理

```typescript
// Create subscriber
const subscriber = await service.createSubscriber({
  email: 'user@example.com',
  name: 'John Doe',
  lists: ['newsletter', 'updates'],
  tags: ['premium', 'early-adopter'],
  metadata: {
    source: 'website',
    signupDate: new Date()
  }
});

// Get subscriber
const found = await service.getSubscriber(subscriber.id);

// Update subscriber
await service.updateSubscriber(subscriber.id, {
  name: 'John Smith',
  tags: ['premium', 'verified']
});

// Unsubscribe
await service.unsubscribe('user@example.com');

// Create subscriber list
const list = await service.createList(
  'Monthly Newsletter',
  'Our monthly product updates and news'
);
```

### 5\. 排定的电子邮件

```typescript
// Configure queue
const service = new EmailService({
  providers: [/* ... */],
  database: { type: 'sqlite', database: './email.db' },
  queue: {
    backend: new MemoryBackend(),
    concurrency: 5,
    retryPolicy: {
      maxAttempts: 3,
      backoff: { type: 'exponential', delay: 1000 }
    }
  }
});

// Schedule for later
await service.send({
  from: 'noreply@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Reminder',
  html: '<p>This is your reminder</p>',
  scheduledAt: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
});

// Send with priority
await service.send({
  from: 'alerts@yourdomain.com',
  to: ['admin@yourdomain.com'],
  subject: 'URGENT: System Alert',
  html: '<p>Critical alert</p>',
  priority: 'high' // high, normal, low
});
```

### 6\. 散装发送

```typescript
const results = await service.sendBulk([
  {
    from: 'noreply@yourdomain.com',
    to: ['user1@example.com'],
    subject: 'Personalized for User 1',
    html: '<p>Hello User 1</p>'
  },
  {
    from: 'noreply@yourdomain.com',
    to: ['user2@example.com'],
    subject: 'Personalized for User 2',
    html: '<p>Hello User 2</p>'
  }
]);

results.forEach((result, index) => {
  console.log(`Email ${index + 1}: ${result.success ? 'sent' : 'failed'}`);
});
```

### 7\. 网络垃圾处理

```typescript
// Register webhook handler
service.registerWebhookHandler('delivered', async (event) => {
  console.log(`Email ${event.messageId} was delivered`);
  // Update your database, trigger workflows, etc.
});

service.registerWebhookHandler('opened', async (event) => {
  console.log(`Email ${event.messageId} was opened`);
  // Track user engagement
});

service.registerWebhookHandler('clicked', async (event) => {
  console.log(`Link clicked in ${event.messageId}`);
  // Track click-through rates
});

service.registerWebhookHandler('bounced', async (event) => {
  console.log(`Email ${event.messageId} bounced`);
  // Update subscriber status
  await service.unsubscribe(event.data.email);
});

// Process webhook from provider
await service.handleWebhook({
  provider: 'sendgrid',
  event: 'delivered',
  messageId: 'msg_123',
  timestamp: new Date(),
  data: { /* provider-specific data */ }
});
```

## API 参考

### 电子邮件服务

#### 构造器

```typescript
new EmailService(config: EmailServiceConfig)
```

**配置 :**

```typescript
interface EmailServiceConfig {
  providers: ProviderConfig[];
  defaultProvider?: EmailProvider;
  database: DatabaseConfig;
  queue?: QueueOptions;
  templates?: {
    cacheEnabled?: boolean;
    cacheTTL?: number;
  };
  tracking?: {
    enabled?: boolean;
    domain?: string;
  };
  compliance?: {
    unsubscribeLink?: boolean;
    footerRequired?: boolean;
  };
}

interface ProviderConfig {
  type: 'sendgrid' | 'mailgun' | 'ses' | 'smtp';
  apiKey?: string;
  domain?: string;
  region?: string;
  smtp?: SMTPConfig;
  rateLimit?: RateLimitConfig;
}
```

#### 方法

##### 电子邮件发送

-   `send(request: EmailRequest): Promise<SendEmailResult>` - 发送电子邮件
-   `sendBulk(requests: EmailRequest[]): Promise<SendEmailResult[]>` - 发送多封电子邮件

##### 模板管理

-   `createTemplate(request: TemplateCreateRequest): Promise<EmailTemplate>` - 创建模板
-   `getTemplate(id: string): Promise<EmailTemplate | null>` - 获取模板
-   `updateTemplate(id: string, update: TemplateUpdateRequest): Promise<EmailTemplate>` - 更新模板
-   `deleteTemplate(id: string): Promise<boolean>` - 删除模板

##### 交货跟踪

-   `getDelivery(id: string): Promise<DeliveryRecord | null>` - 拿到交货记录
-   `trackOpen(deliveryId: string): Promise<void>` - 跟踪电子邮件打开
-   `trackClick(deliveryId: string): Promise<void>` - 点击音轨链接
-   `getDeliveryStats(startDate?: Date, endDate?: Date): Promise<DeliveryStats>` - 获取统计数据

##### 订户管理

-   `createSubscriber(request: SubscriberCreateRequest): Promise<Subscriber>` - 创建订阅者
-   `getSubscriber(id: string): Promise<Subscriber | null>` - 获取订阅者
-   `updateSubscriber(id: string, update: SubscriberUpdateRequest): Promise<Subscriber>` - 更新用户
-   `unsubscribe(email: string): Promise<boolean>` - 取消订阅电子邮件
-   `createList(name: string, description?: string): Promise<SubscriberList>` - 创建列表

##### Webhook 处理

-   `registerWebhookHandler(event: string, handler: WebhookHandler): void` - 登记员
-   `handleWebhook(event: WebhookEvent): Promise<void>` - 进程网点

##### 生命周期

-   `initialize(): Promise<void>` - 服务初始化
-   `shutdown(): Promise<void>` - 清理和关闭

## 类型定义

```typescript
interface EmailRequest {
  from: EmailAddress | string;
  to: EmailAddress[] | string[];
  cc?: EmailAddress[] | string[];
  bcc?: EmailAddress[] | string[];
  subject: string;
  html?: string;
  text?: string;
  templateId?: string;
  templateData?: TemplateContext;
  attachments?: EmailAttachment[];
  headers?: Record<string, string>;
  tags?: string[];
  metadata?: Record<string, any>;
  priority?: 'high' | 'normal' | 'low';
  scheduledAt?: Date;
  provider?: EmailProvider;
}

interface SendEmailResult {
  success: boolean;
  messageId?: string;
  deliveryId?: string;
  provider?: EmailProvider;
  error?: string;
  timestamp: Date;
  queuedForLater?: boolean;
}

interface DeliveryStats {
  total: number;
  sent: number;
  delivered: number;
  opened: number;
  clicked: number;
  bounced: number;
  failed: number;
  openRate: number;
  clickRate: number;
  bounceRate: number;
}

enum DeliveryStatus {
  QUEUED = 'queued',
  SENDING = 'sending',
  SENT = 'sent',
  DELIVERED = 'delivered',
  OPENED = 'opened',
  CLICKED = 'clicked',
  BOUNCED = 'bounced',
  FAILED = 'failed',
  UNSUBSCRIBED = 'unsubscribed'
}
```

## 最佳做法

### 处理错误

```typescript
try {
  await service.send(emailRequest);
} catch (error) {
  if (error instanceof ProviderError) {
    // Switch to backup provider
    console.error('Provider failed:', error.provider);
  } else if (error instanceof TemplateError) {
    // Template rendering failed
    console.error('Template error:', error.message);
  } else if (error instanceof DeliveryError) {
    // Delivery failed
    console.error('Delivery error:', error.message);
  }
}
```

### 模板变量

```typescript
// Always validate template data matches template variables
const template = await service.getTemplate(templateId);
const missingVars = template.variables.filter(
  v => !(v in templateData)
);
if (missingVars.length > 0) {
  throw new Error(`Missing template variables: ${missingVars.join(', ')}`);
}
```

### 限制费率

```typescript
// Configure per-provider rate limits
const service = new EmailService({
  providers: [
    {
      type: 'sendgrid',
      apiKey: process.env.SENDGRID_API_KEY,
      rateLimit: {
        maxPerSecond: 100,
        maxPerMinute: 5000,
        maxPerHour: 100000
      }
    }
  ],
  // ...
});
```

### 监测

```typescript
// Regular health monitoring
setInterval(async () => {
  const stats = await service.getDeliveryStats();

  if (stats.bounceRate > 5) {
    console.warn('High bounce rate detected:', stats.bounceRate);
  }

  if (stats.failed > 100) {
    console.error('High failure count:', stats.failed);
  }
}, 60000); // Every minute
```

## 依赖关系

此套件的管弦乐 :

-   [@bernierllc/电子邮件发送器](https://npmcn.com/package/core/email-sender) - 多供应商电子邮件发送
-   [@bernierllc/电子邮件-parser](https://npmcn.com/package/core/email-parser) - 电子邮件内容解析
-   [@ bernierllc/ template- 引擎](https://npmcn.com/package/core/template-engine) - 模板渲染
-   [@bernierllc/队列管理器](https://npmcn.com/package/core/queue-manager) - 背景工作处理
-   [@bernierllc/webhook-验证器](https://npmcn.com/package/core/webhook-validator) - 网页记录验证
-   [@bernierllc/数据库调整器](https://npmcn.com/package/core/database-adapter) - 数据持久性
-   [@ bernierllc/ 拖放器](https://npmcn.com/package/core/logger) - 结构化伐木
-   [@bernierlc/ 配置管理器](https://npmcn.com/package/core/config-manager) - 配置管理

## 一体化状况

-   **锁定器**: 集成 - 用于结构化记录的用法@ bennellc/logger
-   **多克套装**: 准备 - 有标记文档
-   **NeverHub 整合**: 计划 - 服务发现和事件总线集成@bernierllc/neverhub-adapter

## 实例

见 [示例目录](https://npmcn.com/package/%40bernierllc/email-service/examples) 用于完整的工作示例:

-   `basic-smtp.ts` - 基本SMTP电子邮件发送
-   `templates.ts` - 模板管理和渲染
-   `tracking.ts` - 交货跟踪和分析
-   `subscribers.ts` - 订户管理
-   `webhooks.ts` - 网页浏览处理
-   `multi-provider.ts` - 多供应商配置

## 许可证

版权(c)2025 Bernier有限责任公司。 版权所有.

这个软件包是专有软件,只许可在它交付的项目范围内使用.

## 常见问题

### @bernierllc/email-service 是什么？

综合电子邮件服务组织模板管理、多供应商交付、跟踪和用户管理

### 如何安装 @bernierllc/email-service？

在项目目录运行 npm install @bernierllc/email-service，或使用 pnpm add / yarn add / bun add。

### @bernierllc/email-service 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @bernierllc/email-service 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @bernierllc/email-service 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @bernierllc/email-service 可以商用吗？

@bernierllc/email-service 使用 PROPRIETARY 许可。声明的许可为 PROPRIETARY，请阅读许可原文确认使用条件。以上为概括，不构成法律意见，请以许可原文为准。

### @bernierllc/email-service 的下载量有多少？

根据 npm 官方下载统计，@bernierllc/email-service 在 2026/10/08 – 2026/11/06 这 30 天内被下载 1,976 次，日均约 66 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @bernierllc/email-service 还在维护吗？

最新版本 6\.0\.10 发布于 2026/11/05（3 天前）；至今共发布 30 个版本，其中过去 12 个月发布了 28 个；首次发布于 2025/10/08。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

