# @bernierllc/email-sender 中文文档

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

版本：5\.14\.0
npm 元数据更新时间：2026-11-05T01:25:25.853Z
中文译文更新时间：2026-11-07T23:09:24.004Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：564 kB，103 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=18\.0\.0
- 运行依赖：1 个
- peer 依赖：aws-sdk ^2\.1000\.0，nodemailer ^6\.9\.0，@sendgrid/mail ^8\.1\.0
- 首次发布：2025-07-28T23:26:48.547Z
- 最新版本发布：2026-11-05T01:25:25.681Z
- 近 30 天下载量：2498（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：22（近 12 个月 17 个）

## 中文简介

有提供者- 不可知界面和 SendGrid 高级功能的电子邮件发送( 模板、 经核实的发送者、 速率限制)

## 安装

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

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

## README

# @bernierllc/电子邮件发送器

用提供者-不可知界面发送基本电子邮件的核心工具 .

## 特征

-   **提供者-不可知论**: 支持多个电子邮件提供者( SMTP, SendGrid, SES, Mailgun, Postmark)
-   **显示电子邮件安全**: 防止非生产环境中的意外电子邮件发送
-   **类型脚本**: 完整类型脚本支持并严格打字
-   **验证**: 全面的电子邮件和配置验证
-   **附录**: 文件附件的支持
-   **批量发送**: 高效发送多封电子邮件
-   **处理错误**: 有力的错误处理和报告
-   **测试**: 全面试验覆盖率

## 安装

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

**说明**: 此软件包使用对等依赖性 。 您必须分别安装 :

```bash
# For SMTP provider
npm install nodemailer

# For AWS SES provider
npm install aws-sdk
```

## 快速启动

### 基本用途

```typescript
import { EmailSender } from '@bernierllc/email-sender';

// Configure SMTP provider
const config = {
  provider: 'smtp' as const,
  host: 'smtp.gmail.com',
  port: 587,
  secure: false,
  username: 'your-email@gmail.com',
  password: 'your-app-password',
  fromEmail: 'noreply@yourdomain.com',
  fromName: 'Your App',
};

// Create email sender
const emailSender = new EmailSender(config);

// Send an email
const result = await emailSender.sendEmail({
  toEmail: 'recipient@example.com',
  toName: 'John Doe',
  subject: 'Welcome to our app!',
  htmlContent: '<h1>Welcome!</h1><p>Thank you for joining us.</p>',
  textContent: 'Welcome! Thank you for joining us.',
});

if (result.success) {
  console.log('Email sent successfully:', result.messageId);
} else {
  console.error('Failed to send email:', result.errorMessage);
}
```

### 发送Grid 配置

```typescript
import { EmailSender } from '@bernierllc/email-sender';

const config = {
  provider: 'sendgrid' as const,
  apiKey: 'your-sendgrid-api-key',
  fromEmail: 'noreply@yourdomain.com',
  fromName: 'Your App',
  // Optional: point every SendGrid call (mail send, templates, senders) at
  // another host, e.g. a local mock in tests. Give the bare origin; a
  // trailing `/v3` is also accepted. Defaults to https://api.sendgrid.com.
  endpoint: process.env.SENDGRID_API_BASE_URL,
};

const emailSender = new EmailSender(config);
```

### AWS SES 配置

```typescript
import { EmailSender } from '@bernierllc/email-sender';

const config = {
  provider: 'ses' as const,
  apiKey: 'your-aws-access-key',
  secretKey: 'your-aws-secret-key',
  region: 'us-east-1',
  fromEmail: 'noreply@yourdomain.com',
  fromName: 'Your App',
  sandbox: false, // Set to true if in SES sandbox mode
};

const emailSender = new EmailSender(config);
```

### 邮件枪配置

```typescript
import { EmailSender } from '@bernierllc/email-sender';

const config = {
  provider: 'mailgun' as const,
  apiKey: 'your-mailgun-api-key',
  domain: 'yourdomain.com',
  region: 'us', // or 'eu' for European region
  fromEmail: 'noreply@yourdomain.com',
  fromName: 'Your App',
};

const emailSender = new EmailSender(config);
```

### 邮戳配置

```typescript
import { EmailSender } from '@bernierllc/email-sender';

const config = {
  provider: 'postmark' as const,
  apiKey: 'your-postmark-api-key',
  accountToken: 'your-postmark-account-token', // Optional, for template operations
  fromEmail: 'noreply@yourdomain.com',
  fromName: 'Your App',
};

const emailSender = new EmailSender(config);
```

