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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/tempmail_sdk/channels.rb +29 -7
  4. data/lib/tempmail_sdk/channels_data.rb +29 -7
  5. data/lib/tempmail_sdk/providers/altmails.rb +99 -0
  6. data/lib/tempmail_sdk/providers/apihz.rb +138 -0
  7. data/lib/tempmail_sdk/providers/awamail.rb +95 -0
  8. data/lib/tempmail_sdk/providers/best_temp_mail.rb +77 -0
  9. data/lib/tempmail_sdk/providers/chatgpt_org_uk.rb +129 -0
  10. data/lib/tempmail_sdk/providers/clawdemail.rb +122 -0
  11. data/lib/tempmail_sdk/providers/crazymailing.rb +114 -0
  12. data/lib/tempmail_sdk/providers/disposablemail.rb +125 -0
  13. data/lib/tempmail_sdk/providers/disposablemail_app.rb +66 -0
  14. data/lib/tempmail_sdk/providers/email10min.rb +152 -0
  15. data/lib/tempmail_sdk/providers/emailnator.rb +132 -0
  16. data/lib/tempmail_sdk/providers/emailtemp_org.rb +131 -0
  17. data/lib/tempmail_sdk/providers/expressinboxhub.rb +118 -0
  18. data/lib/tempmail_sdk/providers/fakemail.rb +143 -0
  19. data/lib/tempmail_sdk/providers/firetempmail.rb +86 -0
  20. data/lib/tempmail_sdk/providers/flybymail.rb +93 -0
  21. data/lib/tempmail_sdk/providers/generator_email.rb +146 -0
  22. data/lib/tempmail_sdk/providers/haribu.rb +29 -3
  23. data/lib/tempmail_sdk/providers/huskmail.rb +132 -0
  24. data/lib/tempmail_sdk/providers/internxt.rb +176 -0
  25. data/lib/tempmail_sdk/providers/linshi_xyz.rb +79 -0
  26. data/lib/tempmail_sdk/providers/linshiyouxiang_net.rb +85 -0
  27. data/lib/tempmail_sdk/providers/mail_sunls.rb +42 -1
  28. data/lib/tempmail_sdk/providers/mail_td.rb +161 -0
  29. data/lib/tempmail_sdk/providers/mailcat_ai.rb +52 -0
  30. data/lib/tempmail_sdk/providers/maildrop.rb +79 -4
  31. data/lib/tempmail_sdk/providers/mailgolem.rb +96 -0
  32. data/lib/tempmail_sdk/providers/mailinator.rb +9 -2
  33. data/lib/tempmail_sdk/providers/mailmomy.rb +1 -1
  34. data/lib/tempmail_sdk/providers/mailtemp_cc.rb +91 -0
  35. data/lib/tempmail_sdk/providers/mailticking.rb +139 -0
  36. data/lib/tempmail_sdk/providers/minuteinbox.rb +174 -0
  37. data/lib/tempmail_sdk/providers/moakt.rb +29 -3
  38. data/lib/tempmail_sdk/providers/mtempmail.rb +140 -0
  39. data/lib/tempmail_sdk/providers/mytempmail_cc.rb +76 -0
  40. data/lib/tempmail_sdk/providers/nowtempmail.rb +112 -0
  41. data/lib/tempmail_sdk/providers/noxen_de5_net.rb +392 -0
  42. data/lib/tempmail_sdk/providers/nukemail.rb +188 -0
  43. data/lib/tempmail_sdk/providers/nullmail.rb +95 -0
  44. data/lib/tempmail_sdk/providers/openinbox.rb +102 -0
  45. data/lib/tempmail_sdk/providers/shadowmail.rb +174 -0
  46. data/lib/tempmail_sdk/providers/shitpost_email.rb +85 -0
  47. data/lib/tempmail_sdk/providers/smail_pw.rb +156 -0
  48. data/lib/tempmail_sdk/providers/smails.rb +128 -0
  49. data/lib/tempmail_sdk/providers/socketio_mail.rb +25 -0
  50. data/lib/tempmail_sdk/providers/temp_mail_gg.rb +362 -0
  51. data/lib/tempmail_sdk/providers/tempgbox.rb +118 -0
  52. data/lib/tempmail_sdk/providers/tempmail100.rb +148 -0
  53. data/lib/tempmail_sdk/providers/tempmail_cn.rb +111 -0
  54. data/lib/tempmail_sdk/providers/tempmail_ee.rb +373 -0
  55. data/lib/tempmail_sdk/providers/tempmailportal.rb +131 -0
  56. data/lib/tempmail_sdk/providers/tempmails_io.rb +89 -0
  57. data/lib/tempmail_sdk/providers/tempmailto.rb +312 -0
  58. data/lib/tempmail_sdk/providers/temporarymail_com.rb +184 -0
  59. data/lib/tempmail_sdk/providers/tenmin_app.rb +100 -0
  60. data/lib/tempmail_sdk/providers/tenminutemail_net.rb +183 -0
  61. data/lib/tempmail_sdk/providers/thirty_min_email.rb +90 -0
  62. data/lib/tempmail_sdk/providers/tmpkit.rb +129 -0
  63. data/lib/tempmail_sdk/providers/twentyfourmail_chacuo.rb +83 -0
  64. data/lib/tempmail_sdk/providers/vip_215.rb +171 -0
  65. data/lib/tempmail_sdk/providers/zerodrop.rb +90 -0
  66. data/lib/tempmail_sdk/registry.rb +285 -23
  67. data/lib/tempmail_sdk/types.rb +13 -0
  68. data/lib/tempmail_sdk/version.rb +1 -1
  69. data/lib/tempmail_sdk.rb +1 -1
  70. metadata +58 -6
  71. data/lib/tempmail_sdk/providers/gonebox_email.rb +0 -89
  72. data/lib/tempmail_sdk/providers/temp_mail_now.rb +0 -103
  73. data/lib/tempmail_sdk/providers/webmailtemp.rb +0 -108
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "uri"
5
+
6
+ module TempmailSdk
7
+ module Providers
8
+ # 24mail.chacuo.net 渠道实现
9
+ # POST / 同一接口用于注册和收信,HTTP only
10
+ module TwentyfourmailChacuo
11
+ CHANNEL = "24mail-chacuo"
12
+ BASE_URL = "http://24mail.chacuo.net"
13
+ DOMAINS = %w[chacuo.net 027168.com].freeze
14
+
15
+ HEADERS = {
16
+ "Accept" => "application/json, text/javascript, */*; q=0.01",
17
+ "Accept-Language" => "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
18
+ "Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8",
19
+ "Origin" => BASE_URL,
20
+ "Referer" => "#{BASE_URL}/",
21
+ "User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
22
+ "(KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0",
23
+ "x-requested-with" => "XMLHttpRequest"
24
+ }.freeze
25
+
26
+ module_function
27
+
28
+ def random_local(length = 10)
29
+ chars = ("a".."z").to_a + ("0".."9").to_a
30
+ Array.new(length) { chars.sample }.join
31
+ end
32
+
33
+ # 创建 24mail-chacuo 临时邮箱
34
+ # @return [EmailInfo]
35
+ def generate_email
36
+ name = random_local(10)
37
+ domain = DOMAINS.sample
38
+ body = "data=#{URI.encode_www_form_component("#{name}@#{domain}")}&type=refresh&arg="
39
+ resp = Http.post(BASE_URL + "/", headers: HEADERS, body: body, timeout: 15)
40
+ resp.raise_for_status
41
+ data = JSON.parse(resp.body)
42
+ raise "24mail-chacuo: 创建失败 status=#{data["status"]} info=#{data["info"]}" unless data["status"] == 1
43
+
44
+ email = "#{name}@#{domain}"
45
+ EmailInfo.new(channel: CHANNEL, email: email, token: email)
46
+ end
47
+
48
+ # 获取 24mail-chacuo 邮件列表
49
+ # @param email [String]
50
+ # @return [Array<Email>]
51
+ def get_emails(email)
52
+ addr = email.to_s.strip
53
+ raise "24mail-chacuo: 邮箱地址为空" if addr.empty?
54
+
55
+ at_idx = addr.index("@")
56
+ name = at_idx ? addr[0...at_idx] : addr
57
+ domain = at_idx ? addr[at_idx + 1..] : DOMAINS[0]
58
+
59
+ body = "data=#{URI.encode_www_form_component("#{name}@#{domain}")}&type=refresh&arg="
60
+ resp = Http.post(BASE_URL + "/", headers: HEADERS, body: body, timeout: 15)
61
+ resp.raise_for_status
62
+ data = JSON.parse(resp.body)
63
+ return [] unless data["status"] == 1 && data["data"].is_a?(Array) && !data["data"].empty?
64
+
65
+ list = data["data"][0]["list"]
66
+ return [] unless list.is_a?(Array)
67
+
68
+ list.map do |item|
69
+ flat = {
70
+ "id" => item["MID"],
71
+ "from" => item["FROM"],
72
+ "to" => addr,
73
+ "subject" => item["SUBJECT"],
74
+ "body" => item["CONTENT"],
75
+ "date" => item["TIME"],
76
+ "isRead" => false
77
+ }
78
+ Normalize.normalize_email(flat, addr)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "uri"
5
+ require "cgi"
6
+
7
+ module TempmailSdk
8
+ module Providers
9
+ # vip.215.im 渠道实现
10
+ # 流程:GET / 取首页 cookie → POST /api/temp-inbox 创建邮箱(得到 address + token)
11
+ # GET /v1/messages 拉取邮件列表(HTTP 优先)
12
+ # GET /v1/messages/{id} 补拉单封详情
13
+ # token 为 JWT,用于后续 API 鉴权
14
+ module Vip215
15
+ CHANNEL = "vip-215"
16
+ BASE = "https://vip.215.im"
17
+ UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
18
+ "(KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36 Edg/148.0.0.0"
19
+
20
+ HOME_HEADERS = {
21
+ "User-Agent" => UA,
22
+ "Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
23
+ "Accept-Language" => "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
24
+ "Cache-Control" => "no-cache",
25
+ "DNT" => "1",
26
+ "Pragma" => "no-cache",
27
+ "Sec-Fetch-Dest" => "document",
28
+ "Sec-Fetch-Mode" => "navigate",
29
+ "Sec-Fetch-Site" => "same-origin",
30
+ "Upgrade-Insecure-Requests" => "1"
31
+ }.freeze
32
+
33
+ API_HEADERS = {
34
+ "User-Agent" => UA,
35
+ "Accept" => "*/*",
36
+ "Accept-Language" => "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
37
+ "Cache-Control" => "no-cache",
38
+ "Content-Type" => "application/json",
39
+ "DNT" => "1",
40
+ "Origin" => BASE,
41
+ "Pragma" => "no-cache",
42
+ "Referer" => "#{BASE}/",
43
+ "Sec-Fetch-Dest" => "empty",
44
+ "Sec-Fetch-Mode" => "cors",
45
+ "Sec-Fetch-Site" => "same-origin",
46
+ "X-Locale" => "zh"
47
+ }.freeze
48
+
49
+ module_function
50
+
51
+ # 合并 Set-Cookie 响应头到 cookie 字符串
52
+ def merge_cookies(existing, set_cookie_lines)
53
+ map = {}
54
+ existing.to_s.split(";").each do |part|
55
+ part = part.strip
56
+ next unless part.include?("=")
57
+
58
+ k, v = part.split("=", 2)
59
+ map[k.strip] = v.to_s.strip unless k.strip.empty?
60
+ end
61
+ set_cookie_lines.each do |line|
62
+ pair = line.split(";", 2).first.to_s.strip
63
+ next unless pair.include?("=")
64
+
65
+ k, v = pair.split("=", 2)
66
+ map[k.strip] = v.to_s.strip unless k.strip.empty?
67
+ end
68
+ map.map { |k, v| "#{k}=#{v}" }.join("; ")
69
+ end
70
+
71
+ # 访问首页获取必要 cookie(yyds_homepage_bridge / yyds_homepage_device)
72
+ def establish_session
73
+ resp = Http.get(BASE + "/", headers: HOME_HEADERS, timeout: 15)
74
+ resp.raise_for_status
75
+ cookie = merge_cookies("", resp.set_cookies)
76
+ raise "vip-215: 缺少首页 cookie" unless cookie.include?("yyds_homepage_bridge=") &&
77
+ cookie.include?("yyds_homepage_device=")
78
+
79
+ cookie
80
+ end
81
+
82
+ # 创建 vip-215 临时邮箱
83
+ # @return [EmailInfo]
84
+ def generate_email
85
+ cookie = establish_session
86
+ resp = Http.post(
87
+ BASE + "/api/temp-inbox",
88
+ headers: API_HEADERS.merge("Cookie" => cookie),
89
+ body: "",
90
+ timeout: 15
91
+ )
92
+ resp.raise_for_status
93
+ data = JSON.parse(resp.body)
94
+ raise "vip-215: 创建失败" unless data["success"] && data["data"]
95
+
96
+ address = data["data"]["address"].to_s.strip
97
+ token = data["data"]["token"].to_s.strip
98
+ raise "vip-215: 响应缺少 address 或 token" if address.empty? || token.empty?
99
+
100
+ EmailInfo.new(channel: CHANNEL, email: address, token: token)
101
+ end
102
+
103
+ # 判断邮件条目是否已含真实正文
104
+ def has_real_body?(row)
105
+ %w[text body_text html body_html content body].any? do |key|
106
+ v = row[key]
107
+ v.is_a?(String) && !v.strip.empty?
108
+ end
109
+ end
110
+
111
+ # 提取邮件 ID
112
+ def extract_message_id(row)
113
+ %w[id messageId message_id].each do |key|
114
+ v = row[key]
115
+ next if v.nil?
116
+ return v.to_s.strip if v.is_a?(String) && !v.strip.empty?
117
+ return v.to_i.to_s if v.is_a?(Numeric)
118
+ end
119
+ ""
120
+ end
121
+
122
+ # 补拉单封邮件详情
123
+ def fetch_message_detail(token, id)
124
+ mid = id.to_s.strip
125
+ return nil if mid.empty?
126
+
127
+ resp = Http.get(
128
+ "#{BASE}/v1/messages/#{URI.encode_www_form_component(mid)}",
129
+ headers: API_HEADERS.merge("Authorization" => "Bearer #{token}"),
130
+ timeout: 15
131
+ )
132
+ return nil unless resp.status_code == 200
133
+
134
+ parsed = JSON.parse(resp.body)
135
+ return nil unless parsed["success"] && parsed["data"].is_a?(Hash)
136
+
137
+ parsed["data"]
138
+ rescue StandardError
139
+ nil
140
+ end
141
+
142
+ # 获取 vip-215 邮件列表(HTTP GET /v1/messages)
143
+ # @param token [String] JWT
144
+ # @param email [String]
145
+ # @return [Array<Email>]
146
+ def get_emails(token, email)
147
+ raise "vip-215: token 为空" if token.to_s.strip.empty?
148
+
149
+ resp = Http.get(
150
+ BASE + "/v1/messages",
151
+ headers: API_HEADERS.merge("Authorization" => "Bearer #{token}"),
152
+ timeout: 15
153
+ )
154
+ resp.raise_for_status
155
+ parsed = JSON.parse(resp.body)
156
+ raise "vip-215: messages success=false" unless parsed["success"]
157
+
158
+ messages = parsed.dig("data", "messages") || []
159
+ messages.map do |row|
160
+ id = extract_message_id(row)
161
+ unless has_real_body?(row) || id.empty?
162
+ detail = fetch_message_detail(token, id)
163
+ row = row.merge(detail) if detail
164
+ end
165
+ row["to"] ||= email
166
+ Normalize.normalize_email(row, email)
167
+ end
168
+ end
169
+ end
170
+ end
171
+ 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