tempmail-sdk 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +162 -72
  2. package/demo/poll-emails.ts +25 -40
  3. package/dist/index.d.ts +96 -2
  4. package/dist/index.js +186 -21
  5. package/dist/logger.d.ts +73 -0
  6. package/dist/logger.js +100 -0
  7. package/dist/normalize.d.ts +12 -0
  8. package/dist/normalize.js +132 -0
  9. package/dist/providers/awamail.d.ts +15 -0
  10. package/dist/providers/awamail.js +91 -0
  11. package/dist/providers/chatgpt-org-uk.js +4 -2
  12. package/dist/providers/dropmail.d.ts +13 -0
  13. package/dist/providers/dropmail.js +86 -0
  14. package/dist/providers/linshi-email.js +4 -2
  15. package/dist/providers/mail-tm.d.ts +11 -0
  16. package/dist/providers/mail-tm.js +172 -0
  17. package/dist/providers/temp-mail-io.d.ts +13 -0
  18. package/dist/providers/temp-mail-io.js +99 -0
  19. package/dist/providers/tempmail-la.d.ts +15 -0
  20. package/dist/providers/tempmail-la.js +89 -0
  21. package/dist/providers/tempmail-lol.d.ts +1 -1
  22. package/dist/providers/tempmail-lol.js +5 -3
  23. package/dist/providers/tempmail.js +4 -2
  24. package/dist/retry.d.ts +38 -0
  25. package/dist/retry.js +121 -0
  26. package/dist/types.d.ts +118 -28
  27. package/dist/types.js +1 -1
  28. package/package.json +1 -1
  29. package/src/index.ts +182 -25
  30. package/src/logger.ts +106 -0
  31. package/src/normalize.ts +125 -0
  32. package/src/providers/awamail.ts +101 -0
  33. package/src/providers/chatgpt-org-uk.ts +3 -1
  34. package/src/providers/dropmail.ts +98 -0
  35. package/src/providers/linshi-email.ts +3 -1
  36. package/src/providers/mail-tm.ts +193 -0
  37. package/src/providers/temp-mail-io.ts +108 -0
  38. package/src/providers/tempmail-la.ts +99 -0
  39. package/src/providers/tempmail-lol.ts +4 -2
  40. package/src/providers/tempmail.ts +3 -1
  41. package/src/retry.ts +146 -0
  42. package/src/types.ts +120 -28
  43. package/test/example.ts +16 -1
