tempmail_sdk 1.3.3 → 1.3.5
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/tempmail_sdk/channels.rb +29 -7
- data/lib/tempmail_sdk/channels_data.rb +29 -7
- data/lib/tempmail_sdk/providers/altmails.rb +99 -0
- data/lib/tempmail_sdk/providers/apihz.rb +138 -0
- data/lib/tempmail_sdk/providers/awamail.rb +95 -0
- data/lib/tempmail_sdk/providers/best_temp_mail.rb +77 -0
- data/lib/tempmail_sdk/providers/chatgpt_org_uk.rb +129 -0
- data/lib/tempmail_sdk/providers/clawdemail.rb +122 -0
- data/lib/tempmail_sdk/providers/crazymailing.rb +114 -0
- data/lib/tempmail_sdk/providers/disposablemail.rb +125 -0
- data/lib/tempmail_sdk/providers/disposablemail_app.rb +66 -0
- data/lib/tempmail_sdk/providers/email10min.rb +152 -0
- data/lib/tempmail_sdk/providers/emailnator.rb +132 -0
- data/lib/tempmail_sdk/providers/emailtemp_org.rb +131 -0
- data/lib/tempmail_sdk/providers/expressinboxhub.rb +118 -0
- data/lib/tempmail_sdk/providers/fakemail.rb +143 -0
- data/lib/tempmail_sdk/providers/firetempmail.rb +86 -0
- data/lib/tempmail_sdk/providers/flybymail.rb +93 -0
- data/lib/tempmail_sdk/providers/generator_email.rb +146 -0
- data/lib/tempmail_sdk/providers/haribu.rb +29 -3
- data/lib/tempmail_sdk/providers/huskmail.rb +132 -0
- data/lib/tempmail_sdk/providers/internxt.rb +176 -0
- data/lib/tempmail_sdk/providers/linshi_xyz.rb +79 -0
- data/lib/tempmail_sdk/providers/linshiyouxiang_net.rb +85 -0
- data/lib/tempmail_sdk/providers/mail_sunls.rb +42 -1
- data/lib/tempmail_sdk/providers/mail_td.rb +161 -0
- data/lib/tempmail_sdk/providers/mailcat_ai.rb +52 -0
- data/lib/tempmail_sdk/providers/maildrop.rb +79 -4
- data/lib/tempmail_sdk/providers/mailgolem.rb +96 -0
- data/lib/tempmail_sdk/providers/mailinator.rb +9 -2
- data/lib/tempmail_sdk/providers/mailmomy.rb +1 -1
- data/lib/tempmail_sdk/providers/mailtemp_cc.rb +91 -0
- data/lib/tempmail_sdk/providers/mailticking.rb +139 -0
- data/lib/tempmail_sdk/providers/minuteinbox.rb +174 -0
- data/lib/tempmail_sdk/providers/moakt.rb +29 -3
- data/lib/tempmail_sdk/providers/mtempmail.rb +140 -0
- data/lib/tempmail_sdk/providers/mytempmail_cc.rb +76 -0
- data/lib/tempmail_sdk/providers/nowtempmail.rb +112 -0
- data/lib/tempmail_sdk/providers/noxen_de5_net.rb +392 -0
- data/lib/tempmail_sdk/providers/nukemail.rb +188 -0
- data/lib/tempmail_sdk/providers/nullmail.rb +95 -0
- data/lib/tempmail_sdk/providers/openinbox.rb +102 -0
- data/lib/tempmail_sdk/providers/shadowmail.rb +174 -0
- data/lib/tempmail_sdk/providers/shitpost_email.rb +85 -0
- data/lib/tempmail_sdk/providers/smail_pw.rb +156 -0
- data/lib/tempmail_sdk/providers/smails.rb +128 -0
- data/lib/tempmail_sdk/providers/socketio_mail.rb +25 -0
- data/lib/tempmail_sdk/providers/temp_mail_gg.rb +362 -0
- data/lib/tempmail_sdk/providers/tempgbox.rb +118 -0
- data/lib/tempmail_sdk/providers/tempmail100.rb +148 -0
- data/lib/tempmail_sdk/providers/tempmail_cn.rb +111 -0
- data/lib/tempmail_sdk/providers/tempmail_ee.rb +373 -0
- data/lib/tempmail_sdk/providers/tempmailportal.rb +131 -0
- data/lib/tempmail_sdk/providers/tempmails_io.rb +89 -0
- data/lib/tempmail_sdk/providers/tempmailto.rb +312 -0
- data/lib/tempmail_sdk/providers/temporarymail_com.rb +184 -0
- data/lib/tempmail_sdk/providers/tenmin_app.rb +100 -0
- data/lib/tempmail_sdk/providers/tenminutemail_net.rb +183 -0
- data/lib/tempmail_sdk/providers/thirty_min_email.rb +90 -0
- data/lib/tempmail_sdk/providers/tmpkit.rb +129 -0
- data/lib/tempmail_sdk/providers/twentyfourmail_chacuo.rb +83 -0
- data/lib/tempmail_sdk/providers/vip_215.rb +171 -0
- data/lib/tempmail_sdk/providers/zerodrop.rb +90 -0
- data/lib/tempmail_sdk/registry.rb +285 -23
- data/lib/tempmail_sdk/types.rb +13 -0
- data/lib/tempmail_sdk/version.rb +1 -1
- data/lib/tempmail_sdk.rb +1 -1
- metadata +58 -6
- data/lib/tempmail_sdk/providers/gonebox_email.rb +0 -89
- data/lib/tempmail_sdk/providers/temp_mail_now.rb +0 -103
- data/lib/tempmail_sdk/providers/webmailtemp.rb +0 -108
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 94b1283ca19ff9597330edb468dfa560e673fe8176921d74834e348ade013dc1
|
|
4
|
+
data.tar.gz: 1e9e82a350c0d42cba190079c117ed520ee4d48c2a28a0b2765e8746696856cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b1d8285e29796a127ae34c83fd014df2fcf7a06efccc6739bac2a567cbf9eb9d15b87861ec488a61c432be578b5426643c6ded3ff6c2bfeccf2a9a7a7045709
|
|
7
|
+
data.tar.gz: d1c0b4969332cecc27ed714ebfa1adaef8715eb0c53fddc836c0b1c87a299b4f202081e180490500196f4f59ff165633ef46f09357d9f21d9fc12208e1c8417b
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
4
4
|
|
|
5
|
-
Ruby 语言临时邮箱 SDK,公开 **
|
|
5
|
+
Ruby 语言临时邮箱 SDK,公开 **296** 个 `channel` 渠道标识,聚合 100+ 个第三方临时邮箱服务商,所有渠道返回**统一标准化格式**。渠道标识与顺序与 Go / npm / Rust / Python / C 等其余各端保持一致(十端同步);随机生成邮箱时在本端独立打乱尝试顺序。
|
|
6
6
|
|
|
7
7
|
## 安装
|
|
8
8
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
#
|
|
3
|
-
# 渠道标识常量模块(
|
|
3
|
+
# 渠道标识常量模块(296 个),常量值即渠道 slug。
|
|
4
4
|
# 由 .channel_meta.json 生成,供用户以常量方式引用渠道,避免手写字符串出错。
|
|
5
5
|
#
|
|
6
6
|
module TempmailSdk
|
|
@@ -31,6 +31,7 @@ module TempmailSdk
|
|
|
31
31
|
MAILFORSPAM_DISPOSABLE = "mailforspam-disposable"
|
|
32
32
|
TEMPMAILC = "tempmailc"
|
|
33
33
|
MAILNESIA = "mailnesia"
|
|
34
|
+
MAILTICKING = "mailticking"
|
|
34
35
|
THROWAWAYMAIL = "throwawaymail"
|
|
35
36
|
TEMPMAIL_FISH = "tempmail-fish"
|
|
36
37
|
NEIGHBOURS_SH = "neighbours-sh"
|
|
@@ -80,7 +81,6 @@ module TempmailSdk
|
|
|
80
81
|
VILLATOGEL_COM = "villatogel-com"
|
|
81
82
|
MAIL123 = "mail123"
|
|
82
83
|
MAIL10S = "mail10s"
|
|
83
|
-
WEBMAILTEMP = "webmailtemp"
|
|
84
84
|
TEMPFASTMAIL = "tempfastmail"
|
|
85
85
|
C_1SEC_MAIL = "1sec-mail"
|
|
86
86
|
FAKEMAIL = "fakemail"
|
|
@@ -162,7 +162,6 @@ module TempmailSdk
|
|
|
162
162
|
HARIBU = "haribu"
|
|
163
163
|
ROOTSH = "rootsh"
|
|
164
164
|
FAKE_EMAIL_SITE = "fake-email-site"
|
|
165
|
-
MOHMAL = "mohmal"
|
|
166
165
|
MAILGOLEM = "mailgolem"
|
|
167
166
|
BEST_TEMP_MAIL = "best-temp-mail"
|
|
168
167
|
DISPOSABLEMAIL_APP = "disposablemail-app"
|
|
@@ -183,14 +182,12 @@ module TempmailSdk
|
|
|
183
182
|
TEMPP_MAILS = "tempp-mails"
|
|
184
183
|
EMAILTEMP_ORG = "emailtemp-org"
|
|
185
184
|
MYTEMPMAIL_CC = "mytempmail-cc"
|
|
186
|
-
TEMP_MAIL_NOW = "temp-mail-now"
|
|
187
185
|
MAIL_TD = "mail-td"
|
|
188
186
|
MAILHOLE_DE = "mailhole-de"
|
|
189
187
|
TMAIL_LINK = "tmail-link"
|
|
190
188
|
C_24MAIL_CHACUO = "24mail-chacuo"
|
|
191
189
|
NIMAIL = "nimail"
|
|
192
190
|
FREECUSTOM = "freecustom"
|
|
193
|
-
C_16888888_CYOU = "16888888-cyou"
|
|
194
191
|
C_17666688_SHOP = "17666688-shop"
|
|
195
192
|
C_282MAIL_COM = "282mail-com"
|
|
196
193
|
BLACKHOLE_DJURBY_SE = "blackhole-djurby-se"
|
|
@@ -205,7 +202,6 @@ module TempmailSdk
|
|
|
205
202
|
EASYME_PRO = "easyme-pro"
|
|
206
203
|
EBS_COM_AR = "ebs-com-ar"
|
|
207
204
|
ETGDEV_DE = "etgdev-de"
|
|
208
|
-
EVERGREENCO_SHOP = "evergreenco-shop"
|
|
209
205
|
FWD2M_ESZETT_ES = "fwd2m-eszett-es"
|
|
210
206
|
JAMA_TRENET_EU = "jama-trenet-eu"
|
|
211
207
|
J_FAIRUSE_ORG = "j-fairuse-org"
|
|
@@ -279,11 +275,37 @@ module TempmailSdk
|
|
|
279
275
|
TEMPGMAILER = "tempgmailer"
|
|
280
276
|
TEMP_MAIL_ORG = "temp-mail-org"
|
|
281
277
|
XKX_ME = "xkx-me"
|
|
282
|
-
GONEBOX_EMAIL = "gonebox-email"
|
|
283
278
|
MAILCAT_AI = "mailcat-ai"
|
|
284
279
|
TEMPGO_EMAIL = "tempgo-email"
|
|
285
280
|
RESTMAIL_NET = "restmail-net"
|
|
286
281
|
DROPMAIL_ME = "dropmail-me"
|
|
287
282
|
TEN_MINUTE_MAIL_NET = "ten-minute-mail-net"
|
|
283
|
+
TEMPMAILS_IO = "tempmails-io"
|
|
284
|
+
SHITPOST_EMAIL = "shitpost-email"
|
|
285
|
+
SMAILS = "smails"
|
|
286
|
+
TEMPMAILPORTAL = "tempmailportal"
|
|
287
|
+
HUSKMAIL = "huskmail"
|
|
288
|
+
ZERODROP = "zerodrop"
|
|
289
|
+
FIRETEMPMAIL = "firetempmail"
|
|
290
|
+
NULLMAIL = "nullmail"
|
|
291
|
+
TENMIN_APP = "tenmin-app"
|
|
292
|
+
MTEMPMAIL = "mtempmail"
|
|
293
|
+
TEMPMAIL_EE = "tempmail-ee"
|
|
294
|
+
TEMPORARYMAIL_COM = "temporarymail-com"
|
|
295
|
+
C_30MINEMAIL = "30minemail"
|
|
296
|
+
LINSHI_XYZ = "linshi-xyz"
|
|
297
|
+
CRAZYMAILING = "crazymailing"
|
|
298
|
+
NOXEN_DE5_NET = "noxen-de5-net"
|
|
299
|
+
NUKEMAIL = "nukemail"
|
|
300
|
+
SHADOWMAIL = "shadowmail"
|
|
301
|
+
FLYBYMAIL = "flybymail"
|
|
302
|
+
NOWTEMPMAIL = "nowtempmail"
|
|
303
|
+
CLAWDEMAIL = "clawdemail"
|
|
304
|
+
TEMPMAIL100 = "tempmail100"
|
|
305
|
+
TEMPMAILTO = "tempmailto"
|
|
306
|
+
TEMP_MAIL_GG = "temp-mail-gg"
|
|
307
|
+
TMPKIT = "tmpkit"
|
|
308
|
+
INTERNXT = "internxt"
|
|
309
|
+
GENERATOR_EMAIL = "generator-email"
|
|
288
310
|
end
|
|
289
311
|
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# 每项为 [slug, name, website],注册表按此顺序枚举,顺序为硬约束。
|
|
5
5
|
#
|
|
6
6
|
module TempmailSdk
|
|
7
|
-
#
|
|
7
|
+
# 296 个渠道的有序元数据
|
|
8
8
|
CHANNEL_DATA = [
|
|
9
9
|
["tempmail", "TempMail", "tempmail.ing"],
|
|
10
10
|
["tempmail-cn", "TempMail CN", "tempmail.cn"],
|
|
@@ -31,6 +31,7 @@ module TempmailSdk
|
|
|
31
31
|
["mailforspam-disposable", "MailForSpam Disposable", "disposable.email"],
|
|
32
32
|
["tempmailc", "TempMailC", "tempmailc.com"],
|
|
33
33
|
["mailnesia", "Mailnesia", "mailnesia.com"],
|
|
34
|
+
["mailticking", "MailTicking", "mailticking.com"],
|
|
34
35
|
["throwawaymail", "ThrowawayMail", "throwawaymail.app"],
|
|
35
36
|
["tempmail-fish", "TempMail Fish", "tempmail.fish"],
|
|
36
37
|
["neighbours-sh", "Neighbours", "neighbours.sh"],
|
|
@@ -80,7 +81,6 @@ module TempmailSdk
|
|
|
80
81
|
["villatogel-com", "villatogel.com", "getnada.net"],
|
|
81
82
|
["mail123", "Mail123", "mail123.fr"],
|
|
82
83
|
["mail10s", "Mail10s", "mail10s.com"],
|
|
83
|
-
["webmailtemp", "WebMailTemp", "webmailtemp.com"],
|
|
84
84
|
["tempfastmail", "TempFastMail", "tempfastmail.com"],
|
|
85
85
|
["1sec-mail", "1SecMail", "1sec-mail.com"],
|
|
86
86
|
["fakemail", "FakeMail", "fakemail.net"],
|
|
@@ -162,7 +162,6 @@ module TempmailSdk
|
|
|
162
162
|
["haribu", "Haribu", "haribu.net"],
|
|
163
163
|
["rootsh", "Rootsh(BccTo)", "rootsh.com"],
|
|
164
164
|
["fake-email-site", "FakeEmailSite", "fake-email.site"],
|
|
165
|
-
["mohmal", "Mohmal", "mohmal.com"],
|
|
166
165
|
["mailgolem", "MailGolem", "mailgolem.com"],
|
|
167
166
|
["best-temp-mail", "BestTempMail", "best-temp-mail.com"],
|
|
168
167
|
["disposablemail-app", "DisposableMail", "disposablemail.app"],
|
|
@@ -183,14 +182,12 @@ module TempmailSdk
|
|
|
183
182
|
["tempp-mails", "TemppMails", "tempp-mails.com"],
|
|
184
183
|
["emailtemp-org", "EmailTemp", "emailtemp.org"],
|
|
185
184
|
["mytempmail-cc", "MyTempMail.cc", "mytempmail.cc"],
|
|
186
|
-
["temp-mail-now", "TempMailNow", "temp-mail.now"],
|
|
187
185
|
["mail-td", "Mail.td", "mail.td"],
|
|
188
186
|
["mailhole-de", "Mailhole.de", "mailhole.de"],
|
|
189
187
|
["tmail-link", "TMail.link", "tmail.link"],
|
|
190
188
|
["24mail-chacuo", "24Mail Chacuo", "24mail.chacuo.net"],
|
|
191
189
|
["nimail", "NiMail", "nimail.cn"],
|
|
192
190
|
["freecustom", "FreeCustom.Email", "freecustom.email"],
|
|
193
|
-
["16888888-cyou", "Mailmomy (16888888.cyou)", "mailmomy.com"],
|
|
194
191
|
["17666688-shop", "Mailmomy (17666688.shop)", "mailmomy.com"],
|
|
195
192
|
["282mail-com", "Mailmomy (282mail.com)", "mailmomy.com"],
|
|
196
193
|
["blackhole-djurby-se", "Mailinator (blackhole.djurby.se)", "mailinator.com"],
|
|
@@ -205,7 +202,6 @@ module TempmailSdk
|
|
|
205
202
|
["easyme-pro", "Mailmomy (easyme.pro)", "mailmomy.com"],
|
|
206
203
|
["ebs-com-ar", "Mailinator (ebs.com.ar)", "mailinator.com"],
|
|
207
204
|
["etgdev-de", "Mailinator (etgdev.de)", "mailinator.com"],
|
|
208
|
-
["evergreenco-shop", "Mailmomy (evergreenco.shop)", "mailmomy.com"],
|
|
209
205
|
["fwd2m-eszett-es", "Mailinator (fwd2m.eszett.es)", "mailinator.com"],
|
|
210
206
|
["jama-trenet-eu", "Mailinator (jama.trenet.eu)", "mailinator.com"],
|
|
211
207
|
["j-fairuse-org", "Mailinator (j.fairuse.org)", "mailinator.com"],
|
|
@@ -279,11 +275,37 @@ module TempmailSdk
|
|
|
279
275
|
["tempgmailer", "TempGmailer", "tempgmailer.com"],
|
|
280
276
|
["temp-mail-org", "Temp-Mail.org", "temp-mail.org"],
|
|
281
277
|
["xkx-me", "XKX.me", "xkx.me"],
|
|
282
|
-
["gonebox-email", "Gonebox Email", "gonebox.email"],
|
|
283
278
|
["mailcat-ai", "Mailcat AI", "mailcat.ai"],
|
|
284
279
|
["tempgo-email", "TempGo Email", "tempgo.email"],
|
|
285
280
|
["restmail-net", "Restmail.net", "restmail.net"],
|
|
286
281
|
["dropmail-me", "DropMail.me", "dropmail.me"],
|
|
287
282
|
["ten-minute-mail-net", "10MinuteMail.net", "10minutemail.net"],
|
|
283
|
+
["tempmails-io", "TempMails.io", "tempmails.io"],
|
|
284
|
+
["shitpost-email", "ShitPost.email", "shitpost.email"],
|
|
285
|
+
["smails", "Smails.dev", "smails.dev"],
|
|
286
|
+
["tempmailportal", "TempMail Portal", "tempmailportal.com"],
|
|
287
|
+
["huskmail", "HuskMail", "huskmail.xyz"],
|
|
288
|
+
["zerodrop", "Zerodrop", "zerodrop.dev"],
|
|
289
|
+
["firetempmail", "FireTempMail", "firetempmail.com"],
|
|
290
|
+
["nullmail", "NullMail", "nullmail.cc"],
|
|
291
|
+
["tenmin-app", "Tenmin.app", "tenmin.app"],
|
|
292
|
+
["mtempmail", "MTempMail", "mtempmail.com"],
|
|
293
|
+
["tempmail-ee", "TempMail.ee", "tempmail.ee"],
|
|
294
|
+
["temporarymail-com", "Temporarymail.com", "temporarymail.com"],
|
|
295
|
+
["30minemail", "30minemail", "30minemail.com"],
|
|
296
|
+
["linshi-xyz", "Linshi.xyz", "linshi.xyz"],
|
|
297
|
+
["crazymailing", "CrazyMailing", "crazymailing.com"],
|
|
298
|
+
["noxen-de5-net", "UniMail Bot", "tempmail.noxen.de5.net"],
|
|
299
|
+
["nukemail", "NukeMail", "nukemail.app"],
|
|
300
|
+
["shadowmail", "ShadowMail", "shadowmail.win"],
|
|
301
|
+
["flybymail", "FlyByMail", "flybymail.com"],
|
|
302
|
+
["nowtempmail", "NowTempMail", "nowtempmail.com"],
|
|
303
|
+
["clawdemail", "ClawdEmail", "clawdemail.com"],
|
|
304
|
+
["tempmail100", "TempMail100", "tempmail100.com"],
|
|
305
|
+
["tempmailto", "Tempmailto", "tempmailto.com"],
|
|
306
|
+
["temp-mail-gg", "TempMailGG", "temp-mail.gg"],
|
|
307
|
+
["tmpkit", "Tmpkit", "tmpkit.com"],
|
|
308
|
+
["internxt", "Internxt", "internxt.com"],
|
|
309
|
+
["generator-email", "GeneratorEmail", "generator.email"],
|
|
288
310
|
].freeze
|
|
289
311
|
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module TempmailSdk
|
|
6
|
+
module Providers
|
|
7
|
+
# altmails.com 渠道实现
|
|
8
|
+
#
|
|
9
|
+
# 流程:
|
|
10
|
+
# 1. GET / 建立 session,从 HTML inline script 提取 CSRF token('_token': 'xxx')
|
|
11
|
+
# 2. GET /random-email-address 获取随机邮箱地址(纯文本响应)
|
|
12
|
+
# 3. 收信:重新建立 session 获取新 CSRF,POST /fetch-emails/{email} 获取邮件列表
|
|
13
|
+
# 4. GET /view/{id} 获取每封邮件正文 HTML
|
|
14
|
+
module Altmails
|
|
15
|
+
CHANNEL = "altmails"
|
|
16
|
+
BASE_URL = "https://tempmail.altmails.com"
|
|
17
|
+
|
|
18
|
+
BROWSER_HEADERS = {
|
|
19
|
+
"Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
|
20
|
+
"Accept-Language" => "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7",
|
|
21
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
CSRF_RE = /'_token'\s*:\s*'([^']+)'/.freeze
|
|
25
|
+
|
|
26
|
+
module_function
|
|
27
|
+
|
|
28
|
+
# 访问首页提取 CSRF token
|
|
29
|
+
# @return [String]
|
|
30
|
+
def fetch_csrf
|
|
31
|
+
resp = Http.get("#{BASE_URL}/", headers: BROWSER_HEADERS)
|
|
32
|
+
resp.raise_for_status
|
|
33
|
+
m = resp.body.match(CSRF_RE)
|
|
34
|
+
raise "altmails: 未能从首页提取 CSRF token" unless m
|
|
35
|
+
|
|
36
|
+
m[1]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# 创建临时邮箱
|
|
40
|
+
# @return [EmailInfo]
|
|
41
|
+
def generate_email
|
|
42
|
+
csrf = fetch_csrf
|
|
43
|
+
resp = Http.get("#{BASE_URL}/random-email-address",
|
|
44
|
+
headers: BROWSER_HEADERS.merge("Referer" => "#{BASE_URL}/"))
|
|
45
|
+
resp.raise_for_status
|
|
46
|
+
email = resp.body.strip
|
|
47
|
+
raise "altmails: 邮箱地址无效: #{email.inspect}" if email.empty? || !email.include?("@")
|
|
48
|
+
|
|
49
|
+
EmailInfo.new(channel: CHANNEL, email: email, token: csrf)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# 获取邮件列表
|
|
53
|
+
# @param email [String]
|
|
54
|
+
# @param token [String] CSRF token(收信时重新获取新 session)
|
|
55
|
+
# @return [Array<Email>]
|
|
56
|
+
def get_emails(email, token)
|
|
57
|
+
_ = token
|
|
58
|
+
csrf = fetch_csrf
|
|
59
|
+
fetch_url = "#{BASE_URL}/fetch-emails/#{URI.encode_www_form_component(email)}"
|
|
60
|
+
form = "_token=#{URI.encode_www_form_component(csrf)}"
|
|
61
|
+
resp = Http.post(fetch_url,
|
|
62
|
+
headers: {
|
|
63
|
+
"Accept" => "application/json, text/plain, */*",
|
|
64
|
+
"Accept-Language" => "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7",
|
|
65
|
+
"Content-Type" => "application/x-www-form-urlencoded",
|
|
66
|
+
"Origin" => BASE_URL,
|
|
67
|
+
"Referer" => "#{BASE_URL}/",
|
|
68
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
69
|
+
"X-Requested-With" => "XMLHttpRequest"
|
|
70
|
+
},
|
|
71
|
+
body: form)
|
|
72
|
+
resp.raise_for_status
|
|
73
|
+
items = begin
|
|
74
|
+
resp.json
|
|
75
|
+
rescue StandardError
|
|
76
|
+
[]
|
|
77
|
+
end
|
|
78
|
+
return [] unless items.is_a?(Array)
|
|
79
|
+
|
|
80
|
+
items.filter_map do |item|
|
|
81
|
+
next unless item.is_a?(Hash)
|
|
82
|
+
|
|
83
|
+
item["to"] = email
|
|
84
|
+
mail_id = item["id"].to_s
|
|
85
|
+
unless mail_id.empty?
|
|
86
|
+
begin
|
|
87
|
+
vr = Http.get("#{BASE_URL}/view/#{URI.encode_www_form_component(mail_id)}",
|
|
88
|
+
headers: BROWSER_HEADERS.merge("Referer" => "#{BASE_URL}/"))
|
|
89
|
+
item["html_body"] = vr.body if vr.ok?
|
|
90
|
+
rescue StandardError
|
|
91
|
+
# 忽略正文获取失败
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
Normalize.normalize_email(item, email)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "json"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module TempmailSdk
|
|
8
|
+
module Providers
|
|
9
|
+
# apihz(接口盒子)渠道实现
|
|
10
|
+
#
|
|
11
|
+
# 需 id/key 凭据,邮箱有效期 10 分钟。读信须携带创建时的 pwd,
|
|
12
|
+
# 故 token 用 base64(JSON{mail,pwd}) 编码保存。
|
|
13
|
+
module Apihz
|
|
14
|
+
CHANNEL = "apihz"
|
|
15
|
+
BASE_URL = "https://cn.apihz.cn"
|
|
16
|
+
TOK_PREFIX = "apihz1:"
|
|
17
|
+
# 官方公共账号(共享频次),未配置自有 id/key 时使用
|
|
18
|
+
PUBLIC_ID = "88888888"
|
|
19
|
+
PUBLIC_KEY = "88888888"
|
|
20
|
+
DOMAINS = %w[apimail.email apimail.vip].freeze
|
|
21
|
+
|
|
22
|
+
HEADERS = {
|
|
23
|
+
"Accept" => "application/json",
|
|
24
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
|
|
25
|
+
"(KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36"
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
module_function
|
|
29
|
+
|
|
30
|
+
# 读取 id/key:优先环境变量 APIHZ_ID/APIHZ_KEY,回退官方公共账号
|
|
31
|
+
def credentials
|
|
32
|
+
id = ENV["APIHZ_ID"].to_s.strip
|
|
33
|
+
key = ENV["APIHZ_KEY"].to_s.strip
|
|
34
|
+
id = PUBLIC_ID if id.empty?
|
|
35
|
+
key = PUBLIC_KEY if key.empty?
|
|
36
|
+
[id, key]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# 生成随机本地部分
|
|
40
|
+
def random_local(length = 10)
|
|
41
|
+
chars = ("a".."z").to_a + ("0".."9").to_a
|
|
42
|
+
Array.new(length) { chars.sample }.join
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# 生成 12 位随机密码
|
|
46
|
+
def random_password
|
|
47
|
+
chars = ("A".."Z").to_a + ("a".."z").to_a + ("0".."9").to_a
|
|
48
|
+
Array.new(12) { chars.sample }.join
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# token 编码:前缀 + base64(JSON{mail,pwd})
|
|
52
|
+
def encode_token(mail, pwd)
|
|
53
|
+
raw = JSON.generate("mail" => mail, "pwd" => pwd)
|
|
54
|
+
TOK_PREFIX + Base64.strict_encode64(raw)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# token 解码
|
|
58
|
+
def decode_token(token)
|
|
59
|
+
raise "apihz: 无效 token" unless token.to_s.start_with?(TOK_PREFIX)
|
|
60
|
+
|
|
61
|
+
raw = Base64.strict_decode64(token[TOK_PREFIX.length..])
|
|
62
|
+
o = JSON.parse(raw)
|
|
63
|
+
mail = o["mail"].to_s.strip
|
|
64
|
+
pwd = o["pwd"].to_s.strip
|
|
65
|
+
raise "apihz: 无效 token" if mail.empty? || pwd.empty?
|
|
66
|
+
|
|
67
|
+
[mail, pwd]
|
|
68
|
+
rescue ArgumentError, JSON::ParserError
|
|
69
|
+
raise "apihz: 无效 token"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# 创建临时邮箱
|
|
73
|
+
# GET /api/mail/mailcache.php?id=&key=&domain=&name=&pwd=&buytype=0
|
|
74
|
+
# @return [EmailInfo]
|
|
75
|
+
def generate_email
|
|
76
|
+
id, key = credentials
|
|
77
|
+
domain = DOMAINS.sample
|
|
78
|
+
name = random_local
|
|
79
|
+
pwd = random_password
|
|
80
|
+
|
|
81
|
+
url = "#{BASE_URL}/api/mail/mailcache.php?" \
|
|
82
|
+
"id=#{URI.encode_www_form_component(id)}&key=#{URI.encode_www_form_component(key)}" \
|
|
83
|
+
"&domain=#{URI.encode_www_form_component(domain)}" \
|
|
84
|
+
"&name=#{URI.encode_www_form_component(name)}" \
|
|
85
|
+
"&pwd=#{URI.encode_www_form_component(pwd)}&buytype=0"
|
|
86
|
+
|
|
87
|
+
resp = Http.get(url, headers: HEADERS)
|
|
88
|
+
resp.raise_for_status
|
|
89
|
+
data = resp.json
|
|
90
|
+
raise "apihz: 创建邮箱失败 #{data['msg']}" if data["code"] != 200 || data["mail"].to_s.empty?
|
|
91
|
+
|
|
92
|
+
final_pwd = data["pwd"].to_s
|
|
93
|
+
final_pwd = pwd if final_pwd.empty?
|
|
94
|
+
|
|
95
|
+
EmailInfo.new(channel: CHANNEL, email: data["mail"], token: encode_token(data["mail"], final_pwd))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# 获取邮件列表
|
|
99
|
+
# GET /api/mail/mailgetlist.php?id=&key=&mail=&pwd=&page=1
|
|
100
|
+
# @param token [String]
|
|
101
|
+
# @return [Array<Email>]
|
|
102
|
+
def get_emails(token)
|
|
103
|
+
mail, pwd = decode_token(token)
|
|
104
|
+
id, key = credentials
|
|
105
|
+
|
|
106
|
+
url = "#{BASE_URL}/api/mail/mailgetlist.php?" \
|
|
107
|
+
"id=#{URI.encode_www_form_component(id)}&key=#{URI.encode_www_form_component(key)}" \
|
|
108
|
+
"&mail=#{URI.encode_www_form_component(mail)}" \
|
|
109
|
+
"&pwd=#{URI.encode_www_form_component(pwd)}&page=1"
|
|
110
|
+
|
|
111
|
+
resp = Http.get(url, headers: HEADERS)
|
|
112
|
+
resp.raise_for_status
|
|
113
|
+
data = resp.json
|
|
114
|
+
return [] if data["code"] != 200
|
|
115
|
+
|
|
116
|
+
list = data["data"]
|
|
117
|
+
return [] unless list.is_a?(Array) && !list.empty?
|
|
118
|
+
|
|
119
|
+
list.map do |msg|
|
|
120
|
+
from_addr = msg["frommail"].to_s
|
|
121
|
+
from_addr = msg["fromname"].to_s if from_addr.empty?
|
|
122
|
+
date_val = msg["time2"].to_s
|
|
123
|
+
date_val = msg["time1"].to_s if date_val.empty?
|
|
124
|
+
Normalize.normalize_email({
|
|
125
|
+
"id" => msg["time1"].to_s,
|
|
126
|
+
"from" => from_addr,
|
|
127
|
+
"to" => mail,
|
|
128
|
+
"subject" => msg["subject"].to_s,
|
|
129
|
+
"text" => msg["content"].to_s,
|
|
130
|
+
"html" => msg["content"].to_s,
|
|
131
|
+
"date" => date_val,
|
|
132
|
+
"isRead" => false
|
|
133
|
+
}, mail)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module TempmailSdk
|
|
6
|
+
module Providers
|
|
7
|
+
# awamail.com 渠道实现
|
|
8
|
+
#
|
|
9
|
+
# 流程:
|
|
10
|
+
# 1. POST /welcome/change_mailbox(空 body)不跟随重定向,从 Set-Cookie 提取 awamail_session
|
|
11
|
+
# 2. GET /welcome/get_emails 携带 Cookie 获取邮件列表
|
|
12
|
+
module Awamail
|
|
13
|
+
CHANNEL = "awamail"
|
|
14
|
+
BASE_URL = "https://awamail.com/welcome"
|
|
15
|
+
|
|
16
|
+
HEADERS = {
|
|
17
|
+
"Accept" => "application/json, text/javascript, */*; q=0.01",
|
|
18
|
+
"Accept-Language" => "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
|
19
|
+
"Cache-Control" => "no-cache",
|
|
20
|
+
"DNT" => "1",
|
|
21
|
+
"Origin" => "https://awamail.com",
|
|
22
|
+
"Pragma" => "no-cache",
|
|
23
|
+
"Referer" => "https://awamail.com/?lang=zh",
|
|
24
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
|
|
25
|
+
"(KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0",
|
|
26
|
+
"X-Requested-With" => "XMLHttpRequest"
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# 创建临时邮箱
|
|
32
|
+
# POST /welcome/change_mailbox,从 Set-Cookie 提取 awamail_session
|
|
33
|
+
# @return [EmailInfo]
|
|
34
|
+
def generate_email
|
|
35
|
+
resp = Http.post("#{BASE_URL}/change_mailbox",
|
|
36
|
+
headers: HEADERS.merge("Content-Length" => "0"))
|
|
37
|
+
# 不跟随重定向,直接从响应提取 cookie
|
|
38
|
+
session_cookie = resp.cookie_value("awamail_session")
|
|
39
|
+
raise "awamail: 未能提取 awamail_session cookie" if session_cookie.to_s.empty?
|
|
40
|
+
|
|
41
|
+
cookie_str = "awamail_session=#{session_cookie}"
|
|
42
|
+
|
|
43
|
+
data = begin
|
|
44
|
+
resp.json
|
|
45
|
+
rescue StandardError
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
email_addr = data.is_a?(Hash) ? data.dig("data", "email_address").to_s : ""
|
|
50
|
+
if email_addr.empty?
|
|
51
|
+
# 若 POST 响应无邮箱,尝试 GET get_emails 获取
|
|
52
|
+
gr = Http.get("#{BASE_URL}/get_emails",
|
|
53
|
+
headers: HEADERS.merge("Cookie" => cookie_str))
|
|
54
|
+
gr.raise_for_status
|
|
55
|
+
gd = gr.json
|
|
56
|
+
email_addr = gd.is_a?(Hash) ? gd.dig("data", "email_address").to_s : ""
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
raise "awamail: 未能获取邮箱地址" if email_addr.empty?
|
|
60
|
+
|
|
61
|
+
info = EmailInfo.new(channel: CHANNEL, email: email_addr, token: cookie_str)
|
|
62
|
+
if data.is_a?(Hash)
|
|
63
|
+
info.expires_at = data.dig("data", "expired_at").to_s
|
|
64
|
+
info.created_at = data.dig("data", "created_at").to_s
|
|
65
|
+
end
|
|
66
|
+
info
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# 获取邮件列表
|
|
70
|
+
# GET /welcome/get_emails,携带 Cookie
|
|
71
|
+
# @param token [String] awamail_session cookie 字符串
|
|
72
|
+
# @param email [String]
|
|
73
|
+
# @return [Array<Email>]
|
|
74
|
+
def get_emails(token, email)
|
|
75
|
+
resp = Http.get("#{BASE_URL}/get_emails",
|
|
76
|
+
headers: HEADERS.merge(
|
|
77
|
+
"Cookie" => token,
|
|
78
|
+
"X-Requested-With" => "XMLHttpRequest"
|
|
79
|
+
))
|
|
80
|
+
resp.raise_for_status
|
|
81
|
+
data = resp.json
|
|
82
|
+
return [] unless data.is_a?(Hash) && data["success"]
|
|
83
|
+
|
|
84
|
+
emails_raw = data.dig("data", "emails")
|
|
85
|
+
return [] unless emails_raw.is_a?(Array)
|
|
86
|
+
|
|
87
|
+
emails_raw.filter_map do |raw|
|
|
88
|
+
next unless raw.is_a?(Hash)
|
|
89
|
+
|
|
90
|
+
Normalize.normalize_email(raw, email)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
|
|
6
|
+
module TempmailSdk
|
|
7
|
+
module Providers
|
|
8
|
+
# best-temp-mail.com 渠道实现
|
|
9
|
+
#
|
|
10
|
+
# 纯 JSON REST API,无需认证,无需 Session。
|
|
11
|
+
# 创建邮箱: POST /api/v3/createEmail body: {"intToken":"<uuid>"}
|
|
12
|
+
# 获取邮件: POST /api/v3/getEmailList body: {"address":"...","id":"...","intToken":"...","update_tag":"..."}
|
|
13
|
+
module BestTempMail
|
|
14
|
+
CHANNEL = "best-temp-mail"
|
|
15
|
+
API_BASE = "https://best-temp-mail.com/api/v3"
|
|
16
|
+
|
|
17
|
+
HEADERS = {
|
|
18
|
+
"Accept" => "application/json, text/plain, */*",
|
|
19
|
+
"Accept-Language" => "zh-CN,zh;q=0.9,en;q=0.8",
|
|
20
|
+
"Content-Type" => "application/json",
|
|
21
|
+
"Origin" => "https://best-temp-mail.com",
|
|
22
|
+
"Referer" => "https://best-temp-mail.com/",
|
|
23
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
|
|
24
|
+
"(KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
# 创建临时邮箱
|
|
30
|
+
# @return [EmailInfo]
|
|
31
|
+
def generate_email
|
|
32
|
+
int_token = SecureRandom.uuid
|
|
33
|
+
resp = Http.post("#{API_BASE}/createEmail",
|
|
34
|
+
headers: HEADERS,
|
|
35
|
+
json: { "intToken" => int_token })
|
|
36
|
+
resp.raise_for_status
|
|
37
|
+
data = resp.json
|
|
38
|
+
raise "best-temp-mail: 创建邮箱失败 status=#{data['status']}" \
|
|
39
|
+
if data["status"] != "success" || data.dig("data", "address").to_s.empty?
|
|
40
|
+
|
|
41
|
+
d = data["data"]
|
|
42
|
+
token = JSON.generate("intToken" => int_token, "id" => d["id"].to_s, "update_tag" => d["update_tag"].to_s)
|
|
43
|
+
EmailInfo.new(channel: CHANNEL, email: d["address"], token: token)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# 获取邮件列表
|
|
47
|
+
# @param email [String]
|
|
48
|
+
# @param token [String] JSON 编码的 intToken/id/update_tag
|
|
49
|
+
# @return [Array<Email>]
|
|
50
|
+
def get_emails(email, token)
|
|
51
|
+
tkn = JSON.parse(token)
|
|
52
|
+
resp = Http.post("#{API_BASE}/getEmailList",
|
|
53
|
+
headers: HEADERS,
|
|
54
|
+
json: {
|
|
55
|
+
"address" => email,
|
|
56
|
+
"id" => tkn["id"].to_s,
|
|
57
|
+
"intToken" => tkn["intToken"].to_s,
|
|
58
|
+
"update_tag" => tkn["update_tag"].to_s
|
|
59
|
+
})
|
|
60
|
+
resp.raise_for_status
|
|
61
|
+
data = resp.json
|
|
62
|
+
return [] unless data.dig("data", "hasNewEmail")
|
|
63
|
+
|
|
64
|
+
emails_raw = data.dig("data", "emails")
|
|
65
|
+
return [] unless emails_raw.is_a?(Array)
|
|
66
|
+
|
|
67
|
+
emails_raw.filter_map do |raw|
|
|
68
|
+
next unless raw.is_a?(Hash)
|
|
69
|
+
|
|
70
|
+
Normalize.normalize_email(raw, email)
|
|
71
|
+
end
|
|
72
|
+
rescue JSON::ParserError
|
|
73
|
+
raise "best-temp-mail: 无效的 token 格式"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|