## API 参考

### 电子邮件发送器

发送邮件的主课.

#### 构造器

```typescript
new EmailSender(config: EmailProviderConfig)
```

#### 方法

##### `sendEmail(email: EmailMessage): Promise<SendResult>`

发送一个电子邮件.

```typescript
const result = await emailSender.sendEmail({
  toEmail: 'recipient@example.com',
  subject: 'Test Email',
  htmlContent: '<h1>Hello</h1>',
});
```

##### `sendBatch(emails: EmailMessage[]): Promise<SendResult[]>`

分批发送多封邮件 .

```typescript
const results = await emailSender.sendBatch([
  { toEmail: 'user1@example.com', subject: 'Email 1', htmlContent: '<h1>Email 1</h1>' },
  { toEmail: 'user2@example.com', subject: 'Email 2', htmlContent: '<h1>Email 2</h1>' },
]);
```

##### `validateConfiguration(): EmailValidationResult`

验证提供者配置 .

```typescript
const validation = emailSender.validateConfiguration();
if (!validation.isValid) {
  console.error('Configuration errors:', validation.errors);
}
```

##### `validateEmailMessage(email: EmailMessage): EmailValidationResult`

发送前验证电子邮件信息 .

```typescript
const validation = emailSender.validateEmailMessage(email);
if (!validation.isValid) {
  console.error('Email validation errors:', validation.errors);
}
```

##### `testConnection(): Promise<boolean>`

测试连接到电子邮件提供者 .

```typescript
const isConnected = await emailSender.testConnection();
if (isConnected) {
  console.log('Connection successful');
} else {
  console.error('Connection failed');
}
```

##### `getCapabilities(): EmailProviderCapabilities`

获取当前提供者的能力.

```typescript
const capabilities = emailSender.getCapabilities();
console.log('Supports attachments:', capabilities.supportsAttachments);
console.log('Max batch size:', capabilities.maxBatchSize);
```

### 类型

#### 电子邮件信

```typescript
interface EmailMessage {
  toEmail: string;
  toName?: string;
  fromEmail?: string;
  fromName?: string;
  subject: string;
  htmlContent?: string;
  textContent?: string;
  replyTo?: string;
  headers?: Record<string, string>;
  attachments?: EmailAttachment[];
  metadata?: Record<string, any>;
  /** Per-message open, click and UTM tracking; omitted = the provider account's default. */
  tracking?: { opens?: boolean; clicks?: boolean; utm?: boolean };
}
```

`tracking: { clicks: false }` 在下面的提供者上保留无法重写HTML和文本部分的链接,这是一次性链接(签名、邀请、密码重置)所需要的。 它映射到 SendGrid `tracking_settings`邮件枪 `o:tracking-clicks`编号 :`o:tracking-opens`邮戳 `TrackLinks`编号 :`TrackOpens` (邮戳忽略 `opens: false` 在服务器一级打开跟踪)和Mandrill `track_clicks`编号 :`track_opens`;不跟踪的提供者忽略了它. SMTP2GO设定只跟踪每个API密钥,并忽略了该覆盖,所以使用一个按下跟踪键进行一次性链接.

