tempmail_sdk 1.3.4 → 1.3.6
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 +52 -27
- data/lib/tempmail_sdk/channels_data.rb +52 -27
- data/lib/tempmail_sdk/providers/clawdemail.rb +122 -0
- data/lib/tempmail_sdk/providers/crazymailing.rb +114 -0
- data/lib/tempmail_sdk/providers/duckmail.rb +9 -2
- 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/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/mail_tm.rb +9 -2
- data/lib/tempmail_sdk/providers/mailmomy.rb +1 -1
- data/lib/tempmail_sdk/providers/mailticking.rb +139 -0
- data/lib/tempmail_sdk/providers/mtempmail.rb +140 -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/shadowmail.rb +174 -0
- data/lib/tempmail_sdk/providers/shitpost_email.rb +85 -0
- data/lib/tempmail_sdk/providers/smails.rb +128 -0
- data/lib/tempmail_sdk/providers/temp_mail_gg.rb +362 -0
- data/lib/tempmail_sdk/providers/tempmail100.rb +148 -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/thirty_min_email.rb +90 -0
- data/lib/tempmail_sdk/providers/tmpkit.rb +129 -0
- data/lib/tempmail_sdk/providers/zerodrop.rb +90 -0
- data/lib/tempmail_sdk/registry.rb +223 -107
- data/lib/tempmail_sdk/types.rb +13 -0
- data/lib/tempmail_sdk/version.rb +1 -1
- data/lib/tempmail_sdk.rb +1 -1
- metadata +31 -7
- data/lib/tempmail_sdk/providers/gonebox_email.rb +0 -89
- data/lib/tempmail_sdk/providers/mohmal.rb +0 -208
- data/lib/tempmail_sdk/providers/temp_mail_now.rb +0 -103
- data/lib/tempmail_sdk/providers/webmailtemp.rb +0 -108
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module TempmailSdk
|
|
6
|
+
module Providers
|
|
7
|
+
# Tmpkit 渠道实现(tmpkit.com,Next.js tRPC 前端 + Go-Guerrilla SMTP 后端)
|
|
8
|
+
#
|
|
9
|
+
# 流程:
|
|
10
|
+
# POST /api/rpc/tempmail/initSession(body 为 tRPC 包裹 {"json":{}})建箱,
|
|
11
|
+
# 响应 session.sessionId 与 session.email(sessionId 同值 Set-Cookie)
|
|
12
|
+
# POST /api/rpc/tempmail/getEmails({"json":{"offset":0,"limit":20}} +
|
|
13
|
+
# Cookie tempmail_session=<sessionId>)列信(列表键 mailId,无 id)
|
|
14
|
+
# POST /api/rpc/tempmail/getEmailDetail({"json":{"mailId":<数字>}})取正文
|
|
15
|
+
# 会话粘性:token 保存 sessionId(tempMailSession=<sid>),读信显式携带
|
|
16
|
+
# Cookie 请求头,防并行会话串箱。
|
|
17
|
+
module Tmpkit
|
|
18
|
+
CHANNEL = "tmpkit"
|
|
19
|
+
BASE_URL = "https://tmpkit.com"
|
|
20
|
+
RPC_PREFIX = "#{BASE_URL}/api/rpc/tempmail"
|
|
21
|
+
|
|
22
|
+
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " \
|
|
23
|
+
"(KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36"
|
|
24
|
+
|
|
25
|
+
module_function
|
|
26
|
+
|
|
27
|
+
# tRPC 调用请求头(Content-Type JSON、Accept 通配、同站 Origin/Referer)
|
|
28
|
+
# @param cookie [String] sessionId,非空时携带 tempmail_session Cookie
|
|
29
|
+
# @return [Hash]
|
|
30
|
+
def rpc_headers(cookie = "")
|
|
31
|
+
hdrs = {
|
|
32
|
+
"User-Agent" => USER_AGENT,
|
|
33
|
+
"Accept" => "*/*",
|
|
34
|
+
"Content-Type" => "application/json",
|
|
35
|
+
"Origin" => BASE_URL,
|
|
36
|
+
"Referer" => "#{BASE_URL}/en"
|
|
37
|
+
}
|
|
38
|
+
hdrs["Cookie"] = "tempmail_session=#{cookie}" unless cookie.empty?
|
|
39
|
+
hdrs
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# 对 tmpkit 发起 rpc 调用(tRPC 包裹 {"json":<reqBody>})
|
|
43
|
+
# 响应外层 {"json":{...}} 解析为 Hash 返回。
|
|
44
|
+
# @param procedure [String] rpc 过程名
|
|
45
|
+
# @param req_body [Hash] 过程参数
|
|
46
|
+
# @param cookie [String] sessionId
|
|
47
|
+
# @return [Hash]
|
|
48
|
+
def rpc(procedure, req_body, cookie = "")
|
|
49
|
+
resp = Http.post("#{RPC_PREFIX}/#{procedure}",
|
|
50
|
+
headers: rpc_headers(cookie),
|
|
51
|
+
body: JSON.generate({ json: req_body }),
|
|
52
|
+
timeout: 15)
|
|
53
|
+
resp.raise_for_status
|
|
54
|
+
outer = resp.json
|
|
55
|
+
payload = outer.is_a?(Hash) ? outer["json"] : nil
|
|
56
|
+
raise "tmpkit: #{procedure} 响应缺 json 载荷" unless payload.is_a?(Hash)
|
|
57
|
+
|
|
58
|
+
payload
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# 创建 tmpkit.com 临时邮箱
|
|
62
|
+
# 调 initSession(tRPC 包裹 {"json":{}}),sessionId 与邮箱地址同返。
|
|
63
|
+
# @return [EmailInfo]
|
|
64
|
+
def generate_email
|
|
65
|
+
data = rpc("initSession", {})
|
|
66
|
+
sess = data["session"]
|
|
67
|
+
raise "tmpkit: 创建会话响应缺 session 字段" unless sess.is_a?(Hash)
|
|
68
|
+
|
|
69
|
+
email = sess["email"].to_s.strip
|
|
70
|
+
session_id = sess["sessionId"].to_s.strip
|
|
71
|
+
raise "tmpkit: 创建会话响应缺少必要字段(email/sessionId)" if email.empty? || session_id.empty? || !email.include?("@")
|
|
72
|
+
|
|
73
|
+
EmailInfo.new(channel: CHANNEL, email: email,
|
|
74
|
+
token: "tempMailSession=#{session_id}")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# 获取 tmpkit.com 邮件列表
|
|
78
|
+
# getEmails(offset 0 / limit 20)取摘要,逐封 getEmailDetail 拉详情并
|
|
79
|
+
# 将详情键并入摘要;详情失败回退列表摘要。getEmails 返回的 session.email
|
|
80
|
+
# 与收信邮箱不符时报错,防止会话被覆盖。
|
|
81
|
+
# @param email [String] 邮箱地址
|
|
82
|
+
# @param token [String] 会话凭据串(tempMailSession=<sessionId>)
|
|
83
|
+
# @return [Array<Email>]
|
|
84
|
+
def get_emails(email, token)
|
|
85
|
+
raw = token.to_s.strip
|
|
86
|
+
mailbox = raw.start_with?("tempMailSession=") ? raw.delete_prefix("tempMailSession=") : raw
|
|
87
|
+
raise "tmpkit: 会话 token 为空" if mailbox.empty?
|
|
88
|
+
|
|
89
|
+
data = rpc("getEmails", { offset: 0, limit: 20 }, mailbox)
|
|
90
|
+
|
|
91
|
+
# 会话指向校验:getEmails 响应自带 session.email(无 Cookie 时
|
|
92
|
+
# session 为 null,同样视为会话失效)
|
|
93
|
+
sess = data["session"]
|
|
94
|
+
if sess.is_a?(Hash)
|
|
95
|
+
got = sess["email"].to_s.strip
|
|
96
|
+
raise "tmpkit: 会话邮箱不匹配(响应 #{got},请求 #{email})" if !got.empty? && got != email
|
|
97
|
+
else
|
|
98
|
+
raise "tmpkit: 会话已失效(getEmails 返回空会话)"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
list = data["emails"]
|
|
102
|
+
raise "tmpkit: 邮件列表响应缺 emails 字段" unless list.is_a?(Array)
|
|
103
|
+
|
|
104
|
+
list.map do |item|
|
|
105
|
+
next unless item.is_a?(Hash)
|
|
106
|
+
|
|
107
|
+
m = item.dup
|
|
108
|
+
# mailId 为数字:合法时逐封拉详情(详情键并入摘要,跳过会话类键)
|
|
109
|
+
mail_id = m["mailId"]
|
|
110
|
+
if mail_id.is_a?(Numeric) && mail_id.positive?
|
|
111
|
+
begin
|
|
112
|
+
detail = rpc("getEmailDetail", { mailId: mail_id.to_i }, mailbox)
|
|
113
|
+
if detail.is_a?(Hash)
|
|
114
|
+
detail.each do |k, v|
|
|
115
|
+
next if %w[session emails total error].include?(k)
|
|
116
|
+
|
|
117
|
+
m[k] = v
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
rescue StandardError
|
|
121
|
+
# 详情失败回退列表摘要
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
Normalize.normalize_email(m, email)
|
|
125
|
+
end.compact
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module TempmailSdk
|
|
6
|
+
module Providers
|
|
7
|
+
# Zerodrop 渠道实现(zerodrop.dev)
|
|
8
|
+
#
|
|
9
|
+
# 无认证 REST:建箱无需请求,本地生成 "sdk"+8 位随机名,地址为 <名>@zerodrop-sandbox.online;
|
|
10
|
+
# 读信 GET /api/inbox/{name}?source=sdk,响应形如 {"emails":[...],"count":N}。
|
|
11
|
+
# 平台邮件对象只有 id/from/to/subject/receivedAt/raw/otp/magicLink,正文仅存在于
|
|
12
|
+
# raw(完整 MIME 原文),需剥离头部提取纯文本 body。
|
|
13
|
+
module Zerodrop
|
|
14
|
+
CHANNEL = "zerodrop"
|
|
15
|
+
BASE_URL = "https://zerodrop.dev"
|
|
16
|
+
DOMAIN = "zerodrop-sandbox.online"
|
|
17
|
+
|
|
18
|
+
HEADERS = {
|
|
19
|
+
"Accept" => "application/json",
|
|
20
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
|
|
21
|
+
"(KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0"
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
# 生成 "sdk"+8 位 [a-z0-9] 随机本地名
|
|
27
|
+
CHARS = ("a".."z").to_a + ("0".."9").to_a
|
|
28
|
+
def random_name
|
|
29
|
+
"sdk" + Array.new(8) { CHARS.sample }.join
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# 从 raw(完整 MIME 原文)提取纯文本正文:
|
|
33
|
+
# 定位首个空行(RFC 5322 头部/正文分隔,\r\n\r\n 或 \n\n),其后部分即 body
|
|
34
|
+
# @param raw [String] MIME 原文
|
|
35
|
+
# @return [String]
|
|
36
|
+
def raw_body(raw)
|
|
37
|
+
idx = raw.index("\r\n\r\n")
|
|
38
|
+
return raw[(idx + 4)..] if idx
|
|
39
|
+
|
|
40
|
+
idx = raw.index("\n\n")
|
|
41
|
+
return raw[(idx + 2)..] if idx
|
|
42
|
+
|
|
43
|
+
""
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# 创建临时邮箱
|
|
47
|
+
# 建箱无需请求,本地生成随机名,token 复用完整地址以便收件箱回查
|
|
48
|
+
# @return [EmailInfo]
|
|
49
|
+
def generate_email
|
|
50
|
+
email = "#{random_name}@#{DOMAIN}"
|
|
51
|
+
EmailInfo.new(channel: CHANNEL, email: email, token: email)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# 读取收件箱
|
|
55
|
+
# GET /api/inbox/{name}?source=sdk
|
|
56
|
+
# @param email [String] 邮箱地址
|
|
57
|
+
# @param _token [String] 令牌(本渠道忽略,以邮箱为准)
|
|
58
|
+
# @return [Array<Email>]
|
|
59
|
+
def get_emails(email, _token)
|
|
60
|
+
addr = email.to_s.strip
|
|
61
|
+
parts = addr.split("@", 2)
|
|
62
|
+
raise "zerodrop: 非 #{DOMAIN} 域邮箱地址" unless parts.size == 2 && parts[1] == DOMAIN
|
|
63
|
+
|
|
64
|
+
url = "#{BASE_URL}/api/inbox/#{URI.encode_www_form_component(parts[0])}?source=sdk"
|
|
65
|
+
resp = Http.get(url, headers: HEADERS, timeout: 15)
|
|
66
|
+
resp.raise_for_status
|
|
67
|
+
data = resp.json
|
|
68
|
+
emails = data.is_a?(Hash) ? data["emails"] : nil
|
|
69
|
+
return [] unless emails.is_a?(Array)
|
|
70
|
+
|
|
71
|
+
emails.filter_map do |m|
|
|
72
|
+
next unless m.is_a?(Hash)
|
|
73
|
+
|
|
74
|
+
row = {
|
|
75
|
+
"id" => m["id"],
|
|
76
|
+
"from" => m["from"],
|
|
77
|
+
"to" => addr,
|
|
78
|
+
"subject" => m["subject"],
|
|
79
|
+
"date" => m["receivedAt"] || m["date"]
|
|
80
|
+
}
|
|
81
|
+
# 正文仅存在于 raw(完整 MIME 原文):提取纯文本 body 作 text
|
|
82
|
+
raw = m["raw"].to_s
|
|
83
|
+
body = raw_body(raw)
|
|
84
|
+
row["text"] = body unless body.empty?
|
|
85
|
+
Normalize.normalize_email(row, addr)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|