@@ -0,0 +1,108 @@
1
+ import { EmailInfo, Email, Channel } from '../types';
2
+ import { normalizeEmail } from '../normalize';
3
+
4
+ const CHANNEL: Channel = 'temp-mail-io';
5
+ const BASE_URL = 'https://api.internal.temp-mail.io/api/v3';
6
+ const PAGE_URL = 'https://temp-mail.io/en';
7
+
8
+ /**
9
+ * 缓存从页面动态获取的 mobileTestingHeader 值(用于 X-CORS-Header)
10
+ */
11
+ let cachedCorsHeader: string | null = null;
12
+
13
+ /**
14
+ * 从 temp-mail.io 页面的 __NUXT__ 运行时配置中提取 mobileTestingHeader
15
+ * 该值用于 API 请求的 X-CORS-Header 头,缺少此头会导致 400 错误
16
+ */
17
+ async function fetchCorsHeader(): Promise<string> {
18
+ if (cachedCorsHeader) return cachedCorsHeader;
19
+
20
+ try {
21
+ const response = await fetch(PAGE_URL, {
22
+ headers: {
23
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36',
24
+ },
25
+ });
26
+ const html = await response.text();
27
+ const match = html.match(/mobileTestingHeader\s*:\s*"([^"]+)"/);
28
+ if (match) {
29
+ cachedCorsHeader = match[1];
30
+ return cachedCorsHeader;
31
+ }
32
+ } catch {
33
+ /* 提取失败时使用默认值 */
34
+ }
35
+
36
+ cachedCorsHeader = '1';
37
+ return cachedCorsHeader;
38
+ }
39
+
40
+ /**
41
+ * 构建 API 请求头
42
+ * 关键头: Content-Type, Application-Name, Application-Version, X-CORS-Header
43
+ */
44
+ async function getApiHeaders(): Promise<Record<string, string>> {
45
+ const corsHeader = await fetchCorsHeader();
46
+ return {
47
+ 'Content-Type': 'application/json',
48
+ 'Application-Name': 'web',
49
+ 'Application-Version': '4.0.0',
50
+ 'X-CORS-Header': corsHeader,
51
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0',
52
+ 'origin': 'https://temp-mail.io',
53
+ 'referer': 'https://temp-mail.io/',
54
+ };
55
+ }
56
+
57
+ /**
58
+ * 创建临时邮箱
59
+ * API: POST /api/v3/email/new
60
+ * 返回: { email, token }
61
+ */
62
+ export async function generateEmail(): Promise<EmailInfo> {
63
+ const headers = await getApiHeaders();
64
+ const response = await fetch(`${BASE_URL}/email/new`, {
65
+ method: 'POST',
66
+ headers,
67
+ body: JSON.stringify({ min_name_length: 10, max_name_length: 10 }),
68
+ });
69
+
70
+ if (!response.ok) {
71
+ throw new Error(`Failed to generate email: ${response.status}`);
72
+ }
73
+
74
+ const data = await response.json();
75
+
76
+ if (!data.email || !data.token) {
77
+ throw new Error('Failed to generate email');
78
+ }
79
+
80
+ return {
81
+ channel: CHANNEL,
82
+ email: data.email,
83
+ token: data.token,
84
+ };
85
+ }
86
+
87
+ /**
88
+ * 获取邮件列表
89
+ * API: GET /api/v3/email/{email}/messages
90
+ * 返回: [ { id, from, to, cc, subject, body_text, body_html, created_at, attachments } ]
91
+ */
92
+ export async function getEmails(email: string): Promise<Email[]> {
93
+ const headers = await getApiHeaders();
94
+ const response = await fetch(`${BASE_URL}/email/${email}/messages`, {
95
+ method: 'GET',
96
+ headers,
97
+ });
98
+
99
+ if (!response.ok) {
100
+ throw new Error(`Failed to get emails: ${response.status}`);
101
+ }
102
+
103
+ const data = await response.json();
104
+
105
+ // API 直接返回邮件数组
106
+ const rawEmails = Array.isArray(data) ? data : [];
107
+ return rawEmails.map((raw: any) => normalizeEmail(raw, email));
108
+ }
@@ -0,0 +1,99 @@
1
+ import { EmailInfo, Email, Channel } from '../types';
2
+ import { normalizeEmail } from '../normalize';
3
+
4
+ const CHANNEL: Channel = 'tempmail-la';
5
+ const BASE_URL = 'https://tempmail.la/api';
6
+
7
+ const DEFAULT_HEADERS: Record<string, string> = {
8
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0',
9
+ 'Accept': 'application/json, text/plain, */*',
10
+ 'Content-Type': 'application/json',
11
+ 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
12
+ 'cache-control': 'no-cache',
13
+ 'dnt': '1',
14
+ 'locale': 'zh-CN',
15
+ 'origin': 'https://tempmail.la',
16
+ 'platform': 'PC',
17
+ 'pragma': 'no-cache',
18
+ 'product': 'TEMP_MAIL',
19
+ 'referer': 'https://tempmail.la/zh-CN/tempmail',
20
+ 'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Microsoft Edge";v="144"',
21
+ 'sec-ch-ua-mobile': '?0',
22
+ 'sec-ch-ua-platform': '"Windows"',
23
+ 'sec-fetch-dest': 'empty',
24
+ 'sec-fetch-mode': 'cors',
25
+ 'sec-fetch-site': 'same-origin',
26
+ };
27
+
28
+ /**
29
+ * 创建临时邮箱
30
+ * API: POST /api/mail/create
31
+ * 返回: { code: 0, data: { mailId, address, type, startAt, endAt } }
32
+ */
33
+ export async function generateEmail(): Promise<EmailInfo> {
34
+ const response = await fetch(`${BASE_URL}/mail/create`, {
35
+ method: 'POST',
36
+ headers: DEFAULT_HEADERS,
37
+ body: JSON.stringify({ turnstile: '' }),
38
+ });
39
+
40
+ if (!response.ok) {
41
+ throw new Error(`Failed to generate email: ${response.status}`);
42
+ }
43
+
44
+ const data = await response.json();
45
+
46
+ if (data.code !== 0 || !data.data) {
47
+ throw new Error('Failed to generate email');
48
+ }
49
+
50
+ return {
51
+ channel: CHANNEL,
52
+ email: data.data.address,
53
+ expiresAt: data.data.endAt,
54
+ createdAt: data.data.startAt,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * 获取邮件列表
60
+ * API: POST /api/mail/box
61
+ * 请求: { address, cursor }
62
+ * 返回: { code: 0, data: { rows: [...], cursor, hasMore } }
63
+ * 每封邮件: { mailboxId, messageFrom, subject, createdAt, html, attachments, read }
64
+ */
65
+ export async function getEmails(email: string): Promise<Email[]> {
66
+ const allEmails: any[] = [];
67
+ let cursor: string | null = null;
68
+ let hasMore = true;
69
+
70
+ // 支持分页,循环获取所有邮件
71
+ while (hasMore) {
72
+ const response: Response = await fetch(`${BASE_URL}/mail/box`, {
73
+ method: 'POST',
74
+ headers: DEFAULT_HEADERS,
75
+ body: JSON.stringify({ address: email, cursor }),
76
+ });
77
+
78
+ if (!response.ok) {
79
+ throw new Error(`Failed to get emails: ${response.status}`);
80
+ }
81
+
82
+ const data: any = await response.json();
83
+
84
+ if (data.code !== 0 || !data.data) {
85
+ throw new Error('Failed to get emails');
86
+ }
87
+
88
+ const rows = data.data.rows || [];
89
+ allEmails.push(...rows);
90
+
91
+ if (data.data.hasMore && data.data.cursor) {
92
+ cursor = data.data.cursor;
93
+ } else {
94
+ hasMore = false;
95
+ }
96
+ }
97
+
98
+ return allEmails.map((raw: any) => normalizeEmail(raw, email));
99
+ }
@@ -1,4 +1,5 @@
1
1
  import { EmailInfo, Email, Channel } from '../types';
2
+ import { normalizeEmail } from '../normalize';
2
3
 
3
4
  const CHANNEL: Channel = 'tempmail-lol';
4
5
  const BASE_URL = 'https://api.tempmail.lol/v2';
@@ -37,7 +38,7 @@ export async function generateEmail(domain: string | null = null): Promise<Email
37
38
  };
38
39
  }