`tracking: { utm: false }` 停止将分析查询参数(UTM标签)附加到链接中;使其未定义账户默认值。 它不停止点击跟踪: 链接只按逐字记录 `{ clicks: false, utm: false }`。 。 。 . `utm: true` 强制标记使用账户的 UTM 值 。 只有SendGrid尊重它(`tracking_settings.ganalytics`每个供养者都忽视它 `getCapabilities().features.utmTracking` 说是哪个.

#### 电子邮件连接

```typescript
interface EmailAttachment {
  filename: string;
  content: string; // Base64 encoded
  contentType?: string;
  disposition?: 'attachment' | 'inline';
}
```

#### 发送结果

```typescript
interface SendResult {
  success: boolean;
  messageId?: string;
  errorMessage?: string;
  providerResponse?: any;
  metadata?: Record<string, any>;
}
```

#### 电子邮件 ProviderConfig

```typescript
interface EmailProviderConfig {
  provider: 'sendgrid' | 'ses' | 'mailgun' | 'postmark' | 'smtp';
  apiKey?: string;
  region?: string;
  endpoint?: string;
  fromEmail: string;
  fromName?: string;
  replyTo?: string;
  webhookUrl?: string;
  webhookSecret?: string;
  sandbox?: boolean;
  // SMTP specific options
  host?: string;
  port?: number;
  secure?: boolean;
  username?: string;
  password?: string;
}
```

## 提供者的能力

每个供应商通过下列途径暴露其能力: `getCapabilities()` 方法。 能力接口既包括遗留布尔旗,也包括扩大的旗帜 `features` 用于精细能力检查的地图.

### 电子邮件提供能力接口

```typescript
interface EmailProviderCapabilities {
  // Legacy boolean flags (always available)
  supportsBatch: boolean;
  supportsTemplates: boolean;
  supportsWebhooks: boolean;
  supportsAttachments: boolean;
  supportsCustomHeaders: boolean;
  supportsDeliveryTracking: boolean;
  maxBatchSize: number;
  maxAttachmentSize: number;

  // Expanded feature map (optional, populated by capability-aware providers)
  features?: Record<string, CapabilityEntry>;
}
```

### 能力输入

表格中的每个条目 `features` 映射描述特定特性是如何被支持的 :

```typescript
type CapabilitySource = 'provider' | 'platform' | 'enhanced' | 'unsupported';

interface CapabilityEntry {
  source: CapabilitySource;      // How the feature is implemented
  description: string;           // Human-readable description
  limitations?: string;          // Known limitations (e.g., "72hr max scheduling window")
  degradation?: {                // Present when platform polyfill has a degradation strategy
    strategy: string;
    description: string;
    docUrl: string;
  } | null;
  overridable: boolean;          // Whether the entry can be overridden at runtime
}
```

### 提供能力摘要

| 提供者 | 批次 | 模板 | 网络呼号 | 附录 | 自定义信头 | 交货跟踪 |
| --- | --- | --- | --- | --- | --- | --- |
| 发送Grid | 有(个性化) | 是(动态模板) | 是 (Event Webhook) (英语) | 对 | 对 | 对 |
| 邮件枪 | 是(接收变量) | 是(存储模板) | 对 | 对 | 对 | 对 |
| 邮戳 | 是(批发API) | 是(服务器侧) | 对 | 对 | 对 | 对 |
| 用户 | 是 (发送Blk电子邮件) | 是(电子邮件模板) | 是(通过SNS) | 是( raw 电子邮件) | 对 | 是(通过SNS) |
| SMTP 软件 | 顺序\* | 没有服务器侧 | 没有 | 是(微小中型企业) | 对 | 没有 |

\*SMTP批发由平台相继处理,而不是由供应商自行处理.

### 宣布自定义提供者的能力

执行自定义提供者时,通过返回适当的值来声明能力 `getCapabilities()`数字 :

```typescript
import { EmailProvider, EmailProviderCapabilities, CapabilityEntry } from '@bernierllc/email-sender';

class CustomProvider extends EmailProvider {
  getCapabilities(): EmailProviderCapabilities {
    return {
      supportsBatch: true,
      supportsTemplates: false,
      supportsWebhooks: true,
      supportsAttachments: true,
      supportsCustomHeaders: true,
      supportsDeliveryTracking: true,
      maxBatchSize: 500,
      maxAttachmentSize: 10 * 1024 * 1024, // 10 MB

      // Optional: declare fine-grained features for capability-aware routing
      features: {
        sendEmail: {
          source: 'provider',
          description: 'Send email via custom API',
          degradation: null,
          overridable: false,
        },
        batchSend: {
          source: 'provider',
          description: 'Batch send via custom API bulk endpoint',
          degradation: null,
          overridable: true,
        },
        scheduledSend: {
          source: 'unsupported',
          description: 'Custom provider does not support scheduled send',
          degradation: null,
          overridable: false,
        },
      },
    };
  }
}
```

当 `features` 地图已存在 `@bernierllc/email-manager` 能力路由器将其用于智能供应商选择. 缺席时,路由器会倒回静态能力矩阵.

### Zod 验证

两者 `CapabilityEntry` 财务报告和审定财务报表 `DegradationInfo` 拥有运行时间验证的 Zod 计划 :

```typescript
import { capabilityEntrySchema, degradationInfoSchema } from '@bernierllc/email-sender';

const result = capabilityEntrySchema.safeParse(entry);
if (!result.success) {
  console.error('Invalid capability entry:', result.error.issues);
}
```

* * *

## 显示电子邮件安全

使用中转安全功能,防止在非生产环境中发送意外邮件.

### 以白名单粘贴( Block 非白名单)

```typescript
import { EmailSender } from '@bernierllc/email-sender';

const emailSender = new EmailSender({
  provider: 'smtp' as const,
  host: 'smtp.example.com',
  port: 587,
  username: 'user',
  password: 'pass',
  fromEmail: 'sender@example.com',
  stagingSafety: {
    enabled: true,
    environment: 'staging',
    whitelist: ['test@example.com', 'admin@example.com', 'qa@example.com'],
    blockNonWhitelisted: true,
    logBlocked: true,
  },
});

// This will send (whitelisted)
await emailSender.sendEmail({
  toEmail: 'test@example.com',
  subject: 'Test Email',
  htmlContent: '<p>This email will be sent</p>',
});

// This will be blocked (not whitelisted)
const result = await emailSender.sendEmail({
  toEmail: 'customer@example.com',
  subject: 'Test Email',
  htmlContent: '<p>This email will be blocked</p>',
});
console.log(result.success); // false
console.log(result.errorMessage); // "Email blocked by safety manager: ..."
```

### 用重写粘接( 重定向到测试电子邮件)

```typescript
const emailSender = new EmailSender({
  provider: 'smtp' as const,
  host: 'smtp.example.com',
  port: 587,
  username: 'user',
  password: 'pass',
  fromEmail: 'sender@example.com',
  stagingSafety: {
    enabled: true,
    environment: 'staging',
    whitelist: ['admin@example.com'], // Admin emails go through normally
    rewriteTo: 'staging-test@example.com', // All other emails redirected here
    blockNonWhitelisted: false,
    logBlocked: true,
  },
});

// This will be sent to staging-test@example.com instead
await emailSender.sendEmail({
  toEmail: 'customer@example.com',
  subject: 'Test Email',
  htmlContent: '<p>This will be sent to staging-test@example.com</p>',
});
```

### 制作(所有电子邮件)

```typescript
const emailSender = new EmailSender({
  provider: 'smtp' as const,
  host: 'smtp.example.com',
  port: 587,
  username: 'user',
  password: 'pass',
  fromEmail: 'sender@example.com',
  stagingSafety: {
    enabled: true,
    environment: 'production',
    whitelist: [], // Not used in production
    blockNonWhitelisted: false,
    logBlocked: false,
  },
});

// All emails are allowed in production
await emailSender.sendEmail({
  toEmail: 'customer@example.com',
  subject: 'Production Email',
  htmlContent: '<p>This email will be sent</p>',
});
```

### 发送前检查收件人安全性

```typescript
const safetyResult = emailSender.checkRecipientSafety('test@example.com');
console.log('Safety check result:', safetyResult);

if (safetyResult && !safetyResult.allowed) {
  console.log('Email would be blocked:', safetyResult.reason);
}
```

### 基于环境的动态配置

```typescript
const environment = process.env.NODE_ENV || 'development';

const emailSender = new EmailSender({
  provider: 'smtp' as const,
  host: 'smtp.example.com',
  port: 587,
  username: 'user',
  password: 'pass',
  fromEmail: 'sender@example.com',
  stagingSafety: {
    enabled: environment !== 'production',
    environment: environment as 'development' | 'staging' | 'production',
    whitelist: environment === 'staging'
      ? ['qa@example.com', 'test@example.com']
      : [],
    rewriteTo: environment === 'development' ? 'dev@example.com' : undefined,
    blockNonWhitelisted: environment === 'staging',
    logBlocked: true,
  },
});

console.log('Current environment:', environment);
console.log('Safety enabled:', emailSender.isSafetyEnabled());
console.log('Safety config:', emailSender.getSafetyConfig());
```

## 实例

### 以附件发送电子邮件

```typescript
import { EmailSender } from '@bernierllc/email-sender';
import fs from 'fs';

const emailSender = new EmailSender(config);

const attachment = {
  filename: 'report.pdf',
  content: fs.readFileSync('report.pdf').toString('base64'),
  contentType: 'application/pdf',
  disposition: 'attachment' as const,
};

const result = await emailSender.sendEmail({
  toEmail: 'recipient@example.com',
  subject: 'Monthly Report',
  htmlContent: '<h1>Monthly Report</h1><p>Please find the attached report.</p>',
  attachments: [attachment],
});
```

### 用自定义信头发送电子邮件

```typescript
const result = await emailSender.sendEmail({
  toEmail: 'recipient@example.com',
  subject: 'Priority Message',
  htmlContent: '<h1>Important Update</h1>',
  headers: {
    'X-Priority': '1',
    'X-Custom-Header': 'custom-value',
  },
});
```

### 带有不同内容的批次电子邮件

```typescript
const emails = [
  {
    toEmail: 'user1@example.com',
    toName: 'User One',
    subject: 'Personalized Email 1',
    htmlContent: '<h1>Hello User One!</h1>',
  },
  {
    toEmail: 'user2@example.com',
    toName: 'User Two',
    subject: 'Personalized Email 2',
    htmlContent: '<h1>Hello User Two!</h1>',
  },
];

const results = await emailSender.sendBatch(emails);
```

### 处理错误

```typescript
try {
  const result = await emailSender.sendEmail(email);
  
  if (result.success) {
    console.log('Email sent successfully');
  } else {
    console.error('Email failed:', result.errorMessage);
    
    // Check if it's a validation error
    const validation = emailSender.validateEmailMessage(email);
    if (!validation.isValid) {
      console.error('Validation errors:', validation.errors);
    }
  }
} catch (error) {
  console.error('Unexpected error:', error);
}
```

## 提供者支助

### 目前得到支持

-   **SMTP 软件**: 用节点符完全支持
-   **发送Grid**: 完全支持 SendGrid API
-   **警报器**: 用 AWS SDK 提供完全支持( 需要) `aws-sdk` 依赖同伴)
-   **邮件枪**: 完全支持 Mailgun API
-   **邮戳**: 完全支持 Postmark API

