tempmail-sdk 1.1.2 → 1.1.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.
package/dist/retry.js CHANGED
@@ -17,8 +17,13 @@ const DEFAULT_RETRY_OPTIONS = {
17
17
  };
18
18
  /**
19
19
  * 默认重试判断
20
- * 网络错误、超时、HTTP 4xx/5xx 错误均可重试
21
- * 仅参数校验类错误(由 SDK 内部抛出)不重试
20
+ * 以下错误类型会触发重试:
21
+ * - 网络连接错误(fetch failed, ECONNREFUSED, ECONNRESET 等)
22
+ * - 超时错误(timeout, abort)
23
+ * - DNS 解析失败
24
+ * - HTTP 429 限流
25
+ * - HTTP 4xx/5xx 服务端错误(含状态码的错误消息)
26
+ * 仅 SDK 内部的参数校验类错误不重试
22
27
  */
23
28
  function defaultShouldRetry(error) {
24
29
  if (!error)
@@ -40,7 +45,7 @@ function defaultShouldRetry(error) {
40
45
  if (message.includes('429') || message.includes('too many requests') || message.includes('rate limit')) {
41
46
  return true;
42
47
  }
43
- /* HTTP 4xx/5xx 错误 重试 */
48
+ /* HTTP 4xx/5xx 错误(含状态码的错误消息)→ 重试 */
44
49
  const statusMatch = message.match(/:\s*(\d{3})/);
45
50
  if (statusMatch) {
46
51
  const status = parseInt(statusMatch[1], 10);
@@ -56,9 +61,9 @@ function sleep(ms) {
56
61
  }
57
62
  /**
58
63
  * 带重试的异步操作执行器
59
- * - 自动重试可恢复的错误(网络错误、超时、5xx)
64
+ * - 自动重试可恢复的错误(网络错误、超时、HTTP 4xx/5xx)
60
65
  * - 指数退避避免过度请求
61
- * - 不可恢复的错误(4xx 参数错误等)直接抛出不重试
66
+ * - 不可恢复的错误(SDK 内部参数校验错误等)直接抛出不重试
62
67
  *
63
68
  * @param fn 要执行的异步操作
64
69
  * @param options 重试配置
@@ -103,13 +108,39 @@ async function withRetry(fn, options) {
103
108
  * @param init fetch 选项
104
109
  * @param timeoutMs 超时时间(毫秒)
105
110
  */
106
- async function fetchWithTimeout(url, init, timeoutMs) {
111
+ /**
112
+ * 缓存的全局配置快照,避免每次请求都读取
113
+ * 仅在 setConfig 被调用时失效(通过 configVersion 比对)
114
+ */
115
+ let _cachedFetchConfig = null;
116
+ /**
117
+ * 获取缓存的 fetch 配置
118
+ */
119
+ function getFetchConfig() {
107
120
  const config = (0, config_1.getConfig)();
108
- const effectiveTimeout = timeoutMs ?? config.timeout ?? DEFAULT_RETRY_OPTIONS.timeout;
121
+ /* 简单的引用比对即可,getConfig 在未变更时返回同一对象 */
122
+ if (!_cachedFetchConfig || _cachedFetchConfig.fetchFn !== (config.customFetch || fetch) || _cachedFetchConfig.timeout !== (config.timeout ?? DEFAULT_RETRY_OPTIONS.timeout)) {
123
+ _cachedFetchConfig = {
124
+ fetchFn: config.customFetch || fetch,
125
+ timeout: config.timeout ?? DEFAULT_RETRY_OPTIONS.timeout,
126
+ version: 0,
127
+ };
128
+ }
129
+ return _cachedFetchConfig;
130
+ }
131
+ async function fetchWithTimeout(url, init, timeoutMs) {
132
+ const { fetchFn, timeout: defaultTimeout } = getFetchConfig();
133
+ const effectiveTimeout = timeoutMs ?? defaultTimeout;
109
134
  const controller = new AbortController();
110
135
  const timeoutId = setTimeout(() => controller.abort(), effectiveTimeout);
111
- /* 使用自定义 fetch 或原生 fetch */
112
- const fetchFn = config.customFetch || fetch;
136
+ /*
137
+ * 如果调用方已提供 signal,需要同时监听两个信号(调用方 + 超时)
138
+ * 任一触发则中断请求
139
+ */
140
+ const externalSignal = init?.signal;
141
+ if (externalSignal) {
142
+ externalSignal.addEventListener('abort', () => controller.abort(), { once: true });
143
+ }
113
144
  try {
114
145
  const response = await fetchFn(url, {
115
146
  ...init,
@@ -127,4 +158,4 @@ async function fetchWithTimeout(url, init, timeoutMs) {
127
158
  clearTimeout(timeoutId);
128
159
  }
129
160
  }
130
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcmV0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7QUFtRkgsOEJBaUNDO0FBVUQsNENBMkJDO0FBdkpELHFDQUFrQztBQUNsQyxxQ0FBcUM7QUFrQnJDLE1BQU0scUJBQXFCLEdBQTJCO0lBQ3BELFVBQVUsRUFBRSxDQUFDO0lBQ2IsWUFBWSxFQUFFLElBQUk7SUFDbEIsUUFBUSxFQUFFLElBQUk7SUFDZCxPQUFPLEVBQUUsS0FBSztJQUNkLFdBQVcsRUFBRSxrQkFBa0I7Q0FDaEMsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxTQUFTLGtCQUFrQixDQUFDLEtBQVU7SUFDcEMsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUV6QixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFbkUsaUJBQWlCO0lBQ2pCLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7UUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7UUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDOUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7UUFDN0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQztRQUNsQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUN2QixPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDOUIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsc0JBQXNCO0lBQ3RCLElBQUksT0FBTyxDQUFDLFFBQVEs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Q3BDLEdBQVcsRUFDWCxJQUFrQixFQUNsQixTQUFrQjtJQUVsQixNQUFNLE1BQU0sR0FBRyxJQUFBLGtCQUFTLEdBQUUsQ0FBQztJQUMzQixNQUFNLGdCQUFnQixHQUFHLFNBQVMsSUFBSSxNQUFNLENBQUMsT0FBTyxJQUFJLHFCQUFxQixDQUFDLE9BQU8sQ0FBQztJQUN0RixNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ3pDLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUV6RSwyQkFBMkI7SUFDM0IsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFdBQVcsSUFBSSxLQUFLLENBQUM7SUFFNUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxFQUFFO1lBQ2xDLEdBQUcsSUFBSTtZQUNQLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTTtTQUMxQixDQUFDLENBQUM7UUFDSCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztRQUNwQixJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7WUFDaEMsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsZ0JBQWdCLE9BQU8sR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN6RSxDQUFDO1FBQ0QsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO1lBQVMsQ0FBQztRQUNULFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMxQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog6YCa55So6YeN6K+V5bel5YW3XG4gKiDmj5Dkvpvor7fmsYLph43or5XjgIHotoXml7bmjqfliLbjgIHmjIfmlbDpgIDpgb/nrYnplJnor6/mgaLlpI3mnLrliLZcbiAqL1xuXG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgeyBnZXRDb25maWcgfSBmcm9tICcuL2NvbmZpZyc7XG5cbi8qKlxuICog6YeN6K+V6YWN572u6YCJ6aG5XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmV0cnlPcHRpb25zIHtcbiAgLyoqIOacgOWkp+mHjeivleasoeaVsO+8iOS4jeWQq+mmluasoeivt+axgu+8ie+8jOm7mOiupCAyICovXG4gIG1heFJldHJpZXM/OiBudW1iZXI7XG4gIC8qKiDliJ3lp4vph43or5Xlu7bov5/vvIjmr6vnp5LvvInvvIzpu5jorqQgMTAwMCAqL1xuICBpbml0aWFsRGVsYXk/OiBudW1iZXI7XG4gIC8qKiDmnIDlpKfph43or5Xlu7bov5/vvIjmr6vnp5LvvInvvIzpu5jorqQgNTAwMCAqL1xuICBtYXhEZWxheT86IG51bWJlcjtcbiAgLyoqIOivt+axgui2heaXtuaXtumXtO+8iOavq+enku+8ie+8jOm7mOiupCAxNTAwMCAqL1xuICB0aW1lb3V0PzogbnVtYmVyO1xuICAvKiog5piv5ZCm5a+56K+l6ZSZ6K+v6L+b6KGM6YeN6K+V55qE5Yik5pat5Ye95pWwICovXG4gIHNob3VsZFJldHJ5PzogKGVycm9yOiBhbnkpID0+IGJvb2xlYW47XG59XG5cbmNvbnN0IERFRkFVTFRfUkVUUllfT1BUSU9OUzogUmVxdWlyZWQ8UmV0cnlPcHRpb25zPiA9IHtcbiAgbWF4UmV0cmllczogMixcbiAgaW5pdGlhbERlbGF5OiAxMDAwLFxuICBtYXhEZWxheTogNTAwMCxcbiAgdGltZW91dDogMTUwMDAsXG4gIHNob3VsZFJldHJ5OiBkZWZhdWx0U2hvdWxkUmV0cnksXG59O1xuXG4vKipcbiAqIOm7mOiupOmHjeivleWIpOaWrVxuICog572R57uc6ZSZ6K+v44CB6LaF5pe244CBSFRUUCA0eHgvNXh4IOmUmeivr+Wdh+WPr+mHjeivlVxuICog5LuF5Y+C5pWw5qCh6aqM57G76ZSZ6K+v77yI55SxIFNESyDlhoXpg6jmipvlh7rvvInkuI3ph43or5VcbiAqL1xuZnVuY3Rpb24gZGVmYXVsdFNob3VsZFJldHJ5KGVycm9yOiBhbnkpOiBib29sZWFuIHtcbiAgaWYgKCFlcnJvcikgcmV0dXJuIGZhbHNlO1xuXG4gIGNvbnN0IG1lc3NhZ2UgPSBTdHJpbmcoZXJyb3IubWVzc2FnZSB8fCBlcnJvciB8fCAnJykudG9Mb3dlckNhc2UoKTtcblxuICAvKiDnvZHnu5znuqfliKvplJnor68g4oaSIOmHjeivlSAqL1xuICBpZiAobWVzc2FnZS5pbmNsdWRlcygnZmV0Y2ggZmFpbGVkJykgfHxcbiAgICAgIG1lc3NhZ2UuaW5jbHVkZXMoJ25ldHdvcmsnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnZWNvbm5yZWZ1c2VkJykgfHxcbiAgICAgIG1lc3NhZ2UuaW5jbHVkZXMoJ2Vjb25ucmVzZXQnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnZXRpbWVkb3V0JykgfHxcbiAgICAgIG1lc3NhZ2UuaW5jbHVkZXMoJ3RpbWVvdXQnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnc29ja2V0IGhhbmcgdXAnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnZG5zJykgfHxcbiAgICAgIG1lc3NhZ2UuaW5jbHVkZXMoJ2Fib3J0JykpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qIEhUVFAgNDI5IOmZkOa1gSDihpIg6YeN6K+VICovXG4gIGlmIChtZXNzYWdlLmluY2x1ZGVzKCc0MjknKSB8fCBtZXNzYWdlLmluY2x1ZGVzKCd0b28gbWFueSByZXF1ZXN0cycpIHx8IG1lc3NhZ2UuaW5jbHVkZXMoJ3JhdGUgbGltaXQnKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyogSFRUUCA0eHgvNXh4IOmUmeivryDihpIg6YeN6K+VICovXG4gIGNvbnN0IHN0YXR1c01hdGNoID0gbWVzc2FnZS5tYXRjaCgvOlxccyooXFxkezN9KS8pO1xuICBpZiAoc3RhdHVzTWF0Y2gpIHtcbiAgICBjb25zdCBzdGF0dXMgPSBwYXJzZUludChzdGF0dXNNYXRjaFsxXSwgMTApO1xuICAgIHJldHVybiBzdGF0dXMgPj0gNDAwO1xuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIOS8keecoOaMh+Wumuavq+enklxuICovXG5mdW5jdGlvbiBzbGVlcChtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxuLyoqXG4gKiDluKbph43or5XnmoTlvILmraXmk43kvZzmiafooYzlmahcbiAqIC0g6Ieq5Yqo6YeN6K+V5Y+v5oGi5aSN55qE6ZSZ6K+v77yI572R57uc6ZSZ6K+v44CB6LaF5pe244CBNXh477yJXG4gKiAtIOaMh+aVsOmAgOmBv+mBv+WFjei/h+W6puivt+axglxuICogLSDkuI3lj6/mgaLlpI3nmoTplJnor6/vvIg0eHgg5Y+C5pWw6ZSZ6K+v562J77yJ55u05o6l5oqb5Ye65LiN6YeN6K+VXG4gKlxuICogQHBhcmFtIGZuIOimgeaJp+ihjOeahOW8guatpeaTjeS9nFxuICogQHBhcmFtIG9wdGlvbnMg6YeN6K+V6YWN572uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoUmV0cnk8VD4oZm46ICgpID0+IFByb21pc2U8VD4sIG9wdGlvbnM/OiBSZXRyeU9wdGlvbnMpOiBQcm9taXNlPFQ+IHtcbiAgY29uc3Qgb3B0cyA9IHsgLi4uREVGQVVMVF9SRVRSWV9PUFRJT05TLCAuLi5vcHRpb25zIH07XG4gIGxldCBsYXN0RXJyb3I6IGFueTtcblxuICBmb3IgKGxldCBhdHRlbXB0ID0gMDsgYXR0ZW1wdCA8PSBvcHRzLm1heFJldHJpZXM7IGF0dGVtcHQrKykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbigpO1xuICAgICAgaWYgKGF0dGVtcHQgPiAwKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGDnrKwgJHthdHRlbXB0ICsgMX0g5qyh5bCd6K+V5oiQ5YqfYCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGxhc3RFcnJvciA9IGVycm9yO1xuICAgICAgY29uc3QgZXJyb3JNc2cgPSBlcnJvci5tZXNzYWdlIHx8IFN0cmluZyhlcnJvcik7XG5cbiAgICAgIC8qIOacgOWQjuS4gOasoeWwneivleWksei0peaIluS4jeWPr+mHjeivleeahOmUmeivryDihpIg55u05o6l5oqb5Ye6ICovXG4gICAgICBpZiAoYXR0ZW1wdCA+PSBvcHRzLm1heFJldHJpZXMgfHwgIW9wdHMuc2hvdWxkUmV0cnkoZXJyb3IpKSB7XG4gICAgICAgIGlmIChhdHRlbXB0ID49IG9wdHMubWF4UmV0cmllcyAmJiBvcHRzLm1heFJldHJpZXMgPiAwKSB7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKGDph43or5UgJHtvcHRzLm1heFJldHJpZXN9IOasoeWQjuS7jeWksei0pTogJHtlcnJvck1zZ31gKTtcbiAgICAgICAgfSBlbHNlIGlmICghb3B0cy5zaG91bGRSZXRyeShlcnJvcikpIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYOS4jeWPr+mHjeivleeahOmUmeivrzogJHtlcnJvck1zZ31gKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cblxuICAgICAgLyog5oyH5pWw6YCA6YG/562J5b6FICovXG4gICAgICBjb25zdCBkZWxheSA9IE1hdGgubWluKG9wdHMuaW5pdGlhbERlbGF5ICogTWF0aC5wb3coMiwgYXR0ZW1wdCksIG9wdHMubWF4RGVsYXkpO1xuICAgICAgbG9nZ2VyLndhcm4oYOivt+axguWksei0pSAoJHtlcnJvck1zZ30p77yMJHtkZWxheX1tcyDlkI7nrKwgJHthdHRlbXB0ICsgMn0g5qyh6YeN6K+VLi4uYCk7XG4gICAgICBhd2FpdCBzbGVlcChkZWxheSk7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbGFzdEVycm9yO1xufVxuXG4vKipcbiAqIOW4pui2heaXtuaOp+WItueahCBmZXRjaCDljIXoo4VcbiAqIOWcqOWOn+eUnyBmZXRjaCDln7rnoYDkuIrmt7vliqDotoXml7bkuK3mlq3og73liptcbiAqXG4gKiBAcGFyYW0gdXJsIOivt+axgiBVUkxcbiAqIEBwYXJhbSBpbml0IGZldGNoIOmAiemhuVxuICogQHBhcmFtIHRpbWVvdXRNcyDotoXml7bml7bpl7TvvIjmr6vnp5LvvIlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoV2l0aFRpbWVvdXQoXG4gIHVybDogc3RyaW5nLFxuICBpbml0PzogUmVxdWVzdEluaXQsXG4gIHRpbWVvdXRNcz86IG51bWJlcixcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IGVmZmVjdGl2ZVRpbWVvdXQgPSB0aW1lb3V0TXMgPz8gY29uZmlnLnRpbWVvdXQgPz8gREVGQVVMVF9SRVRSWV9PUFRJT05TLnRpbWVvdXQ7XG4gIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGNvbnN0IHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCBlZmZlY3RpdmVUaW1lb3V0KTtcblxuICAvKiDkvb/nlKjoh6rlrprkuYkgZmV0Y2gg5oiW5Y6f55SfIGZldGNoICovXG4gIGNvbnN0IGZldGNoRm4gPSBjb25maWcuY3VzdG9tRmV0Y2ggfHwgZmV0Y2g7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoRm4odXJsLCB7XG4gICAgICAuLi5pbml0LFxuICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICBpZiAoZXJyb3IubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlcXVlc3QgdGltZW91dCBhZnRlciAke2VmZmVjdGl2ZVRpbWVvdXR9bXM6ICR7dXJsfWApO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfSBmaW5hbGx5IHtcbiAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgfVxufVxuIl19
161
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcmV0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7QUF3RkgsOEJBaUNDO0FBZ0NELDRDQWlDQztBQXhMRCxxQ0FBa0M7QUFDbEMscUNBQXFDO0FBa0JyQyxNQUFNLHFCQUFxQixHQUEyQjtJQUNwRCxVQUFVLEVBQUUsQ0FBQztJQUNiLFlBQVksRUFBRSxJQUFJO0lBQ2xCLFFBQVEsRUFBRSxJQUFJO0lBQ2QsT0FBTyxFQUFFLEtBQUs7SUFDZCxXQUFXLEVBQUUsa0JBQWtCO0NBQ2hDLENBQUM7QUFFRjs7Ozs7Ozs7O0dBU0c7QUFDSCxTQUFTLGtCQUFrQixDQUFDLEtBQVU7SUFDcEMsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUV6QixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFbkUsaUJBQWlCO0lBQ2pCLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7UUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7UUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDOUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7UUFDN0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQztRQUNsQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUN2QixPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDOUIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsc0JBQXNCO0lBQ3RCLElBQUksT0FBTyxDQUFD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S0FBSyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxFQUFFO1lBQ2xDLEdBQUcsSUFBSTtZQUNQLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTTtTQUMxQixDQUFDLENBQUM7UUFDSCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztRQUNwQixJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7WUFDaEMsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsZ0JBQWdCLE9BQU8sR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN6RSxDQUFDO1FBQ0QsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO1lBQVMsQ0FBQztRQUNULFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMxQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog6YCa55So6YeN6K+V5bel5YW3XG4gKiDmj5Dkvpvor7fmsYLph43or5XjgIHotoXml7bmjqfliLbjgIHmjIfmlbDpgIDpgb/nrYnplJnor6/mgaLlpI3mnLrliLZcbiAqL1xuXG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgeyBnZXRDb25maWcgfSBmcm9tICcuL2NvbmZpZyc7XG5cbi8qKlxuICog6YeN6K+V6YWN572u6YCJ6aG5XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmV0cnlPcHRpb25zIHtcbiAgLyoqIOacgOWkp+mHjeivleasoeaVsO+8iOS4jeWQq+mmluasoeivt+axgu+8ie+8jOm7mOiupCAyICovXG4gIG1heFJldHJpZXM/OiBudW1iZXI7XG4gIC8qKiDliJ3lp4vph43or5Xlu7bov5/vvIjmr6vnp5LvvInvvIzpu5jorqQgMTAwMCAqL1xuICBpbml0aWFsRGVsYXk/OiBudW1iZXI7XG4gIC8qKiDmnIDlpKfph43or5Xlu7bov5/vvIjmr6vnp5LvvInvvIzpu5jorqQgNTAwMCAqL1xuICBtYXhEZWxheT86IG51bWJlcjtcbiAgLyoqIOivt+axgui2heaXtuaXtumXtO+8iOavq+enku+8ie+8jOm7mOiupCAxNTAwMCAqL1xuICB0aW1lb3V0PzogbnVtYmVyO1xuICAvKiog5piv5ZCm5a+56K+l6ZSZ6K+v6L+b6KGM6YeN6K+V55qE5Yik5pat5Ye95pWwICovXG4gIHNob3VsZFJldHJ5PzogKGVycm9yOiBhbnkpID0+IGJvb2xlYW47XG59XG5cbmNvbnN0IERFRkFVTFRfUkVUUllfT1BUSU9OUzogUmVxdWlyZWQ8UmV0cnlPcHRpb25zPiA9IHtcbiAgbWF4UmV0cmllczogMixcbiAgaW5pdGlhbERlbGF5OiAxMDAwLFxuICBtYXhEZWxheTogNTAwMCxcbiAgdGltZW91dDogMTUwMDAsXG4gIHNob3VsZFJldHJ5OiBkZWZhdWx0U2hvdWxkUmV0cnksXG59O1xuXG4vKipcbiAqIOm7mOiupOmHjeivleWIpOaWrVxuICog5Lul5LiL6ZSZ6K+v57G75Z6L5Lya6Kem5Y+R6YeN6K+V77yaXG4gKiAtIOe9kee7nOi/nuaOpemUmeivr++8iGZldGNoIGZhaWxlZCwgRUNPTk5SRUZVU0VELCBFQ09OTlJFU0VUIOetie+8iVxuICogLSDotoXml7bplJnor6/vvIh0aW1lb3V0LCBhYm9ydO+8iVxuICogLSBETlMg6Kej5p6Q5aSx6LSlXG4gKiAtIEhUVFAgNDI5IOmZkOa1gVxuICogLSBIVFRQIDR4eC81eHgg5pyN5Yqh56uv6ZSZ6K+v77yI5ZCr54q25oCB56CB55qE6ZSZ6K+v5raI5oGv77yJXG4gKiDku4UgU0RLIOWGhemDqOeahOWPguaVsOagoemqjOexu+mUmeivr+S4jemHjeivlVxuICovXG5mdW5jdGlvbiBkZWZhdWx0U2hvdWxkUmV0cnkoZXJyb3I6IGFueSk6IGJvb2xlYW4ge1xuICBpZiAoIWVycm9yKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3QgbWVzc2FnZSA9IFN0cmluZyhlcnJvci5tZXNzYWdlIHx8IGVycm9yIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuXG4gIC8qIOe9kee7nOe6p+WIq+mUmeivryDihpIg6YeN6K+VICovXG4gIGlmIChtZXNzYWdlLmluY2x1ZGVzKCdmZXRjaCBmYWlsZWQnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnbmV0d29yaycpIHx8XG4gICAgICBtZXNzYWdlLmluY2x1ZGVzKCdlY29ubnJlZnVzZWQnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnZWNvbm5yZXNldCcpIHx8XG4gICAgICBtZXNzYWdlLmluY2x1ZGVzKCdldGltZWRvdXQnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygndGltZW91dCcpIHx8XG4gICAgICBtZXNzYWdlLmluY2x1ZGVzKCdzb2NrZXQgaGFuZyB1cCcpIHx8XG4gICAgICBtZXNzYWdlLmluY2x1ZGVzKCdkbnMnKSB8fFxuICAgICAgbWVzc2FnZS5pbmNsdWRlcygnYWJvcnQnKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyogSFRUUCA0Mjkg6ZmQ5rWBIOKGkiDph43or5UgKi9cbiAgaWYgKG1lc3NhZ2UuaW5jbHVkZXMoJzQyOScpIHx8IG1lc3NhZ2UuaW5jbHVkZXMoJ3RvbyBtYW55IHJlcXVlc3RzJykgfHwgbWVzc2FnZS5pbmNsdWRlcygncmF0ZSBsaW1pdCcpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiBIVFRQIDR4eC81eHgg6ZSZ6K+v77yI5ZCr54q25oCB56CB55qE6ZSZ6K+v5raI5oGv77yJ4oaSIOmHjeivlSAqL1xuICBjb25zdCBzdGF0dXNNYXRjaCA9IG1lc3NhZ2UubWF0Y2goLzpcXHMqKFxcZHszfSkvKTtcbiAgaWYgKHN0YXR1c01hdGNoKSB7XG4gICAgY29uc3Qgc3RhdHVzID0gcGFyc2VJbnQoc3RhdHVzTWF0Y2hbMV0sIDEwKTtcbiAgICByZXR1cm4gc3RhdHVzID49IDQwMDtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiDkvJHnnKDmjIflrprmr6vnp5JcbiAqL1xuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbi8qKlxuICog5bim6YeN6K+V55qE5byC5q2l5pON5L2c5omn6KGM5ZmoXG4gKiAtIOiHquWKqOmHjeivleWPr+aBouWkjeeahOmUmeivr++8iOe9kee7nOmUmeivr+OAgei2heaXtuOAgUhUVFAgNHh4LzV4eO+8iVxuICogLSDmjIfmlbDpgIDpgb/pgb/lhY3ov4fluqbor7fmsYJcbiAqIC0g5LiN5Y+v5oGi5aSN55qE6ZSZ6K+v77yIU0RLIOWGhemDqOWPguaVsOagoemqjOmUmeivr+etie+8ieebtOaOpeaKm+WHuuS4jemHjeivlVxuICpcbiAqIEBwYXJhbSBmbiDopoHmiafooYznmoTlvILmraXmk43kvZxcbiAqIEBwYXJhbSBvcHRpb25zIOmHjeivlemFjee9rlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2l0aFJldHJ5PFQ+KGZuOiAoKSA9PiBQcm9taXNlPFQ+LCBvcHRpb25zPzogUmV0cnlPcHRpb25zKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IG9wdHMgPSB7IC4uLkRFRkFVTFRfUkVUUllfT1BUSU9OUywgLi4ub3B0aW9ucyB9O1xuICBsZXQgbGFzdEVycm9yOiBhbnk7XG5cbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IGF0dGVtcHQgPD0gb3B0cy5tYXhSZXRyaWVzOyBhdHRlbXB0KyspIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZm4oKTtcbiAgICAgIGlmIChhdHRlbXB0ID4gMCkge1xuICAgICAgICBsb2dnZXIuaW5mbyhg56ysICR7YXR0ZW1wdCArIDF9IOasoeWwneivleaIkOWKn2ApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBsYXN0RXJyb3IgPSBlcnJvcjtcbiAgICAgIGNvbnN0IGVycm9yTXNnID0gZXJyb3IubWVzc2FnZSB8fCBTdHJpbmcoZXJyb3IpO1xuXG4gICAgICAvKiDmnIDlkI7kuIDmrKHlsJ3or5XlpLHotKXmiJbkuI3lj6/ph43or5XnmoTplJnor68g4oaSIOebtOaOpeaKm+WHuiAqL1xuICAgICAgaWYgKGF0dGVtcHQgPj0gb3B0cy5tYXhSZXRyaWVzIHx8ICFvcHRzLnNob3VsZFJldHJ5KGVycm9yKSkge1xuICAgICAgICBpZiAoYXR0ZW1wdCA+PSBvcHRzLm1heFJldHJpZXMgJiYgb3B0cy5tYXhSZXRyaWVzID4gMCkge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihg6YeN6K+VICR7b3B0cy5tYXhSZXRyaWVzfSDmrKHlkI7ku43lpLHotKU6ICR7ZXJyb3JNc2d9YCk7XG4gICAgICAgIH0gZWxzZSBpZiAoIW9wdHMuc2hvdWxkUmV0cnkoZXJyb3IpKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGDkuI3lj6/ph43or5XnmoTplJnor686ICR7ZXJyb3JNc2d9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG5cbiAgICAgIC8qIOaMh+aVsOmAgOmBv+etieW+hSAqL1xuICAgICAgY29uc3QgZGVsYXkgPSBNYXRoLm1pbihvcHRzLmluaXRpYWxEZWxheSAqIE1hdGgucG93KDIsIGF0dGVtcHQpLCBvcHRzLm1heERlbGF5KTtcbiAgICAgIGxvZ2dlci53YXJuKGDor7fmsYLlpLHotKUgKCR7ZXJyb3JNc2d9Ke+8jCR7ZGVsYXl9bXMg5ZCO56ysICR7YXR0ZW1wdCArIDJ9IOasoemHjeivlS4uLmApO1xuICAgICAgYXdhaXQgc2xlZXAoZGVsYXkpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IGxhc3RFcnJvcjtcbn1cblxuLyoqXG4gKiDluKbotoXml7bmjqfliLbnmoQgZmV0Y2gg5YyF6KOFXG4gKiDlnKjljp/nlJ8gZmV0Y2gg5Z+656GA5LiK5re75Yqg6LaF5pe25Lit5pat6IO95YqbXG4gKlxuICogQHBhcmFtIHVybCDor7fmsYIgVVJMXG4gKiBAcGFyYW0gaW5pdCBmZXRjaCDpgInpoblcbiAqIEBwYXJhbSB0aW1lb3V0TXMg6LaF5pe25pe26Ze077yI5q+r56eS77yJXG4gKi9cbi8qKlxuICog57yT5a2Y55qE5YWo5bGA6YWN572u5b+r54Wn77yM6YG/5YWN5q+P5qyh6K+35rGC6YO96K+75Y+WXG4gKiDku4XlnKggc2V0Q29uZmlnIOiiq+iwg+eUqOaXtuWkseaViO+8iOmAmui/hyBjb25maWdWZXJzaW9uIOavlOWvue+8iVxuICovXG5sZXQgX2NhY2hlZEZldGNoQ29uZmlnOiB7IGZldGNoRm46IHR5cGVvZiBmZXRjaDsgdGltZW91dDogbnVtYmVyOyB2ZXJzaW9uOiBudW1iZXIgfSB8IG51bGwgPSBudWxsO1xuXG4vKipcbiAqIOiOt+WPlue8k+WtmOeahCBmZXRjaCDphY3nva5cbiAqL1xuZnVuY3Rpb24gZ2V0RmV0Y2hDb25maWcoKTogeyBmZXRjaEZuOiB0eXBlb2YgZmV0Y2g7IHRpbWVvdXQ6IG51bWJlciB9IHtcbiAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gIC8qIOeugOWNleeahOW8leeUqOavlOWvueWNs+WPr++8jGdldENvbmZpZyDlnKjmnKrlj5jmm7Tml7bov5Tlm57lkIzkuIDlr7nosaEgKi9cbiAgaWYgKCFfY2FjaGVkRmV0Y2hDb25maWcgfHwgX2NhY2hlZEZldGNoQ29uZmlnLmZldGNoRm4gIT09IChjb25maWcuY3VzdG9tRmV0Y2ggfHwgZmV0Y2gpIHx8IF9jYWNoZWRGZXRjaENvbmZpZy50aW1lb3V0ICE9PSAoY29uZmlnLnRpbWVvdXQgPz8gREVGQVVMVF9SRVRSWV9PUFRJT05TLnRpbWVvdXQpKSB7XG4gICAgX2NhY2hlZEZldGNoQ29uZmlnID0ge1xuICAgICAgZmV0Y2hGbjogY29uZmlnLmN1c3RvbUZldGNoIHx8IGZldGNoLFxuICAgICAgdGltZW91dDogY29uZmlnLnRpbWVvdXQgPz8gREVGQVVMVF9SRVRSWV9PUFRJT05TLnRpbWVvdXQsXG4gICAgICB2ZXJzaW9uOiAwLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIF9jYWNoZWRGZXRjaENvbmZpZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoV2l0aFRpbWVvdXQoXG4gIHVybDogc3RyaW5nLFxuICBpbml0PzogUmVxdWVzdEluaXQsXG4gIHRpbWVvdXRNcz86IG51bWJlcixcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgeyBmZXRjaEZuLCB0aW1lb3V0OiBkZWZhdWx0VGltZW91dCB9ID0gZ2V0RmV0Y2hDb25maWcoKTtcbiAgY29uc3QgZWZmZWN0aXZlVGltZW91dCA9IHRpbWVvdXRNcyA/PyBkZWZhdWx0VGltZW91dDtcbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgY29uc3QgdGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIGVmZmVjdGl2ZVRpbWVvdXQpO1xuXG4gIC8qXG4gICAqIOWmguaenOiwg+eUqOaWueW3suaPkOS+myBzaWduYWzvvIzpnIDopoHlkIzml7bnm5HlkKzkuKTkuKrkv6Hlj7fvvIjosIPnlKjmlrkgKyDotoXml7bvvIlcbiAgICog5Lu75LiA6Kem5Y+R5YiZ5Lit5pat6K+35rGCXG4gICAqL1xuICBjb25zdCBleHRlcm5hbFNpZ25hbCA9IGluaXQ/LnNpZ25hbDtcbiAgaWYgKGV4dGVybmFsU2lnbmFsKSB7XG4gICAgZXh0ZXJuYWxTaWduYWwuYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCAoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIHsgb25jZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaEZuKHVybCwge1xuICAgICAgLi4uaW5pdCxcbiAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgaWYgKGVycm9yLm5hbWUgPT09ICdBYm9ydEVycm9yJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXF1ZXN0IHRpbWVvdXQgYWZ0ZXIgJHtlZmZlY3RpdmVUaW1lb3V0fW1zOiAke3VybH1gKTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH0gZmluYWxseSB7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gIH1cbn1cbiJdfQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tempmail-sdk",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "临时邮箱 SDK - 支持多个临时邮箱服务商",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -264,7 +264,8 @@ async function getEmailsOnce(channel: Channel, email: string, token?: string): P
264
264
  if (!token) throw new Error('internal error: token missing for tempmail-lol');
265
265
  return tempmailLol.getEmails(token, email);
266
266
  case 'chatgpt-org-uk':
267
- return chatgptOrgUk.getEmails(email);
267
+ if (!token) throw new Error('internal error: token missing for chatgpt-org-uk');
268
+ return chatgptOrgUk.getEmails(token, email);
268
269
  case 'tempmail-la':
269
270
  return tempmailLa.getEmails(email);
270
271
  case 'temp-mail-io':
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'awamail';
5
6
  const BASE_URL = 'https://awamail.com/welcome';
@@ -37,7 +38,7 @@ function extractSessionCookie(response: Response): string {
37
38
  * 需要保存响应中的 Set-Cookie (awamail_session) 用于后续获取邮件
38
39
  */
39
40
  export async function generateEmail(): Promise<InternalEmailInfo> {
40
- const response = await fetch(`${BASE_URL}/change_mailbox`, {
41
+ const response = await fetchWithTimeout(`${BASE_URL}/change_mailbox`, {
41
42
  method: 'POST',
42
43
  headers: {
43
44
  ...DEFAULT_HEADERS,
@@ -77,7 +78,7 @@ export async function generateEmail(): Promise<InternalEmailInfo> {
77
78
  * 返回: { success, data: { emails: [...], latest: {...} } }
78
79
  */
79
80
  export async function getEmails(token: string, email: string): Promise<Email[]> {
80
- const response = await fetch(`${BASE_URL}/get_emails`, {
81
+ const response = await fetchWithTimeout(`${BASE_URL}/get_emails`, {
81
82
  method: 'GET',
82
83
  headers: {
83
84
  ...DEFAULT_HEADERS,
@@ -1,47 +1,104 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'chatgpt-org-uk';
5
6
  const BASE_URL = 'https://mail.chatgpt.org.uk/api';
7
+ const HOME_URL = 'https://mail.chatgpt.org.uk/';
6
8
 
7
9
  const DEFAULT_HEADERS = {
8
10
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36',
9
- 'Content-Type': 'application/json',
10
11
  'Accept': '*/*',
11
12
  'Referer': 'https://mail.chatgpt.org.uk/',
12
- 'sec-ch-ua': '"Microsoft Edge";v="143", "Chromium";v="143", "Not A(Brand";v="24"',
13
- 'sec-ch-ua-mobile': '?0',
14
- 'sec-ch-ua-platform': '"Windows"',
13
+ 'Origin': 'https://mail.chatgpt.org.uk',
15
14
  'DNT': '1',
16
15
  };
17
16
 
18
- export async function generateEmail(): Promise<InternalEmailInfo> {
19
- const response = await fetch(`${BASE_URL}/generate-email`, {
17
+ function extractGmSid(response: Response): string {
18
+ const setCookie = response.headers.get('set-cookie') || '';
19
+ const match = setCookie.match(/gm_sid=([^;]+)/);
20
+ return match ? match[1] : '';
21
+ }
22
+
23
+ async function fetchGmSid(): Promise<string> {
24
+ const response = await fetchWithTimeout(HOME_URL, {
20
25
  method: 'GET',
21
26
  headers: DEFAULT_HEADERS,
22
27
  });
23
28
 
24
29
  if (!response.ok) {
25
- throw new Error(`Failed to generate email: ${response.status}`);
30
+ throw new Error(`Failed to fetch gm_sid: ${response.status}`);
31
+ }
32
+
33
+ const gmSid = extractGmSid(response);
34
+ if (!gmSid) {
35
+ throw new Error('Failed to extract gm_sid cookie');
36
+ }
37
+
38
+ return gmSid;
39
+ }
40
+
41
+ async function fetchGmSidWithRetry(): Promise<string> {
42
+ try {
43
+ return await fetchGmSid();
44
+ } catch (error: any) {
45
+ const message = String(error?.message || error || '').toLowerCase();
46
+ if (message.includes('401') || message.includes('extract gm_sid')) {
47
+ return await fetchGmSid();
48
+ }
49
+ throw error;
50
+ }
51
+ }
52
+
53
+ async function fetchInboxToken(email: string, gmSid: string): Promise<string> {
54
+ const response = await fetchWithTimeout(`${BASE_URL}/inbox-token`, {
55
+ method: 'POST',
56
+ headers: {
57
+ ...DEFAULT_HEADERS,
58
+ 'Content-Type': 'application/json',
59
+ 'Cookie': `gm_sid=${gmSid}`,
60
+ },
61
+ body: JSON.stringify({ email }),
62
+ });
63
+
64
+ if (!response.ok) {
65
+ throw new Error(`Failed to get inbox token: ${response.status}`);
26
66
  }
27
67
 
28
68
  const data = await response.json();
29
-
30
- if (!data.success) {
31
- throw new Error('Failed to generate email');
69
+ const token = data?.auth?.token;
70
+ if (!token) {
71
+ throw new Error('Failed to get inbox token');
32
72
  }
33
73
 
34
- return {
35
- channel: CHANNEL,
36
- email: data.data.email,
37
- };
74
+ return token;
38
75
  }
39
76
 
40
- export async function getEmails(email: string): Promise<Email[]> {
77
+ async function fetchInboxTokenWithRetry(email: string): Promise<string> {
78
+ const gmSid = await fetchGmSidWithRetry();
79
+ try {
80
+ return await fetchInboxToken(email, gmSid);
81
+ } catch (error: any) {
82
+ const message = String(error?.message || error || '').toLowerCase();
83
+ if (message.includes('401')) {
84
+ const refreshedGmSid = await fetchGmSidWithRetry();
85
+ return await fetchInboxToken(email, refreshedGmSid);
86
+ }
87
+ throw error;
88
+ }
89
+ }
90
+
91
+ async function fetchEmails(token: string, email: string): Promise<Email[]> {
92
+ if (!token) {
93
+ throw new Error('internal error: token missing for chatgpt-org-uk');
94
+ }
41
95
  const encodedEmail = encodeURIComponent(email);
42
- const response = await fetch(`${BASE_URL}/emails?email=${encodedEmail}`, {
96
+ const response = await fetchWithTimeout(`${BASE_URL}/emails?email=${encodedEmail}`, {
43
97
  method: 'GET',
44
- headers: DEFAULT_HEADERS,
98
+ headers: {
99
+ ...DEFAULT_HEADERS,
100
+ 'x-inbox-token': token,
101
+ },
45
102
  });
46
103
 
47
104
  if (!response.ok) {
@@ -49,7 +106,7 @@ export async function getEmails(email: string): Promise<Email[]> {
49
106
  }
50
107
 
51
108
  const data = await response.json();
52
-
109
+
53
110
  if (!data.success) {
54
111
  throw new Error('Failed to get emails');
55
112
  }
@@ -57,3 +114,59 @@ export async function getEmails(email: string): Promise<Email[]> {
57
114
  const rawEmails = data.data?.emails || [];
58
115
  return rawEmails.map((raw: any) => normalizeEmail(raw, email));
59
116
  }
117
+
118
+ async function fetchEmailsWithRetry(email: string): Promise<Email[]> {
119
+ const token = await fetchInboxTokenWithRetry(email);
120
+ try {
121
+ return await fetchEmails(token, email);
122
+ } catch (error: any) {
123
+ const message = String(error?.message || error || '').toLowerCase();
124
+ if (message.includes('401')) {
125
+ const refreshedToken = await fetchInboxTokenWithRetry(email);
126
+ return await fetchEmails(refreshedToken, email);
127
+ }
128
+ throw error;
129
+ }
130
+ }
131
+
132
+ export async function generateEmail(): Promise<InternalEmailInfo> {
133
+ const response = await fetchWithTimeout(`${BASE_URL}/generate-email`, {
134
+ method: 'GET',
135
+ headers: DEFAULT_HEADERS,
136
+ });
137
+
138
+ if (!response.ok) {
139
+ throw new Error(`Failed to generate email: ${response.status}`);
140
+ }
141
+
142
+ const data = await response.json();
143
+
144
+ if (!data.success) {
145
+ throw new Error('Failed to generate email');
146
+ }
147
+
148
+ const email = data.data.email;
149
+ const token = await fetchInboxTokenWithRetry(email);
150
+
151
+ return {
152
+ channel: CHANNEL,
153
+ email,
154
+ token,
155
+ };
156
+ }
157
+
158
+ export async function getEmails(token: string, email: string): Promise<Email[]> {
159
+ if (!token) {
160
+ throw new Error('internal error: token missing for chatgpt-org-uk');
161
+ }
162
+
163
+ try {
164
+ return await fetchEmails(token, email);
165
+ } catch (error: any) {
166
+ const message = String(error?.message || error || '').toLowerCase();
167
+ if (message.includes('401')) {
168
+ return await fetchEmailsWithRetry(email);
169
+ }
170
+ throw error;
171
+ }
172
+ }
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'dropmail';
5
6
  const BASE_URL = 'https://dropmail.me/api/graphql/MY_TOKEN';
@@ -29,7 +30,7 @@ async function graphqlRequest(query: string, variables?: Record<string, any>): P
29
30
  params.set('variables', JSON.stringify(variables));
30
31
  }
31
32
 
32
- const response = await fetch(BASE_URL, {
33
+ const response = await fetchWithTimeout(BASE_URL, {
33
34
  method: 'POST',
34
35
  headers: DEFAULT_HEADERS,
35
36
  body: params.toString(),
@@ -10,6 +10,7 @@
10
10
 
11
11
  import { InternalEmailInfo, Email, Channel } from '../types';
12
12
  import { normalizeEmail } from '../normalize';
13
+ import { fetchWithTimeout } from '../retry';
13
14
 
14
15
  const CHANNEL: Channel = 'guerrillamail';
15
16
  const BASE_URL = 'https://api.guerrillamail.com/ajax.php';
@@ -20,7 +21,7 @@ const BASE_URL = 'https://api.guerrillamail.com/ajax.php';
20
21
  * 返回 email_addr + sid_token(用于后续获取邮件)
21
22
  */
22
23
  export async function generateEmail(): Promise<InternalEmailInfo> {
23
- const response = await fetch(`${BASE_URL}?f=get_email_address&lang=en`, {
24
+ const response = await fetchWithTimeout(`${BASE_URL}?f=get_email_address&lang=en`, {
24
25
  method: 'GET',
25
26
  headers: {
26
27
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
@@ -51,7 +52,7 @@ export async function generateEmail(): Promise<InternalEmailInfo> {
51
52
  * 返回 list 数组,每个元素包含 mail_id, mail_from, mail_subject, mail_body 等
52
53
  */
53
54
  export async function getEmails(token: string, email: string): Promise<Email[]> {
54
- const response = await fetch(`${BASE_URL}?f=check_email&seq=0&sid_token=${encodeURIComponent(token)}`, {
55
+ const response = await fetchWithTimeout(`${BASE_URL}?f=check_email&seq=0&sid_token=${encodeURIComponent(token)}`, {
55
56
  method: 'GET',
56
57
  headers: {
57
58
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'linshi-email';
5
6
  const BASE_URL = 'https://www.linshi-email.com/api/v1';
@@ -17,7 +18,7 @@ const DEFAULT_HEADERS = {
17
18
  };
18
19
 
19
20
  export async function generateEmail(): Promise<InternalEmailInfo> {
20
- const response = await fetch(`${BASE_URL}/email/${API_KEY}`, {
21
+ const response = await fetchWithTimeout(`${BASE_URL}/email/${API_KEY}`, {
21
22
  method: 'POST',
22
23
  headers: DEFAULT_HEADERS,
23
24
  body: JSON.stringify({}),
@@ -43,7 +44,7 @@ export async function generateEmail(): Promise<InternalEmailInfo> {
43
44
  export async function getEmails(email: string): Promise<Email[]> {
44
45
  const encodedEmail = encodeURIComponent(email);
45
46
  const timestamp = Date.now();
46
- const response = await fetch(`${BASE_URL}/refreshmessage/${API_KEY}/${encodedEmail}?t=${timestamp}`, {
47
+ const response = await fetchWithTimeout(`${BASE_URL}/refreshmessage/${API_KEY}/${encodedEmail}?t=${timestamp}`, {
47
48
  method: 'GET',
48
49
  headers: DEFAULT_HEADERS,
49
50
  });
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'mail-tm';
5
6
  const BASE_URL = 'https://api.mail.tm';
@@ -26,7 +27,7 @@ function randomString(length: number): string {
26
27
  * API: GET /domains
27
28
  */
28
29
  async function getDomains(): Promise<string[]> {
29
- const response = await fetch(`${BASE_URL}/domains`, {
30
+ const response = await fetchWithTimeout(`${BASE_URL}/domains`, {
30
31
  method: 'GET',
31
32
  headers: DEFAULT_HEADERS,
32
33
  });
@@ -51,7 +52,7 @@ async function getDomains(): Promise<string[]> {
51
52
  * API: POST /accounts
52
53
  */
53
54
  async function createAccount(address: string, password: string): Promise<any> {
54
- const response = await fetch(`${BASE_URL}/accounts`, {
55
+ const response = await fetchWithTimeout(`${BASE_URL}/accounts`, {
55
56
  method: 'POST',
56
57
  headers: { ...DEFAULT_HEADERS, 'Content-Type': 'application/ld+json' },
57
58
  body: JSON.stringify({ address, password }),
@@ -70,7 +71,7 @@ async function createAccount(address: string, password: string): Promise<any> {
70
71
  * API: POST /token
71
72
  */
72
73
  async function getToken(address: string, password: string): Promise<string> {
73
- const response = await fetch(`${BASE_URL}/token`, {
74
+ const response = await fetchWithTimeout(`${BASE_URL}/token`, {
74
75
  method: 'POST',
75
76
  headers: DEFAULT_HEADERS,
76
77
  body: JSON.stringify({ address, password }),
@@ -144,7 +145,7 @@ function flattenMessage(msg: any, recipientEmail: string): any {
144
145
  */
145
146
  export async function getEmails(token: string, email: string): Promise<Email[]> {
146
147
  // 1. 获取邮件列表
147
- const listResponse = await fetch(`${BASE_URL}/messages`, {
148
+ const listResponse = await fetchWithTimeout(`${BASE_URL}/messages`, {
148
149
  method: 'GET',
149
150
  headers: {
150
151
  ...DEFAULT_HEADERS,
@@ -167,7 +168,7 @@ export async function getEmails(token: string, email: string): Promise<Email[]>
167
168
  // 2. 并行获取每封邮件的详情(含 text/html/attachments)
168
169
  const detailPromises = messages.map(async (msg: any) => {
169
170
  try {
170
- const detailResponse = await fetch(`${BASE_URL}/messages/${msg.id}`, {
171
+ const detailResponse = await fetchWithTimeout(`${BASE_URL}/messages/${msg.id}`, {
171
172
  method: 'GET',
172
173
  headers: {
173
174
  ...DEFAULT_HEADERS,
@@ -10,6 +10,7 @@
10
10
  */
11
11
 
12
12
  import { InternalEmailInfo, Email, Channel } from '../types';
13
+ import { fetchWithTimeout } from '../retry';
13
14
 
14
15
  const CHANNEL: Channel = 'maildrop';
15
16
  const GRAPHQL_URL = 'https://api.maildrop.cc/graphql';
@@ -113,7 +114,7 @@ async function graphqlRequest(
113
114
  query: string,
114
115
  variables: Record<string, string> = {},
115
116
  ): Promise<any> {
116
- const response = await fetch(GRAPHQL_URL, {
117
+ const response = await fetchWithTimeout(GRAPHQL_URL, {
117
118
  method: 'POST',
118
119
  headers: {
119
120
  'Content-Type': 'application/json',
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'temp-mail-io';
5
6
  const BASE_URL = 'https://api.internal.temp-mail.io/api/v3';
@@ -18,7 +19,7 @@ async function fetchCorsHeader(): Promise<string> {
18
19
  if (cachedCorsHeader) return cachedCorsHeader;
19
20
 
20
21
  try {
21
- const response = await fetch(PAGE_URL, {
22
+ const response = await fetchWithTimeout(PAGE_URL, {
22
23
  headers: {
23
24
  '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
  },
@@ -61,7 +62,7 @@ async function getApiHeaders(): Promise<Record<string, string>> {
61
62
  */
62
63
  export async function generateEmail(): Promise<InternalEmailInfo> {
63
64
  const headers = await getApiHeaders();
64
- const response = await fetch(`${BASE_URL}/email/new`, {
65
+ const response = await fetchWithTimeout(`${BASE_URL}/email/new`, {
65
66
  method: 'POST',
66
67
  headers,
67
68
  body: JSON.stringify({ min_name_length: 10, max_name_length: 10 }),
@@ -91,7 +92,7 @@ export async function generateEmail(): Promise<InternalEmailInfo> {
91
92
  */
92
93
  export async function getEmails(email: string): Promise<Email[]> {
93
94
  const headers = await getApiHeaders();
94
- const response = await fetch(`${BASE_URL}/email/${email}/messages`, {
95
+ const response = await fetchWithTimeout(`${BASE_URL}/email/${email}/messages`, {
95
96
  method: 'GET',
96
97
  headers,
97
98
  });
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'tempmail-la';
5
6
  const BASE_URL = 'https://tempmail.la/api';
@@ -31,7 +32,7 @@ const DEFAULT_HEADERS: Record<string, string> = {
31
32
  * 返回: { code: 0, data: { mailId, address, type, startAt, endAt } }
32
33
  */
33
34
  export async function generateEmail(): Promise<InternalEmailInfo> {
34
- const response = await fetch(`${BASE_URL}/mail/create`, {
35
+ const response = await fetchWithTimeout(`${BASE_URL}/mail/create`, {
35
36
  method: 'POST',
36
37
  headers: DEFAULT_HEADERS,
37
38
  body: JSON.stringify({ turnstile: '' }),
@@ -69,7 +70,7 @@ export async function getEmails(email: string): Promise<Email[]> {
69
70
 
70
71
  // 支持分页,循环获取所有邮件
71
72
  while (hasMore) {
72
- const response: Response = await fetch(`${BASE_URL}/mail/box`, {
73
+ const response: Response = await fetchWithTimeout(`${BASE_URL}/mail/box`, {
73
74
  method: 'POST',
74
75
  headers: DEFAULT_HEADERS,
75
76
  body: JSON.stringify({ address: email, cursor }),
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'tempmail-lol';
5
6
  const BASE_URL = 'https://api.tempmail.lol/v2';
@@ -15,7 +16,7 @@ const DEFAULT_HEADERS = {
15
16
  };
16
17
 
17
18
  export async function generateEmail(domain: string | null = null): Promise<InternalEmailInfo> {
18
- const response = await fetch(`${BASE_URL}/inbox/create`, {
19
+ const response = await fetchWithTimeout(`${BASE_URL}/inbox/create`, {
19
20
  method: 'POST',
20
21
  headers: DEFAULT_HEADERS,
21
22
  body: JSON.stringify({ domain, captcha: null }),
@@ -39,7 +40,7 @@ export async function generateEmail(domain: string | null = null): Promise<Inter
39
40
  }
40
41
 
41
42
  export async function getEmails(token: string, recipientEmail: string = ''): Promise<Email[]> {
42
- const response = await fetch(`${BASE_URL}/inbox?token=${encodeURIComponent(token)}`, {
43
+ const response = await fetchWithTimeout(`${BASE_URL}/inbox?token=${encodeURIComponent(token)}`, {
43
44
  method: 'GET',
44
45
  headers: DEFAULT_HEADERS,
45
46
  });
@@ -1,5 +1,6 @@
1
1
  import { InternalEmailInfo, Email, Channel } from '../types';
2
2
  import { normalizeEmail } from '../normalize';
3
+ import { fetchWithTimeout } from '../retry';
3
4
 
4
5
  const CHANNEL: Channel = 'tempmail';
5
6
  const BASE_URL = 'https://api.tempmail.ing/api';
@@ -15,7 +16,7 @@ const DEFAULT_HEADERS = {
15
16
  };
16
17
 
17
18
  export async function generateEmail(duration: number = 30): Promise<InternalEmailInfo> {
18
- const response = await fetch(`${BASE_URL}/generate`, {
19
+ const response = await fetchWithTimeout(`${BASE_URL}/generate`, {
19
20
  method: 'POST',
20
21
  headers: DEFAULT_HEADERS,
21
22
  body: JSON.stringify({ duration }),
@@ -41,7 +42,7 @@ export async function generateEmail(duration: number = 30): Promise<InternalEmai
41
42
 
42
43
  export async function getEmails(email: string): Promise<Email[]> {
43
44
  const encodedEmail = encodeURIComponent(email);
44
- const response = await fetch(`${BASE_URL}/emails/${encodedEmail}`, {
45
+ const response = await fetchWithTimeout(`${BASE_URL}/emails/${encodedEmail}`, {
45
46
  method: 'GET',
46
47
  headers: DEFAULT_HEADERS,
47
48
  });