39
40
 
40
- export async function getEmails(token: string): Promise<Email[]> {
41
+ export async function getEmails(token: string, recipientEmail: string = ''): Promise<Email[]> {
41
42
  const response = await fetch(`${BASE_URL}/inbox?token=${encodeURIComponent(token)}`, {
42
43
  method: 'GET',
43
44
  headers: DEFAULT_HEADERS,
@@ -49,5 +50,6 @@ export async function getEmails(token: string): Promise<Email[]> {
49
50
 
50
51
  const data = await response.json();
51
52
 
52
- return data.emails || [];
53
+ const rawEmails = data.emails || [];
54
+ return rawEmails.map((raw: any) => normalizeEmail(raw, recipientEmail));
53
55
  }
@@ -1,4 +1,5 @@
1
1
  import { EmailInfo, Email, Channel } from '../types';
2
+ import { normalizeEmail } from '../normalize';
2
3
 
3
4
  const CHANNEL: Channel = 'tempmail';
4
5
  const BASE_URL = 'https://api.tempmail.ing/api';
@@ -55,5 +56,6 @@ export async function getEmails(email: string): Promise<Email[]> {
55
56
  throw new Error('Failed to get emails');
56
57
  }
57
58
 
58
- return data.emails || [];
59
+ const rawEmails = data.emails || [];
60
+ return rawEmails.map((raw: any) => normalizeEmail(raw, email));
59
61
  }
package/src/retry.ts ADDED
@@ -0,0 +1,146 @@
1
+ /**
2
+ * 通用重试工具
3
+ * 提供请求重试、超时控制、指数退避等错误恢复机制
4
+ */
5
+
6
+ import { logger } from './logger';
7
+
8
+ /**
9
+ * 重试配置选项
10
+ */
11
+ export interface RetryOptions {
12
+ /** 最大重试次数(不含首次请求),默认 2 */
13
+ maxRetries?: number;
14
+ /** 初始重试延迟(毫秒),默认 1000 */
15
+ initialDelay?: number;
16
+ /** 最大重试延迟(毫秒),默认 5000 */
17
+ maxDelay?: number;
18
+ /** 请求超时时间(毫秒),默认 15000 */
19
+ timeout?: number;
20
+ /** 是否对该错误进行重试的判断函数 */
21
+ shouldRetry?: (error: any) => boolean;
22
+ }
23
+
24
+ const DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {
25
+ maxRetries: 2,
26
+ initialDelay: 1000,
27
+ maxDelay: 5000,
28
+ timeout: 15000,
29
+ shouldRetry: defaultShouldRetry,
30
+ };
31
+
32
+ /**
33
+ * 默认重试判断
34
+ * 网络错误、超时、HTTP 4xx/5xx 错误均可重试
35
+ * 仅参数校验类错误(由 SDK 内部抛出)不重试
36
+ */
37
+ function defaultShouldRetry(error: any): boolean {
38
+ if (!error) return false;
39
+
40
+ const message = String(error.message || error || '').toLowerCase();
41
+
42
+ /* 网络级别错误 → 重试 */
43
+ if (message.includes('fetch failed') ||
44
+ message.includes('network') ||
45
+ message.includes('econnrefused') ||
46
+ message.includes('econnreset') ||
47
+ message.includes('etimedout') ||
48
+ message.includes('timeout') ||
49
+ message.includes('socket hang up') ||
50
+ message.includes('dns') ||
51
+ message.includes('abort')) {
52
+ return true;
53
+ }
54
+
55
+ /* HTTP 4xx/5xx 错误 → 重试 */
56
+ const statusMatch = message.match(/:\s*(\d{3})/);
57
+ if (statusMatch) {
58
+ const status = parseInt(statusMatch[1], 10);
59
+ return status >= 400;
60
+ }
61
+
62
+ return false;
63
+ }
64
+
65
+ /**
66
+ * 休眠指定毫秒
67
+ */
68
+ function sleep(ms: number): Promise<void> {
69
+ return new Promise(resolve => setTimeout(resolve, ms));
70
+ }
71
+
72
+ /**
73
+ * 带重试的异步操作执行器
74
+ * - 自动重试可恢复的错误(网络错误、超时、5xx)
75
+ * - 指数退避避免过度请求
76
+ * - 不可恢复的错误(4xx 参数错误等)直接抛出不重试
77
+ *
78
+ * @param fn 要执行的异步操作
79
+ * @param options 重试配置
80
+ */
81
+ export async function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> {
82
+ const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };
83
+ let lastError: any;
84
+
85
+ for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
86
+ try {
87
+ const result = await fn();
88
+ if (attempt > 0) {
89
+ logger.info(`第 ${attempt + 1} 次尝试成功`);
90
+ }
91
+ return result;
92
+ } catch (error: any) {
93
+ lastError = error;
94
+ const errorMsg = error.message || String(error);
95
+
96
+ /* 最后一次尝试失败或不可重试的错误 → 直接抛出 */
97
+ if (attempt >= opts.maxRetries || !opts.shouldRetry(error)) {
98
+ if (attempt >= opts.maxRetries && opts.maxRetries > 0) {
99
+ logger.error(`重试 ${opts.maxRetries} 次后仍失败: ${errorMsg}`);
100
+ } else if (!opts.shouldRetry(error)) {
101
+ logger.debug(`不可重试的错误: ${errorMsg}`);
102
+ }
103
+ throw error;
104
+ }
105
+
106
+ /* 指数退避等待 */
107
+ const delay = Math.min(opts.initialDelay * Math.pow(2, attempt), opts.maxDelay);
108
+ logger.warn(`请求失败 (${errorMsg}),${delay}ms 后第 ${attempt + 2} 次重试...`);
109
+ await sleep(delay);
110
+ }
111
+ }
112
+
113
+ throw lastError;
114
+ }
115
+
116
+ /**
117
+ * 带超时控制的 fetch 包装
118
+ * 在原生 fetch 基础上添加超时中断能力
119
+ *
120
+ * @param url 请求 URL
121
+ * @param init fetch 选项
122
+ * @param timeoutMs 超时时间(毫秒)
123
+ */
124
+ export async function fetchWithTimeout(
125
+ url: string,
126
+ init?: RequestInit,
127
+ timeoutMs: number = DEFAULT_RETRY_OPTIONS.timeout,
128
+ ): Promise<Response> {
129
+ const controller = new AbortController();
130
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
131
+
132
+ try {
133
+ const response = await fetch(url, {
134
+ ...init,
135
+ signal: controller.signal,
136
+ });
137
+ return response;
138
+ } catch (error: any) {
139
+ if (error.name === 'AbortError') {
140
+ throw new Error(`Request timeout after ${timeoutMs}ms: ${url}`);
141
+ }
142
+ throw error;
143
+ } finally {
144
+ clearTimeout(timeoutId);
145
+ }
146
+ }
package/src/types.ts CHANGED
@@ -1,58 +1,150 @@
1
- export type Channel = 'tempmail' | 'linshi-email' | 'tempmail-lol' | 'chatgpt-org-uk';
1
+ /**
2
+ * 支持的临时邮箱渠道标识
3
+ * 每个渠道对应一个第三方临时邮箱服务商
4
+ */
5
+ export type Channel = 'tempmail' | 'linshi-email' | 'tempmail-lol' | 'chatgpt-org-uk' | 'tempmail-la' | 'temp-mail-io' | 'awamail' | 'mail-tm' | 'dropmail';
2
6
 
7
+ /**
8
+ * 创建临时邮箱后返回的邮箱信息
9
+ * 包含邮箱地址、认证令牌和生命周期信息
10
+ */
3
11
  export interface EmailInfo {
12
+ /** 创建该邮箱所使用的渠道 */
4
13
  channel: Channel;
14
+ /** 临时邮箱地址 */
5
15
  email: string;
16
+ /** 认证令牌,部分渠道在获取邮件时需要此令牌 */
6
17
  token?: string;
18
+ /** 邮箱过期时间(ISO 8601 字符串或 Unix 时间戳) */
7
19
  expiresAt?: string | number;
20
+ /** 邮箱创建时间(ISO 8601 字符串) */
8
21
  createdAt?: string;
9
22
  }
10
23
 
24
+ /**
25
+ * 标准化邮件附件
26
+ * 不同渠道的附件字段名不同,SDK 统一归一化为此结构
27
+ */
28
+ export interface EmailAttachment {
29
+ /** 附件文件名 */
30
+ filename: string;
31
+ /** 附件大小(字节) */
32
+ size?: number;
33
+ /** MIME 类型,如 application/pdf */
34
+ contentType?: string;
35
+ /** 附件下载地址 */
36
+ url?: string;
37
+ }
38
+
39
+ /**
40
+ * 标准化邮件格式 - 所有提供商返回统一结构
41
+ */
11
42
  export interface Email {
12
- id?: string | number;
13
- eid?: string;
14
- _id?: string;
15
- from?: string;
16
- from_address?: string;
17
- from_name?: string;
18
- address_from?: string;
19
- name_from?: string;
20
- to?: string;
21
- name_to?: string;
22
- email_address?: string;
23
- subject?: string;
24
- e_subject?: string;
25
- body?: string;
26
- text?: string;
27
- content?: string;
28
- html?: string;
29
- html_content?: string;
30
- date?: string | number;
31
- e_date?: number;
32
- timestamp?: number;
33
- received_at?: string;
34
- created_at?: string;
35
- createdAt?: string;
36
- is_read?: number;
37
- has_html?: boolean;
38
- [key: string]: any;
43
+ /** 邮件唯一标识 */
44
+ id: string;
45
+ /** 发件人邮箱地址 */
46
+ from: string;
47
+ /** 收件人邮箱地址 */
48
+ to: string;
49
+ /** 邮件主题 */
50
+ subject: string;
51
+ /** 纯文本内容 */
52
+ text: string;
53
+ /** HTML 内容 */
54
+ html: string;
55
+ /** ISO 8601 格式的日期字符串 */
56
+ date: string;
57
+ /** 是否已读 */
58
+ isRead: boolean;
59
+ /** 附件列表 */
60
+ attachments: EmailAttachment[];
39
61
  }
40
62
 
63
+ /**
64
+ * 获取邮件列表的返回结果
65
+ * success 为 false 时表示请求失败(重试耗尽),emails 为空数组
66
+ */
41
67
  export interface GetEmailsResult {
68
+ /** 所使用的渠道 */
42
69
  channel: Channel;
70
+ /** 查询的邮箱地址 */
43
71
  email: string;
72
+ /** 邮件列表,失败时为空数组 */
44
73
  emails: Email[];
74
+ /** 请求是否成功,false 表示重试耗尽后仍失败 */
45
75
  success: boolean;
46
76
  }
47
77
 
78
+ /**
79
+ * 重试配置
80
+ * SDK 内部对网络错误、超时、5xx 服务端错误自动重试
81
+ * 4xx 客户端错误(如参数错误)不会重试
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * // 自定义重试策略:最多重试 3 次,首次延迟 2 秒
86
+ * const email = await generateEmail({
87
+ * channel: 'mail-tm',
88
+ * retry: { maxRetries: 3, initialDelay: 2000 },
89
+ * });
90
+ * ```
91
+ */
92
+ export interface RetryConfig {
93
+ /** 最大重试次数(不含首次请求),默认 2 */
94
+ maxRetries?: number;
95
+ /** 初始重试延迟(毫秒),采用指数退避策略,默认 1000 */
96
+ initialDelay?: number;
97
+ /** 最大重试延迟上限(毫秒),默认 5000 */
98
+ maxDelay?: number;
99
+ /** 单次请求超时时间(毫秒),默认 15000 */
100
+ timeout?: number;
101
+ }
102
+
103
+ /**
104
+ * 创建临时邮箱的选项
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * // 使用指定渠道创建邮箱
109
+ * const email = await generateEmail({ channel: 'mail-tm' });
110
+ *
111
+ * // 随机选择渠道
112
+ * const email = await generateEmail();
113
+ * ```
114
+ */
48
115
  export interface GenerateEmailOptions {
116
+ /** 指定渠道,不传则随机选择 */
49
117
  channel?: Channel;
118
+ /** 邮箱有效时长 */
50
119
  duration?: number;
120
+ /** 指定邮箱域名 */
51
121
  domain?: string | null;
122
+ /** 重试配置,不传则使用默认值(最多重试 2 次) */
123
+ retry?: RetryConfig;
52
124
  }
53
125
 
126
+ /**
127
+ * 获取邮件列表的选项
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * const result = await getEmails({
132
+ * channel: emailInfo.channel,
133
+ * email: emailInfo.email,
134
+ * token: emailInfo.token,
135
+ * });
136
+ * if (result.success && result.emails.length > 0) {
137
+ * console.log('收到邮件:', result.emails);
138
+ * }
139
+ * ```
140
+ */
54
141
  export interface GetEmailsOptions {
142
+ /** 渠道标识,必填 */
55
143
  channel: Channel;
144
+ /** 邮箱地址,必填 */
56
145
  email: string;
146
+ /** 认证令牌 */
57
147
  token?: string;
148
+ /** 重试配置,不传则使用默认值(最多重试 2 次) */
149
+ retry?: RetryConfig;
58
150
  }
package/test/example.ts CHANGED
@@ -4,7 +4,7 @@ async function testGenerateEmail() {
4
4
  console.log('=== Test Generate Email ===\n');
5
5
 
6
6
  // Test each channel
7
- const channels: Channel[] = ['tempmail', 'linshi-email', 'tempmail-lol', 'chatgpt-org-uk'];
7
+ const channels: Channel[] = ['tempmail', 'linshi-email', 'tempmail-lol', 'chatgpt-org-uk', 'tempmail-la', 'temp-mail-io', 'awamail', 'mail-tm', 'dropmail'];
8
8
 
9
9
  for (const channel of channels) {
10
10
  try {
@@ -14,6 +14,7 @@ async function testGenerateEmail() {
14
14
  console.log(` Email: ${emailInfo.email}`);
15
15
  if (emailInfo.token) console.log(` Token: ${emailInfo.token}`);
16
16
  if (emailInfo.expiresAt) console.log(` Expires: ${emailInfo.expiresAt}`);
17
+ if (emailInfo.createdAt) console.log(` Created: ${emailInfo.createdAt}`);
17
18
  console.log();
18
19
  } catch (error) {
19
20
  console.error(` Error: ${error}`);
@@ -34,6 +35,20 @@ async function testGetEmails() {
34
35
 
35
36
  const result = await client.getEmails();
36
37
  console.log(`Emails count: ${result.emails.length}`);
38
+
39
+ // 展示标准化的邮件格式
40
+ for (const email of result.emails) {
41
+ console.log(` ID: ${email.id}`);
42
+ console.log(` From: ${email.from}`);
43
+ console.log(` To: ${email.to}`);
44
+ console.log(` Subject: ${email.subject}`);
45
+ console.log(` Date: ${email.date}`);
46
+ console.log(` IsRead: ${email.isRead}`);
47
+ console.log(` Text: ${email.text.substring(0, 100)}`);
48
+ console.log(` HTML: ${email.html.substring(0, 100)}`);
49
+ console.log(` Attachments: ${email.attachments.length}`);
50
+ console.log();
51
+ }
37
52
  console.log();
38
53
  } catch (error) {
39
54
  console.error(`Error: ${error}`);