### 添加新供应商

要添加一个新的提供者,请扩展 `EmailProvider` 基准类 :

```typescript
import { EmailProvider, EmailMessage, SendResult } from '@bernierllc/email-sender';

export class CustomProvider extends EmailProvider {
  async sendEmail(email: EmailMessage): Promise<SendResult> {
    // Implement your provider logic here
  }
  
  async sendBatch(emails: EmailMessage[]): Promise<SendResult[]> {
    // Implement batch sending logic
  }
  
  async getDeliveryStatus(messageId: string): Promise<DeliveryStatus | null> {
    // Implement delivery status checking
  }
  
  async processWebhook(payload: any, signature: string): Promise<WebhookEvent[]> {
    // Implement webhook processing
  }
}
```

## 测试

运行测试套件 :

```bash
npm test
```

进行覆盖测试 :

```bash
npm run test:coverage
```

## 捐款

1.  叉子存储器
2.  创建特性分支
3.  做你的改变
4.  添加新功能测试
5.  确保所有测试通过
6.  提交拉动请求

## 一体化状况

-   **伐木机集成**:不适用 - Email-sender是一个低等的用途,不需要@bernierllc/logger集成. 消费者申请应视需要处理伐木问题.
-   **多克套装**: 准备 - 完整的类型Doc/JSDoc文档。 基于 Markdown 的 README 有广泛的示例 .
-   **NeverHub 整合**:不适用 -- -- 电子邮件发送器是一个无国籍的功能,侧重于电子邮件发送。 @bernierllc/ 绝不需要适应器.

