tempmail-sdk 1.1.0 → 1.1.2
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.
- package/README.md +44 -0
- package/bun.lock +60 -0
- package/demo/poll-emails.ts +7 -8
- package/dist/config.d.ts +47 -0
- package/dist/config.js +68 -0
- package/dist/index.d.ts +21 -20
- package/dist/index.js +84 -38
- package/dist/normalize.js +28 -3
- package/dist/providers/awamail.d.ts +2 -2
- package/dist/providers/awamail.js +1 -1
- package/dist/providers/chatgpt-org-uk.d.ts +2 -2
- package/dist/providers/chatgpt-org-uk.js +1 -1
- package/dist/providers/dropmail.d.ts +2 -2
- package/dist/providers/dropmail.js +1 -1
- package/dist/providers/guerrillamail.d.ts +2 -2
- package/dist/providers/guerrillamail.js +1 -1
- package/dist/providers/linshi-email.d.ts +2 -2
- package/dist/providers/linshi-email.js +1 -1
- package/dist/providers/mail-tm.d.ts +2 -2
- package/dist/providers/mail-tm.js +1 -1
- package/dist/providers/maildrop.d.ts +2 -2
- package/dist/providers/maildrop.js +1 -1
- package/dist/providers/temp-mail-io.d.ts +2 -2
- package/dist/providers/temp-mail-io.js +1 -1
- package/dist/providers/tempmail-la.d.ts +2 -2
- package/dist/providers/tempmail-la.js +1 -1
- package/dist/providers/tempmail-lol.d.ts +2 -2
- package/dist/providers/tempmail-lol.js +1 -1
- package/dist/providers/tempmail.d.ts +2 -2
- package/dist/providers/tempmail.js +25 -2
- package/dist/retry.js +14 -5
- package/dist/types.d.ts +13 -14
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/src/config.ts +82 -0
- package/src/index.ts +87 -40
- package/src/normalize.ts +30 -2
- package/src/providers/awamail.ts +2 -2
- package/src/providers/chatgpt-org-uk.ts +2 -2
- package/src/providers/dropmail.ts +2 -2
- package/src/providers/guerrillamail.ts +2 -2
- package/src/providers/linshi-email.ts +2 -2
- package/src/providers/mail-tm.ts +2 -2
- package/src/providers/maildrop.ts +2 -2
- package/src/providers/temp-mail-io.ts +2 -2
- package/src/providers/tempmail-la.ts +2 -2
- package/src/providers/tempmail-lol.ts +2 -2
- package/src/providers/tempmail.ts +27 -3
- package/src/retry.ts +15 -4
- package/src/types.ts +14 -14
package/dist/types.d.ts
CHANGED
|
@@ -5,20 +5,27 @@
|
|
|
5
5
|
export type Channel = 'tempmail' | 'linshi-email' | 'tempmail-lol' | 'chatgpt-org-uk' | 'tempmail-la' | 'temp-mail-io' | 'awamail' | 'mail-tm' | 'dropmail' | 'guerrillamail' | 'maildrop';
|
|
6
6
|
/**
|
|
7
7
|
* 创建临时邮箱后返回的邮箱信息
|
|
8
|
-
*
|
|
8
|
+
* Token 等认证信息由 SDK 内部维护,不对外暴露
|
|
9
9
|
*/
|
|
10
10
|
export interface EmailInfo {
|
|
11
11
|
/** 创建该邮箱所使用的渠道 */
|
|
12
12
|
channel: Channel;
|
|
13
13
|
/** 临时邮箱地址 */
|
|
14
14
|
email: string;
|
|
15
|
-
/** 认证令牌,部分渠道在获取邮件时需要此令牌 */
|
|
16
|
-
token?: string;
|
|
17
15
|
/** 邮箱过期时间(ISO 8601 字符串或 Unix 时间戳) */
|
|
18
16
|
expiresAt?: string | number;
|
|
19
17
|
/** 邮箱创建时间(ISO 8601 字符串) */
|
|
20
18
|
createdAt?: string;
|
|
21
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* SDK 内部使用的邮箱信息,包含 token 等认证数据
|
|
22
|
+
* 不对外导出,用户无法访问
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export interface InternalEmailInfo extends EmailInfo {
|
|
26
|
+
/** 认证令牌,由 SDK 内部维护 */
|
|
27
|
+
token?: string;
|
|
28
|
+
}
|
|
22
29
|
/**
|
|
23
30
|
* 标准化邮件附件
|
|
24
31
|
* 不同渠道的附件字段名不同,SDK 统一归一化为此结构
|
|
@@ -118,26 +125,18 @@ export interface GenerateEmailOptions {
|
|
|
118
125
|
}
|
|
119
126
|
/**
|
|
120
127
|
* 获取邮件列表的选项
|
|
128
|
+
* Channel/Email/Token 等由 SDK 从 EmailInfo 中自动获取,用户无需手动传递
|
|
121
129
|
*
|
|
122
130
|
* @example
|
|
123
131
|
* ```ts
|
|
124
|
-
* const
|
|
125
|
-
*
|
|
126
|
-
* email: emailInfo.email,
|
|
127
|
-
* token: emailInfo.token,
|
|
128
|
-
* });
|
|
132
|
+
* const info = await generateEmail({ channel: 'mail-tm' });
|
|
133
|
+
* const result = await getEmails(info);
|
|
129
134
|
* if (result.success && result.emails.length > 0) {
|
|
130
135
|
* console.log('收到邮件:', result.emails);
|
|
131
136
|
* }
|
|
132
137
|
* ```
|
|
133
138
|
*/
|
|
134
139
|
export interface GetEmailsOptions {
|
|
135
|
-
/** 渠道标识,必填 */
|
|
136
|
-
channel: Channel;
|
|
137
|
-
/** 邮箱地址,必填 */
|
|
138
|
-
email: string;
|
|
139
|
-
/** 认证令牌 */
|
|
140
|
-
token?: string;
|
|
141
140
|
/** 重试配置,不传则使用默认值(最多重试 2 次) */
|
|
142
141
|
retry?: RetryConfig;
|
|
143
142
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog5pSv5oyB55qE5Li05pe26YKu566x5rig6YGT5qCH6K+GXG4gKiDmr4/kuKrmuKDpgZPlr7nlupTkuIDkuKrnrKzkuInmlrnkuLTml7bpgq7nrrHmnI3liqHllYZcbiAqL1xuZXhwb3J0IHR5cGUgQ2hhbm5lbCA9ICd0ZW1wbWFpbCcgfCAnbGluc2hpLWVtYWlsJyB8ICd0ZW1wbWFpbC1sb2wnIHwgJ2NoYXRncHQtb3JnLXVrJyB8ICd0ZW1wbWFpbC1sYScgfCAndGVtcC1tYWlsLWlvJyB8ICdhd2FtYWlsJyB8ICdtYWlsLXRtJyB8ICdkcm9wbWFpbCcgfCAnZ3VlcnJpbGxhbWFpbCcgfCAnbWFpbGRyb3AnO1xuXG4vKipcbiAqIOWIm+W7uuS4tOaXtumCrueuseWQjui/lOWbnueahOmCrueuseS/
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog5pSv5oyB55qE5Li05pe26YKu566x5rig6YGT5qCH6K+GXG4gKiDmr4/kuKrmuKDpgZPlr7nlupTkuIDkuKrnrKzkuInmlrnkuLTml7bpgq7nrrHmnI3liqHllYZcbiAqL1xuZXhwb3J0IHR5cGUgQ2hhbm5lbCA9ICd0ZW1wbWFpbCcgfCAnbGluc2hpLWVtYWlsJyB8ICd0ZW1wbWFpbC1sb2wnIHwgJ2NoYXRncHQtb3JnLXVrJyB8ICd0ZW1wbWFpbC1sYScgfCAndGVtcC1tYWlsLWlvJyB8ICdhd2FtYWlsJyB8ICdtYWlsLXRtJyB8ICdkcm9wbWFpbCcgfCAnZ3VlcnJpbGxhbWFpbCcgfCAnbWFpbGRyb3AnO1xuXG4vKipcbiAqIOWIm+W7uuS4tOaXtumCrueuseWQjui/lOWbnueahOmCrueuseS/oeaBr1xuICogVG9rZW4g562J6K6k6K+B5L+h5oGv55SxIFNESyDlhoXpg6jnu7TmiqTvvIzkuI3lr7nlpJbmmrTpnLJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbWFpbEluZm8ge1xuICAvKiog5Yib5bu66K+l6YKu566x5omA5L2/55So55qE5rig6YGTICovXG4gIGNoYW5uZWw6IENoYW5uZWw7XG4gIC8qKiDkuLTml7bpgq7nrrHlnLDlnYAgKi9cbiAgZW1haWw6IHN0cmluZztcbiAgLyoqIOmCrueusei/h+acn+aXtumXtO+8iElTTyA4NjAxIOWtl+espuS4suaIliBVbml4IOaXtumXtOaIs++8iSAqL1xuICBleHBpcmVzQXQ/OiBzdHJpbmcgfCBudW1iZXI7XG4gIC8qKiDpgq7nrrHliJvlu7rml7bpl7TvvIhJU08gODYwMSDlrZfnrKbkuLLvvIkgKi9cbiAgY3JlYXRlZEF0Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFNESyDlhoXpg6jkvb/nlKjnmoTpgq7nrrHkv6Hmga/vvIzljIXlkKsgdG9rZW4g562J6K6k6K+B5pWw5o2uXG4gKiDkuI3lr7nlpJblr7zlh7rvvIznlKjmiLfml6Dms5Xorr/pl65cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEludGVybmFsRW1haWxJbmZvIGV4dGVuZHMgRW1haWxJbmZvIHtcbiAgLyoqIOiupOivgeS7pOeJjO+8jOeUsSBTREsg5YaF6YOo57u05oqkICovXG4gIHRva2VuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIOagh+WHhuWMlumCruS7tumZhOS7tlxuICog5LiN5ZCM5rig6YGT55qE6ZmE5Lu25a2X5q615ZCN5LiN5ZCM77yMU0RLIOe7n+S4gOW9kuS4gOWMluS4uuatpOe7k+aehFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVtYWlsQXR0YWNobWVudCB7XG4gIC8qKiDpmYTku7bmlofku7blkI0gKi9cbiAgZmlsZW5hbWU6IHN0cmluZztcbiAgLyoqIOmZhOS7tuWkp+Wwj++8iOWtl+iKgu+8iSAqL1xuICBzaXplPzogbnVtYmVyO1xuICAvKiogTUlNRSDnsbvlnovvvIzlpoIgYXBwbGljYXRpb24vcGRmICovXG4gIGNvbnRlbnRUeXBlPzogc3RyaW5nO1xuICAvKiog6ZmE5Lu25LiL6L295Zyw5Z2AICovXG4gIHVybD86IHN0cmluZztcbn1cblxuLyoqXG4gKiDmoIflh4bljJbpgq7ku7bmoLzlvI8gLSDmiYDmnInmj5DkvpvllYbov5Tlm57nu5/kuIDnu5PmnoRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbWFpbCB7XG4gIC8qKiDpgq7ku7bllK/kuIDmoIfor4YgKi9cbiAgaWQ6IHN0cmluZztcbiAgLyoqIOWPkeS7tuS6uumCrueuseWcsOWdgCAqL1xuICBmcm9tOiBzdHJpbmc7XG4gIC8qKiDmlLbku7bkurrpgq7nrrHlnLDlnYAgKi9cbiAgdG86IHN0cmluZztcbiAgLyoqIOmCruS7tuS4u+mimCAqL1xuICBzdWJqZWN0OiBzdHJpbmc7XG4gIC8qKiDnuq/mlofmnKzlhoXlrrkgKi9cbiAgdGV4dDogc3RyaW5nO1xuICAvKiogSFRNTCDlhoXlrrkgKi9cbiAgaHRtbDogc3RyaW5nO1xuICAvKiogSVNPIDg2MDEg5qC85byP55qE5pel5pyf5a2X56ym5LiyICovXG4gIGRhdGU6IHN0cmluZztcbiAgLyoqIOaYr+WQpuW3suivuyAqL1xuICBpc1JlYWQ6IGJvb2xlYW47XG4gIC8qKiDpmYTku7bliJfooaggKi9cbiAgYXR0YWNobWVudHM6IEVtYWlsQXR0YWNobWVudFtdO1xufVxuXG4vKipcbiAqIOiOt+WPlumCruS7tuWIl+ihqOeahOi/lOWbnue7k+aenFxuICogc3VjY2VzcyDkuLogZmFsc2Ug5pe26KGo56S66K+35rGC5aSx6LSl77yI6YeN6K+V6ICX5bC977yJ77yMZW1haWxzIOS4uuepuuaVsOe7hFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdldEVtYWlsc1Jlc3VsdCB7XG4gIC8qKiDmiYDkvb/nlKjnmoTmuKDpgZMgKi9cbiAgY2hhbm5lbDogQ2hhbm5lbDtcbiAgLyoqIOafpeivoueahOmCrueuseWcsOWdgCAqL1xuICBlbWFpbDogc3RyaW5nO1xuICAvKiog6YKu5Lu25YiX6KGo77yM5aSx6LSl5pe25Li656m65pWw57uEICovXG4gIGVtYWlsczogRW1haWxbXTtcbiAgLyoqIOivt+axguaYr+WQpuaIkOWKn++8jGZhbHNlIOihqOekuumHjeivleiAl+WwveWQjuS7jeWksei0pSAqL1xuICBzdWNjZXNzOiBib29sZWFuO1xufVxuXG4vKipcbiAqIOmHjeivlemFjee9rlxuICogU0RLIOWGhemDqOWvuee9kee7nOmUmeivr+OAgei2heaXtuOAgTV4eCDmnI3liqHnq6/plJnor6/oh6rliqjph43or5VcbiAqIDR4eCDlrqLmiLfnq6/plJnor6/vvIjlpoLlj4LmlbDplJnor6/vvInkuI3kvJrph43or5VcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIC8vIOiHquWumuS5iemHjeivleetlueVpe+8muacgOWkmumHjeivlSAzIOasoe+8jOmmluasoeW7tui/nyAyIOenklxuICogY29uc3QgZW1haWwgPSBhd2FpdCBnZW5lcmF0ZUVtYWlsKHtcbiAqICAgY2hhbm5lbDogJ21haWwtdG0nLFxuICogICByZXRyeTogeyBtYXhSZXRyaWVzOiAzLCBpbml0aWFsRGVsYXk6IDIwMDAgfSxcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmV0cnlDb25maWcge1xuICAvKiog5pyA5aSn6YeN6K+V5qyh5pWw77yI5LiN5ZCr6aaW5qyh6K+35rGC77yJ77yM6buY6K6kIDIgKi9cbiAgbWF4UmV0cmllcz86IG51bWJlcjtcbiAgLyoqIOWIneWni+mHjeivleW7tui/n++8iOavq+enku+8ie+8jOmHh+eUqOaMh+aVsOmAgOmBv+etlueVpe+8jOm7mOiupCAxMDAwICovXG4gIGluaXRpYWxEZWxheT86IG51bWJlcjtcbiAgLyoqIOacgOWkp+mHjeivleW7tui/n+S4iumZkO+8iOavq+enku+8ie+8jOm7mOiupCA1MDAwICovXG4gIG1heERlbGF5PzogbnVtYmVyO1xuICAvKiog5Y2V5qyh6K+35rGC6LaF5pe25pe26Ze077yI5q+r56eS77yJ77yM6buY6K6kIDE1MDAwICovXG4gIHRpbWVvdXQ/OiBudW1iZXI7XG59XG5cbi8qKlxuICog5Yib5bu65Li05pe26YKu566x55qE6YCJ6aG5XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiAvLyDkvb/nlKjmjIflrprmuKDpgZPliJvlu7rpgq7nrrFcbiAqIGNvbnN0IGVtYWlsID0gYXdhaXQgZ2VuZXJhdGVFbWFpbCh7IGNoYW5uZWw6ICdtYWlsLXRtJyB9KTtcbiAqXG4gKiAvLyDpmo/mnLrpgInmi6nmuKDpgZNcbiAqIGNvbnN0IGVtYWlsID0gYXdhaXQgZ2VuZXJhdGVFbWFpbCgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuZXJhdGVFbWFpbE9wdGlvbnMge1xuICAvKiog5oyH5a6a5rig6YGT77yM5LiN5Lyg5YiZ6ZqP5py66YCJ5oupICovXG4gIGNoYW5uZWw/OiBDaGFubmVsO1xuICAvKiog6YKu566x5pyJ5pWI5pe26ZW/ICovXG4gIGR1cmF0aW9uPzogbnVtYmVyO1xuICAvKiog5oyH5a6a6YKu566x5Z+f5ZCNICovXG4gIGRvbWFpbj86IHN0cmluZyB8IG51bGw7XG4gIC8qKiDph43or5XphY3nva7vvIzkuI3kvKDliJnkvb/nlKjpu5jorqTlgLzvvIjmnIDlpJrph43or5UgMiDmrKHvvIkgKi9cbiAgcmV0cnk/OiBSZXRyeUNvbmZpZztcbn1cblxuLyoqXG4gKiDojrflj5bpgq7ku7bliJfooajnmoTpgInpoblcbiAqIENoYW5uZWwvRW1haWwvVG9rZW4g562J55SxIFNESyDku44gRW1haWxJbmZvIOS4reiHquWKqOiOt+WPlu+8jOeUqOaIt+aXoOmcgOaJi+WKqOS8oOmAklxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogY29uc3QgaW5mbyA9IGF3YWl0IGdlbmVyYXRlRW1haWwoeyBjaGFubmVsOiAnbWFpbC10bScgfSk7XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRFbWFpbHMoaW5mbyk7XG4gKiBpZiAocmVzdWx0LnN1Y2Nlc3MgJiYgcmVzdWx0LmVtYWlscy5sZW5ndGggPiAwKSB7XG4gKiAgIGNvbnNvbGUubG9nKCfmlLbliLDpgq7ku7Y6JywgcmVzdWx0LmVtYWlscyk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRFbWFpbHNPcHRpb25zIHtcbiAgLyoqIOmHjeivlemFjee9ru+8jOS4jeS8oOWImeS9v+eUqOm7mOiupOWAvO+8iOacgOWkmumHjeivlSAyIOasoe+8iSAqL1xuICByZXRyeT86IFJldHJ5Q29uZmlnO1xufVxuIl19
|
package/package.json
CHANGED
package/src/config.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK 全局配置
|
|
3
|
+
* 包含代理、超时、SSL 等设置,作用于所有 HTTP 请求
|
|
4
|
+
*
|
|
5
|
+
* 支持环境变量自动读取(优先级低于代码设置):
|
|
6
|
+
* TEMPMAIL_PROXY - 代理 URL
|
|
7
|
+
* TEMPMAIL_TIMEOUT - 超时毫秒数
|
|
8
|
+
* TEMPMAIL_INSECURE - 设为 "1" 或 "true" 跳过 SSL 验证
|
|
9
|
+
*
|
|
10
|
+
* Node.js 环境下设置 insecure 会自动设置 NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* SDK 全局配置接口
|
|
15
|
+
*/
|
|
16
|
+
export interface SDKConfig {
|
|
17
|
+
/** 代理 URL,支持 http/https/socks5,如 "http://127.0.0.1:7890" */
|
|
18
|
+
proxy?: string;
|
|
19
|
+
/** 全局默认超时(毫秒),默认 15000 */
|
|
20
|
+
timeout?: number;
|
|
21
|
+
/** 跳过 SSL 证书验证(调试用) */
|
|
22
|
+
insecure?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 自定义 fetch 函数,用于完全控制 HTTP 请求行为
|
|
25
|
+
* 当设置了 proxy 但环境不支持 undici 时,可通过此选项传入支持代理的 fetch 实现
|
|
26
|
+
*/
|
|
27
|
+
customFetch?: typeof fetch;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** 从环境变量读取默认配置 */
|
|
31
|
+
function loadEnvConfig(): SDKConfig {
|
|
32
|
+
const config: SDKConfig = {};
|
|
33
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
34
|
+
if (process.env.TEMPMAIL_PROXY) {
|
|
35
|
+
config.proxy = process.env.TEMPMAIL_PROXY;
|
|
36
|
+
}
|
|
37
|
+
if (process.env.TEMPMAIL_TIMEOUT) {
|
|
38
|
+
const t = parseInt(process.env.TEMPMAIL_TIMEOUT, 10);
|
|
39
|
+
if (!isNaN(t) && t > 0) config.timeout = t;
|
|
40
|
+
}
|
|
41
|
+
if (process.env.TEMPMAIL_INSECURE === '1' || process.env.TEMPMAIL_INSECURE?.toLowerCase() === 'true') {
|
|
42
|
+
config.insecure = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let globalConfig: SDKConfig = loadEnvConfig();
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 设置 SDK 全局配置
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // 一行跳过 SSL 验证
|
|
56
|
+
* setConfig({ insecure: true });
|
|
57
|
+
*
|
|
58
|
+
* // 设置代理和超时
|
|
59
|
+
* setConfig({ proxy: 'http://127.0.0.1:7890', timeout: 30000 });
|
|
60
|
+
*
|
|
61
|
+
* // 使用自定义 fetch(如支持代理的 undici)
|
|
62
|
+
* import { ProxyAgent, fetch as undiciFetch } from 'undici';
|
|
63
|
+
* const agent = new ProxyAgent('http://127.0.0.1:7890');
|
|
64
|
+
* setConfig({ customFetch: (url, init) => undiciFetch(url, { ...init, dispatcher: agent }) });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export function setConfig(config: SDKConfig): void {
|
|
68
|
+
globalConfig = { ...config };
|
|
69
|
+
/* Node.js 环境下 insecure 自动设置环境变量 */
|
|
70
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
71
|
+
if (config.insecure) {
|
|
72
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
73
|
+
} else {
|
|
74
|
+
delete process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 获取当前 SDK 全局配置 */
|
|
80
|
+
export function getConfig(): SDKConfig {
|
|
81
|
+
return globalConfig;
|
|
82
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -9,14 +9,24 @@ import * as mailTm from './providers/mail-tm';
|
|
|
9
9
|
import * as dropmail from './providers/dropmail';
|
|
10
10
|
import * as guerrillamail from './providers/guerrillamail';
|
|
11
11
|
import * as maildropProvider from './providers/maildrop';
|
|
12
|
-
import { Channel, EmailInfo, Email, EmailAttachment, GetEmailsResult, GenerateEmailOptions, GetEmailsOptions } from './types';
|
|
12
|
+
import { Channel, EmailInfo, InternalEmailInfo, Email, EmailAttachment, GetEmailsResult, GenerateEmailOptions, GetEmailsOptions } from './types';
|
|
13
13
|
import { withRetry, RetryOptions } from './retry';
|
|
14
14
|
import { logger } from './logger';
|
|
15
|
+
import { setConfig, getConfig } from './config';
|
|
15
16
|
|
|
16
17
|
export { Channel, EmailInfo, Email, EmailAttachment, GetEmailsResult, GenerateEmailOptions, GetEmailsOptions } from './types';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* SDK 内部 token 存储
|
|
21
|
+
* 使用 WeakMap 将 EmailInfo 对象映射到对应的 token
|
|
22
|
+
* 用户无法直接访问 token,由 SDK 自动管理
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
const tokenStore = new WeakMap<EmailInfo, string>();
|
|
17
26
|
export { normalizeEmail } from './normalize';
|
|
18
27
|
export { withRetry, fetchWithTimeout, RetryOptions } from './retry';
|
|
19
28
|
export { LogLevel, LogHandler, setLogLevel, getLogLevel, setLogger, logger } from './logger';
|
|
29
|
+
export { SDKConfig, setConfig, getConfig } from './config';
|
|
20
30
|
|
|
21
31
|
/** 渠道名称到 provider 实现的映射表 */
|
|
22
32
|
const providers = {
|
|
@@ -92,33 +102,70 @@ export function getChannelInfo(channel: Channel): ChannelInfo | undefined {
|
|
|
92
102
|
* 创建临时邮箱
|
|
93
103
|
*
|
|
94
104
|
* 错误处理策略:
|
|
95
|
-
* -
|
|
96
|
-
* -
|
|
105
|
+
* - 指定渠道失败时,自动尝试其他可用渠道(打乱顺序逐个尝试)
|
|
106
|
+
* - 未指定渠道时,打乱全部渠道逐个尝试,直到成功
|
|
107
|
+
* - 所有渠道均不可用时返回 null(不抛出异常)
|
|
97
108
|
*
|
|
98
109
|
* @param options - 创建选项,可指定渠道、有效时长、域名等
|
|
99
|
-
* @returns
|
|
100
|
-
* @throws 重试耗尽后仍失败时抛出异常
|
|
110
|
+
* @returns 邮箱信息,所有渠道均不可用时返回 null
|
|
101
111
|
*
|
|
102
112
|
* @example
|
|
103
113
|
* ```ts
|
|
104
114
|
* const emailInfo = await generateEmail({ channel: 'temp-mail-io' });
|
|
105
|
-
* console.log(emailInfo.email);
|
|
115
|
+
* if (emailInfo) console.log(emailInfo.email);
|
|
106
116
|
* ```
|
|
107
117
|
*/
|
|
108
|
-
export async function generateEmail(options: GenerateEmailOptions = {}): Promise<EmailInfo> {
|
|
109
|
-
|
|
118
|
+
export async function generateEmail(options: GenerateEmailOptions = {}): Promise<EmailInfo | null> {
|
|
119
|
+
/*
|
|
120
|
+
* 构建尝试顺序:
|
|
121
|
+
* - 指定渠道 → 优先尝试该渠道,失败后随机尝试其他渠道
|
|
122
|
+
* - 未指定 → 打乱全部渠道逐个尝试
|
|
123
|
+
*/
|
|
124
|
+
const tryOrder = buildChannelOrder(options.channel);
|
|
125
|
+
|
|
126
|
+
for (const ch of tryOrder) {
|
|
127
|
+
logger.info(`创建临时邮箱, 渠道: ${ch}`);
|
|
128
|
+
try {
|
|
129
|
+
const internal: InternalEmailInfo = await withRetry(() => generateEmailOnce(ch, options), options.retry);
|
|
130
|
+
logger.info(`邮箱创建成功: ${internal.email} (渠道: ${ch})`);
|
|
131
|
+
|
|
132
|
+
/* 将 token 存入内部存储,不暴露给用户 */
|
|
133
|
+
const publicInfo: EmailInfo = {
|
|
134
|
+
channel: internal.channel,
|
|
135
|
+
email: internal.email,
|
|
136
|
+
expiresAt: internal.expiresAt,
|
|
137
|
+
createdAt: internal.createdAt,
|
|
138
|
+
};
|
|
139
|
+
if (internal.token) {
|
|
140
|
+
tokenStore.set(publicInfo, internal.token);
|
|
141
|
+
}
|
|
142
|
+
return publicInfo;
|
|
143
|
+
} catch (err: any) {
|
|
144
|
+
logger.warn(`渠道 ${ch} 不可用: ${err.message || err},尝试下一个渠道`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
110
147
|
|
|
111
|
-
logger.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
148
|
+
logger.error('所有渠道均不可用,创建邮箱失败');
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 构建渠道尝试顺序
|
|
154
|
+
* 指定渠道时优先尝试该渠道,其余渠道打乱追加
|
|
155
|
+
* 未指定时打乱全部渠道
|
|
156
|
+
*/
|
|
157
|
+
function buildChannelOrder(preferred?: Channel): Channel[] {
|
|
158
|
+
const shuffled = [...allChannels].sort(() => Math.random() - 0.5);
|
|
159
|
+
if (!preferred) return shuffled;
|
|
160
|
+
const rest = shuffled.filter(ch => ch !== preferred);
|
|
161
|
+
return [preferred, ...rest];
|
|
115
162
|
}
|
|
116
163
|
|
|
117
164
|
/**
|
|
118
165
|
* 单次创建邮箱(不含重试逻辑)
|
|
119
166
|
* 根据渠道类型分发到对应的 provider 实现
|
|
120
167
|
*/
|
|
121
|
-
async function generateEmailOnce(channel: Channel, options: GenerateEmailOptions): Promise<
|
|
168
|
+
async function generateEmailOnce(channel: Channel, options: GenerateEmailOptions): Promise<InternalEmailInfo> {
|
|
122
169
|
switch (channel) {
|
|
123
170
|
case 'tempmail':
|
|
124
171
|
return tempmail.generateEmail(options.duration || 30);
|
|
@@ -149,32 +196,33 @@ async function generateEmailOnce(channel: Channel, options: GenerateEmailOptions
|
|
|
149
196
|
|
|
150
197
|
/**
|
|
151
198
|
* 获取邮件列表
|
|
199
|
+
* Channel/Email/Token 等由 SDK 从 EmailInfo 中自动获取,用户无需手动传递
|
|
152
200
|
*
|
|
153
201
|
* 错误处理策略:
|
|
154
|
-
* -
|
|
202
|
+
* - 网络错误、超时、429、服务端 5xx 错误 → 自动重试(默认 2 次)
|
|
155
203
|
* - 重试耗尽后返回 { success: false, emails: [] },不抛异常
|
|
156
|
-
* - 参数校验错误(缺少
|
|
204
|
+
* - 参数校验错误(缺少 EmailInfo)直接抛出
|
|
157
205
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* @param options - 获取选项,包含渠道、邮箱地址、令牌
|
|
206
|
+
* @param info - GenerateEmail() 返回的邮箱信息
|
|
207
|
+
* @param options - 可选配置(重试等)
|
|
162
208
|
* @returns 邮件结果,包含 success 标记和邮件列表
|
|
163
209
|
*
|
|
164
210
|
* @example
|
|
165
211
|
* ```ts
|
|
166
|
-
* const
|
|
167
|
-
*
|
|
168
|
-
* email: emailInfo.email,
|
|
169
|
-
* token: emailInfo.token,
|
|
170
|
-
* });
|
|
212
|
+
* const info = await generateEmail({ channel: 'mail-tm' });
|
|
213
|
+
* const result = await getEmails(info);
|
|
171
214
|
* if (result.success && result.emails.length > 0) {
|
|
172
215
|
* console.log('收到邮件:', result.emails[0].subject);
|
|
173
216
|
* }
|
|
174
217
|
* ```
|
|
175
218
|
*/
|
|
176
|
-
export async function getEmails(
|
|
177
|
-
|
|
219
|
+
export async function getEmails(info: EmailInfo, options?: GetEmailsOptions): Promise<GetEmailsResult> {
|
|
220
|
+
if (!info) {
|
|
221
|
+
throw new Error('EmailInfo is required, call generateEmail() first');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const { channel, email } = info;
|
|
225
|
+
const token = tokenStore.get(info);
|
|
178
226
|
|
|
179
227
|
if (!channel) {
|
|
180
228
|
throw new Error('Channel is required');
|
|
@@ -185,7 +233,7 @@ export async function getEmails(options: GetEmailsOptions): Promise<GetEmailsRes
|
|
|
185
233
|
|
|
186
234
|
logger.debug(`获取邮件, 渠道: ${channel}, 邮箱: ${email}`);
|
|
187
235
|
try {
|
|
188
|
-
const emails = await withRetry(() => getEmailsOnce(channel, email, token), options
|
|
236
|
+
const emails = await withRetry(() => getEmailsOnce(channel, email, token), options?.retry);
|
|
189
237
|
if (emails.length > 0) {
|
|
190
238
|
logger.info(`获取到 ${emails.length} 封邮件, 渠道: ${channel}`);
|
|
191
239
|
} else {
|
|
@@ -213,7 +261,7 @@ async function getEmailsOnce(channel: Channel, email: string, token?: string): P
|
|
|
213
261
|
case 'linshi-email':
|
|
214
262
|
return linshiEmail.getEmails(email);
|
|
215
263
|
case 'tempmail-lol':
|
|
216
|
-
if (!token) throw new Error('
|
|
264
|
+
if (!token) throw new Error('internal error: token missing for tempmail-lol');
|
|
217
265
|
return tempmailLol.getEmails(token, email);
|
|
218
266
|
case 'chatgpt-org-uk':
|
|
219
267
|
return chatgptOrgUk.getEmails(email);
|
|
@@ -222,19 +270,19 @@ async function getEmailsOnce(channel: Channel, email: string, token?: string): P
|
|
|
222
270
|
case 'temp-mail-io':
|
|
223
271
|
return tempMailIO.getEmails(email);
|
|
224
272
|
case 'awamail':
|
|
225
|
-
if (!token) throw new Error('
|
|
273
|
+
if (!token) throw new Error('internal error: token missing for awamail');
|
|
226
274
|
return awamail.getEmails(token, email);
|
|
227
275
|
case 'mail-tm':
|
|
228
|
-
if (!token) throw new Error('
|
|
276
|
+
if (!token) throw new Error('internal error: token missing for mail-tm');
|
|
229
277
|
return mailTm.getEmails(token, email);
|
|
230
278
|
case 'dropmail':
|
|
231
|
-
if (!token) throw new Error('
|
|
279
|
+
if (!token) throw new Error('internal error: token missing for dropmail');
|
|
232
280
|
return dropmail.getEmails(token, email);
|
|
233
281
|
case 'guerrillamail':
|
|
234
|
-
if (!token) throw new Error('
|
|
282
|
+
if (!token) throw new Error('internal error: token missing for guerrillamail');
|
|
235
283
|
return guerrillamail.getEmails(token, email);
|
|
236
284
|
case 'maildrop':
|
|
237
|
-
if (!token) throw new Error('
|
|
285
|
+
if (!token) throw new Error('internal error: token missing for maildrop');
|
|
238
286
|
return maildropProvider.getEmails(token, email);
|
|
239
287
|
default:
|
|
240
288
|
throw new Error(`Unknown channel: ${channel}`);
|
|
@@ -264,8 +312,9 @@ export class TempEmailClient {
|
|
|
264
312
|
/**
|
|
265
313
|
* 创建临时邮箱并缓存邮箱信息
|
|
266
314
|
* 后续调用 getEmails() 时自动使用此邮箱的渠道、地址和令牌
|
|
315
|
+
* 所有渠道均不可用时返回 null
|
|
267
316
|
*/
|
|
268
|
-
async generate(options: GenerateEmailOptions = {}): Promise<EmailInfo> {
|
|
317
|
+
async generate(options: GenerateEmailOptions = {}): Promise<EmailInfo | null> {
|
|
269
318
|
this.emailInfo = await generateEmail(options);
|
|
270
319
|
return this.emailInfo;
|
|
271
320
|
}
|
|
@@ -276,16 +325,12 @@ export class TempEmailClient {
|
|
|
276
325
|
*
|
|
277
326
|
* @throws 未调用 generate() 时抛出异常
|
|
278
327
|
*/
|
|
279
|
-
async getEmails(): Promise<GetEmailsResult> {
|
|
328
|
+
async getEmails(options?: GetEmailsOptions): Promise<GetEmailsResult> {
|
|
280
329
|
if (!this.emailInfo) {
|
|
281
330
|
throw new Error('No email generated. Call generate() first.');
|
|
282
331
|
}
|
|
283
332
|
|
|
284
|
-
return getEmails(
|
|
285
|
-
channel: this.emailInfo.channel,
|
|
286
|
-
email: this.emailInfo.email,
|
|
287
|
-
token: this.emailInfo.token,
|
|
288
|
-
});
|
|
333
|
+
return getEmails(this.emailInfo, options);
|
|
289
334
|
}
|
|
290
335
|
|
|
291
336
|
/**
|
|
@@ -303,4 +348,6 @@ export default {
|
|
|
303
348
|
generateEmail,
|
|
304
349
|
getEmails,
|
|
305
350
|
TempEmailClient,
|
|
351
|
+
setConfig,
|
|
352
|
+
getConfig,
|
|
306
353
|
};
|
package/src/normalize.ts
CHANGED
|
@@ -11,19 +11,47 @@ import { Email, EmailAttachment } from './types';
|
|
|
11
11
|
* @returns 标准化的 Email 对象
|
|
12
12
|
*/
|
|
13
13
|
export function normalizeEmail(raw: any, recipientEmail: string = ''): Email {
|
|
14
|
+
let text = normalizeText(raw);
|
|
15
|
+
let html = normalizeHtml(raw);
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* 修正 text/html 错配:
|
|
19
|
+
* 部分渠道将 HTML 内容放在 body/text 等字段中,
|
|
20
|
+
* 导致 normalizeText 提取到 HTML 内容而 normalizeHtml 为空。
|
|
21
|
+
* 检测 text 中是否包含 HTML 标签,如果是则移动到 html 字段。
|
|
22
|
+
*/
|
|
23
|
+
if (text && !html && isHtmlContent(text)) {
|
|
24
|
+
html = text;
|
|
25
|
+
text = '';
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
return {
|
|
15
29
|
id: normalizeId(raw),
|
|
16
30
|
from: normalizeFrom(raw),
|
|
17
31
|
to: normalizeTo(raw, recipientEmail),
|
|
18
32
|
subject: normalizeSubject(raw),
|
|
19
|
-
text
|
|
20
|
-
html
|
|
33
|
+
text,
|
|
34
|
+
html,
|
|
21
35
|
date: normalizeDate(raw),
|
|
22
36
|
isRead: normalizeIsRead(raw),
|
|
23
37
|
attachments: normalizeAttachments(raw.attachments),
|
|
24
38
|
};
|
|
25
39
|
}
|
|
26
40
|
|
|
41
|
+
/**
|
|
42
|
+
* 检测内容是否为 HTML
|
|
43
|
+
* 通过检查是否包含常见的 HTML 标签来判断
|
|
44
|
+
*/
|
|
45
|
+
function isHtmlContent(content: string): boolean {
|
|
46
|
+
const trimmed = content.trim().toLowerCase();
|
|
47
|
+
return trimmed.startsWith('<!doctype html') ||
|
|
48
|
+
trimmed.startsWith('<html') ||
|
|
49
|
+
trimmed.startsWith('<body') ||
|
|
50
|
+
(trimmed.includes('<div') && trimmed.includes('</div>')) ||
|
|
51
|
+
(trimmed.includes('<table') && trimmed.includes('</table>')) ||
|
|
52
|
+
(trimmed.includes('<p') && trimmed.includes('</p>') && trimmed.includes('<'));
|
|
53
|
+
}
|
|
54
|
+
|
|
27
55
|
/**
|
|
28
56
|
* 提取邮件 ID
|
|
29
57
|
* 候选字段: id, eid, _id, mailboxId, messageId, mail_id
|
package/src/providers/awamail.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'awamail';
|
|
@@ -36,7 +36,7 @@ function extractSessionCookie(response: Response): string {
|
|
|
36
36
|
* 返回: { success, data: { email_address, expired_at, created_at, ... } }
|
|
37
37
|
* 需要保存响应中的 Set-Cookie (awamail_session) 用于后续获取邮件
|
|
38
38
|
*/
|
|
39
|
-
export async function generateEmail(): Promise<
|
|
39
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
40
40
|
const response = await fetch(`${BASE_URL}/change_mailbox`, {
|
|
41
41
|
method: 'POST',
|
|
42
42
|
headers: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'chatgpt-org-uk';
|
|
@@ -15,7 +15,7 @@ const DEFAULT_HEADERS = {
|
|
|
15
15
|
'DNT': '1',
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export async function generateEmail(): Promise<
|
|
18
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
19
19
|
const response = await fetch(`${BASE_URL}/generate-email`, {
|
|
20
20
|
method: 'GET',
|
|
21
21
|
headers: DEFAULT_HEADERS,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'dropmail';
|
|
@@ -53,7 +53,7 @@ async function graphqlRequest(query: string, variables?: Record<string, any>): P
|
|
|
53
53
|
* GraphQL mutation: introduceSession
|
|
54
54
|
* 返回 session ID (存入 token) 和邮箱地址
|
|
55
55
|
*/
|
|
56
|
-
export async function generateEmail(): Promise<
|
|
56
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
57
57
|
const data = await graphqlRequest(CREATE_SESSION_QUERY);
|
|
58
58
|
|
|
59
59
|
const session = data?.introduceSession;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - 邮箱有效期 60 分钟
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
12
12
|
import { normalizeEmail } from '../normalize';
|
|
13
13
|
|
|
14
14
|
const CHANNEL: Channel = 'guerrillamail';
|
|
@@ -19,7 +19,7 @@ const BASE_URL = 'https://api.guerrillamail.com/ajax.php';
|
|
|
19
19
|
* API: GET ajax.php?f=get_email_address
|
|
20
20
|
* 返回 email_addr + sid_token(用于后续获取邮件)
|
|
21
21
|
*/
|
|
22
|
-
export async function generateEmail(): Promise<
|
|
22
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
23
23
|
const response = await fetch(`${BASE_URL}?f=get_email_address&lang=en`, {
|
|
24
24
|
method: 'GET',
|
|
25
25
|
headers: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'linshi-email';
|
|
@@ -16,7 +16,7 @@ const DEFAULT_HEADERS = {
|
|
|
16
16
|
'DNT': '1',
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export async function generateEmail(): Promise<
|
|
19
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
20
20
|
const response = await fetch(`${BASE_URL}/email/${API_KEY}`, {
|
|
21
21
|
method: 'POST',
|
|
22
22
|
headers: DEFAULT_HEADERS,
|
package/src/providers/mail-tm.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'mail-tm';
|
|
@@ -88,7 +88,7 @@ async function getToken(address: string, password: string): Promise<string> {
|
|
|
88
88
|
* 创建临时邮箱
|
|
89
89
|
* 流程: 获取域名 → 生成随机邮箱/密码 → 创建账号 → 获取 Token
|
|
90
90
|
*/
|
|
91
|
-
export async function generateEmail(): Promise<
|
|
91
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
92
92
|
// 1. 获取可用域名
|
|
93
93
|
const domains = await getDomains();
|
|
94
94
|
if (domains.length === 0) {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - 无过期时间限制
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
13
13
|
|
|
14
14
|
const CHANNEL: Channel = 'maildrop';
|
|
15
15
|
const GRAPHQL_URL = 'https://api.maildrop.cc/graphql';
|
|
@@ -140,7 +140,7 @@ async function graphqlRequest(
|
|
|
140
140
|
* 创建临时邮箱
|
|
141
141
|
* Maildrop 无需注册,任意用户名即可接收邮件
|
|
142
142
|
*/
|
|
143
|
-
export async function generateEmail(): Promise<
|
|
143
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
144
144
|
const username = randomUsername();
|
|
145
145
|
const email = `${username}@${DOMAIN}`;
|
|
146
146
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'temp-mail-io';
|
|
@@ -59,7 +59,7 @@ async function getApiHeaders(): Promise<Record<string, string>> {
|
|
|
59
59
|
* API: POST /api/v3/email/new
|
|
60
60
|
* 返回: { email, token }
|
|
61
61
|
*/
|
|
62
|
-
export async function generateEmail(): Promise<
|
|
62
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
63
63
|
const headers = await getApiHeaders();
|
|
64
64
|
const response = await fetch(`${BASE_URL}/email/new`, {
|
|
65
65
|
method: 'POST',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'tempmail-la';
|
|
@@ -30,7 +30,7 @@ const DEFAULT_HEADERS: Record<string, string> = {
|
|
|
30
30
|
* API: POST /api/mail/create
|
|
31
31
|
* 返回: { code: 0, data: { mailId, address, type, startAt, endAt } }
|
|
32
32
|
*/
|
|
33
|
-
export async function generateEmail(): Promise<
|
|
33
|
+
export async function generateEmail(): Promise<InternalEmailInfo> {
|
|
34
34
|
const response = await fetch(`${BASE_URL}/mail/create`, {
|
|
35
35
|
method: 'POST',
|
|
36
36
|
headers: DEFAULT_HEADERS,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalEmailInfo, Email, Channel } from '../types';
|
|
2
2
|
import { normalizeEmail } from '../normalize';
|
|
3
3
|
|
|
4
4
|
const CHANNEL: Channel = 'tempmail-lol';
|
|
@@ -14,7 +14,7 @@ const DEFAULT_HEADERS = {
|
|
|
14
14
|
'DNT': '1',
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export async function generateEmail(domain: string | null = null): Promise<
|
|
17
|
+
export async function generateEmail(domain: string | null = null): Promise<InternalEmailInfo> {
|
|
18
18
|
const response = await fetch(`${BASE_URL}/inbox/create`, {
|
|
19
19
|
method: 'POST',
|
|
20
20
|
headers: DEFAULT_HEADERS,
|