Module: TempmailSdk::Providers::Ockito
- Defined in:
- lib/tempmail_sdk/providers/ockito.rb
Overview
ockito 渠道实现 API: https://ockito.com/web-api 流程: 获取 gtoken -> 获取邮箱 -> 用 Bearer token 收信
Constant Summary collapse
- CHANNEL =
"ockito"- BASE_URL =
"https://ockito.com/web-api"- DEFAULT_HEADERS =
{ "Accept" => "application/json", "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" }.freeze
Class Method Summary collapse
-
.fetch_bearer_json(path, access_token, refresh_token) ⇒ Object
带 Bearer 认证的请求(401 时自动刷新重试).
-
.fetch_json(path, method: :get, headers: nil, payload: nil) ⇒ Object
请求并解析 JSON.
-
.flatten_inbox_row(raw, recipient) ⇒ Object
扁平化收件箱行.
-
.flatten_message(raw, recipient) ⇒ Object
扁平化邮件详情.
-
.generate_email ⇒ EmailInfo
创建临时邮箱.
-
.get_emails(token, email) ⇒ Array<Email>
获取邮件列表.
-
.pack_token(access_token, refresh_token) ⇒ Object
打包 token.
-
.refresh_access_token(refresh_token) ⇒ Object
刷新 access token.
-
.unpack_token(token) ⇒ Object
解包 token.
Class Method Details
.fetch_bearer_json(path, access_token, refresh_token) ⇒ Object
带 Bearer 认证的请求(401 时自动刷新重试)
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 70 def fetch_bearer_json(path, access_token, refresh_token) _, data = fetch_json(path, headers: { "Authorization" => "Bearer #{access_token}" }) data rescue RuntimeError => e raise unless e..include?("401") refreshed = refresh_access_token(refresh_token) _, data = fetch_json(path, headers: { "Authorization" => "Bearer #{refreshed}" }) data end |
.fetch_json(path, method: :get, headers: nil, payload: nil) ⇒ Object
请求并解析 JSON
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 22 def fetch_json(path, method: :get, headers: nil, payload: nil) request_headers = DEFAULT_HEADERS.dup request_headers.merge!(headers) if headers resp = if method == :post Http.post("#{BASE_URL}#{path}", headers: request_headers, json: payload || {}) else Http.get("#{BASE_URL}#{path}", headers: request_headers) end text = resp.body || "" data = text.empty? ? {} : JSON.parse(text) raise "ockito http #{resp.status_code}" unless resp.ok? [resp.status_code, data.is_a?(Hash) ? data : {}] end |
.flatten_inbox_row(raw, recipient) ⇒ Object
扁平化收件箱行
82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 82 def flatten_inbox_row(raw, recipient) { "id" => (raw["uid"] || "").to_s, "from" => (raw["sender"] || "").to_s, "to" => recipient, "subject" => (raw["subject"] || "").to_s, "text" => (raw["snippet"] || "").to_s, "html" => (raw["html"] || "").to_s, "date" => (raw["timestamp"] || "").to_s, "is_read" => false, "attachments" => [] } end |
.flatten_message(raw, recipient) ⇒ Object
扁平化邮件详情
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 97 def (raw, recipient) obj = raw["obj"].is_a?(Hash) ? raw["obj"] : raw { "id" => (raw["uid"] || "").to_s, "from" => (obj["sender_email"] || obj["SenderEmail"] || obj["from_"] || obj["From"] || obj["from"] || obj["sender_name"] || obj["SenderName"] || "").to_s, "to" => (obj["to"] || obj["To"] || recipient).to_s, "subject" => (obj["subject"] || obj["Subject"] || "").to_s, "text" => (obj["text"] || "").to_s, "html" => (obj["html"] || "").to_s, "date" => (obj["date"] || obj["Date"] || "").to_s, "is_read" => false, "attachments" => [] } end |
.generate_email ⇒ EmailInfo
创建临时邮箱
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 114 def generate_email _, login = fetch_json("/gtoken", method: :post, payload: {}) access_token = login["access_token"].to_s.strip refresh_token = login["refresh_token"].to_s.strip raise "ockito: 无效的 token 响应" if access_token.empty? || refresh_token.empty? _, email_data = fetch_json("/email", headers: { "Authorization" => "Bearer #{access_token}" }) email_value = email_data["email"] email = if email_value.is_a?(String) email_value.strip elsif email_value.is_a?(Hash) (email_value["email"] || "").to_s.strip else "" end raise "ockito: 无效的邮箱响应" if email.empty? || !email.include?("@") EmailInfo.new(channel: CHANNEL, email: email, token: pack_token(access_token, refresh_token)) end |
.get_emails(token, email) ⇒ Array<Email>
获取邮件列表
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 138 def get_emails(token, email) access_token, refresh_token = unpack_token(token) address = email.to_s.strip raise "ockito: 邮箱地址为空" if address.empty? data = fetch_bearer_json("/retrieve/#{URI.encode_www_form_component(address)}/emails", access_token, refresh_token) rows = data["inbox"] return [] unless rows.is_a?(Array) rows.select { |row| row.is_a?(Hash) }.map do |row| uid = row["uid"].to_s.strip if uid.empty? Normalize.normalize_email(flatten_inbox_row(row, address), address) else begin detail = fetch_bearer_json("/retrieve/#{URI.encode_www_form_component(address)}/#{URI.encode_www_form_component(uid)}", access_token, refresh_token) Normalize.normalize_email((detail, address), address) rescue StandardError Normalize.normalize_email(flatten_inbox_row(row, address), address) end end end end |
.pack_token(access_token, refresh_token) ⇒ Object
打包 token
40 41 42 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 40 def pack_token(access_token, refresh_token) JSON.generate({ "access_token" => access_token, "refresh_token" => refresh_token }) end |
.refresh_access_token(refresh_token) ⇒ Object
刷新 access token
60 61 62 63 64 65 66 67 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 60 def refresh_access_token(refresh_token) _, data = fetch_json("/grefresh", method: :post, headers: { "Authorization" => "Bearer #{refresh_token}", "X-PASSTHROUGH" => "Y" }) access = data["access_token"].to_s.strip raise "ockito: 刷新 token 失败" if access.empty? access end |
.unpack_token(token) ⇒ Object
解包 token
45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/tempmail_sdk/providers/ockito.rb', line 45 def unpack_token(token) value = token.to_s.strip raise "ockito: 无效的会话 token" if value.empty? || !value.start_with?("{") data = JSON.parse(value) raise "ockito: 无效的会话 token" unless data.is_a?(Hash) access = data["access_token"].to_s.strip refresh = data["refresh_token"].to_s.strip raise "ockito: 无效的会话 token" if access.empty? || refresh.empty? [access, refresh] end |