### 重大退化

这个软件包的设计是为了在配置的电子邮件提供者之外,在没有外部依赖的情况下独立工作. 所有功能都是自成一体的,有明显的错误处理和验证.

## 许可证

ISC 许可证 - 详情见LICENSE文件.

## 支助

请在GitHub上打开一个问题或联系Bernier LLC.

### 信息分析参数

SendGrid 通过现有的跟踪对象支持清晰的每个消息的 UTM 值 :

```ts
tracking: {
  utm: true,
  utmParameters: {
    source: 'newsletter', medium: 'email', campaign: 'launch',
    term: '', content: 'hero',
  },
}
```

参数仅以 `utm: true`。 。 。 . `utm: false` 只发送 `ganalytics.enable: false`; 省略 `utm` 保留账户行为。 Oinducted/null 参数字段将账户值留在控制中;空字符串是准确传输的. 除字符串/ null 抛出之外启用的参数值 `EmailValidationError` 在HTTP之前。 库不发明提供者长度限制. 提供商: `utmTracking` 能力是不支持的,忽略这些参数.

点击和开放跟踪仍然可独立配置。 有效载荷合同并不保证某一提供商对空值或有点击跟踪功能的分析进行送出-链接处理;在作为应用行为提供这些组合之前,对照用于交付的账户对这些组合进行验证.

## 常见问题

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

有提供者- 不可知界面和 SendGrid 高级功能的电子邮件发送\( 模板、 经核实的发送者、 速率限制\)

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

在项目目录运行 npm install @bernierllc/email-sender，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：aws-sdk（^2\.1000\.0）、nodemailer（^6\.9\.0）、@sendgrid/mail（^8\.1\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

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

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

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

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

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

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

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

@bernierllc/email-sender 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

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

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

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

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

