mailfloss 0.1.0
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 +7 -0
- data/CHANGELOG.md +19 -0
- data/LICENSE +21 -0
- data/README.md +203 -0
- data/lib/mailfloss/client.rb +209 -0
- data/lib/mailfloss/errors.rb +64 -0
- data/lib/mailfloss/resources.rb +294 -0
- data/lib/mailfloss/transport.rb +73 -0
- data/lib/mailfloss/version.rb +5 -0
- data/lib/mailfloss.rb +14 -0
- data/sig/mailfloss.rbs +77 -0
- data/sig/resources.rbs +85 -0
- data/sig/types.rbs +266 -0
- metadata +62 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailfloss
|
|
4
|
+
module Resources
|
|
5
|
+
# @api private
|
|
6
|
+
class Base
|
|
7
|
+
def initialize(client)
|
|
8
|
+
@client = client
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
attr_reader :client
|
|
14
|
+
|
|
15
|
+
def encode(segment)
|
|
16
|
+
URI.encode_www_form_component(segment.to_s)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# POST /batch-verify and its sub-resources.
|
|
21
|
+
class BatchVerify < Base
|
|
22
|
+
# POST /batch-verify — submit a batch of emails for verification.
|
|
23
|
+
#
|
|
24
|
+
# @param emails [Array<String>]
|
|
25
|
+
# @param webhook_url [String, nil] optional completion callback URL
|
|
26
|
+
# @param idempotency_key [String, nil] auto-generated when omitted
|
|
27
|
+
# @return [Hash] { id: } — the created batch job id
|
|
28
|
+
def create(emails:, webhook_url: nil, idempotency_key: nil)
|
|
29
|
+
body = { emails: emails }
|
|
30
|
+
body[:webhook_url] = webhook_url if webhook_url
|
|
31
|
+
client.request(:post, "/batch-verify", body: body, idempotency_key: idempotency_key)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# GET /batch-verify/{id}/status
|
|
35
|
+
#
|
|
36
|
+
# @return [Hash] { status:, progress: }
|
|
37
|
+
def status(id)
|
|
38
|
+
client.request(:get, "/batch-verify/#{encode(id)}/status")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# GET /batch-verify/{id}/results
|
|
42
|
+
#
|
|
43
|
+
# @param per_page [Integer, nil]
|
|
44
|
+
# @param next_cursor [String, nil] the `next` query param
|
|
45
|
+
# @return [Hash] { id:, results: [...] }
|
|
46
|
+
def results(id, per_page: nil, next_cursor: nil)
|
|
47
|
+
client.request(:get, "/batch-verify/#{encode(id)}/results",
|
|
48
|
+
query: { per_page: per_page, next: next_cursor })
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# POST /batch-verify/{id}/cancel
|
|
52
|
+
#
|
|
53
|
+
# @return [Hash] { success: }
|
|
54
|
+
def cancel(id, idempotency_key: nil)
|
|
55
|
+
client.request(:post, "/batch-verify/#{encode(id)}/cancel", idempotency_key: idempotency_key)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# GET /jobs
|
|
60
|
+
class Jobs < Base
|
|
61
|
+
# GET /jobs — cursor-paginated job history.
|
|
62
|
+
#
|
|
63
|
+
# @param per_page [Integer, nil]
|
|
64
|
+
# @param cursor [String, nil]
|
|
65
|
+
# @param source [String, nil] api|csv|zapier|widget|input|integration
|
|
66
|
+
# @param status [String, nil] queued|processing|completed|cancelled
|
|
67
|
+
# @return [Hash] { data: [Job], pagination: { next_cursor:, has_more: } }
|
|
68
|
+
def list(per_page: nil, cursor: nil, source: nil, status: nil)
|
|
69
|
+
client.request(:get, "/jobs",
|
|
70
|
+
query: { per_page: per_page, cursor: cursor, source: source, status: status })
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# GET /jobs/{id}
|
|
74
|
+
#
|
|
75
|
+
# @return [Hash] { id:, status:, source:, source_integration:,
|
|
76
|
+
# created_at:, finished_at:, results: }
|
|
77
|
+
def get(id)
|
|
78
|
+
client.request(:get, "/jobs/#{encode(id)}")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# GET /users
|
|
83
|
+
class Users < Base
|
|
84
|
+
# GET /users — organization members.
|
|
85
|
+
#
|
|
86
|
+
# @return [Hash] { data: [User], pagination: { next_cursor:, has_more: } }
|
|
87
|
+
def list(per_page: nil, cursor: nil)
|
|
88
|
+
client.request(:get, "/users", query: { per_page: per_page, cursor: cursor })
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# GET /users/{user_id}
|
|
92
|
+
#
|
|
93
|
+
# @return [Hash] { id:, email:, name:, role:, is_primary:, status:, created_at: }
|
|
94
|
+
def get(user_id)
|
|
95
|
+
client.request(:get, "/users/#{encode(user_id)}")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# GET /reports/*
|
|
100
|
+
class Reports < Base
|
|
101
|
+
# GET /reports/usage — verification usage report.
|
|
102
|
+
#
|
|
103
|
+
# @param period [String, nil] this_week|this_month|this_year|lifetime
|
|
104
|
+
# @param connection_id [String, nil] scope to one ESP connection
|
|
105
|
+
# @return [Hash] { period:, connection_id:, range:, total:, statuses:, reasons: }
|
|
106
|
+
def usage(period: nil, connection_id: nil)
|
|
107
|
+
client.request(:get, "/reports/usage",
|
|
108
|
+
query: { period: period, connection_id: connection_id })
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# GET/PATCH /account
|
|
113
|
+
class Account < Base
|
|
114
|
+
# GET /account — the authenticated account holder.
|
|
115
|
+
def get
|
|
116
|
+
client.request(:get, "/account")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# PATCH /account — update writable account & settings fields.
|
|
120
|
+
# Only the provided keys are sent.
|
|
121
|
+
#
|
|
122
|
+
# @param name [String, nil]
|
|
123
|
+
# @param organization [String, nil]
|
|
124
|
+
# @param phone [String, nil]
|
|
125
|
+
# @param vat_id [String, nil]
|
|
126
|
+
# @param country [String, nil]
|
|
127
|
+
# @param address [Hash, nil] partial { line1:, line2:, city:, state:, postal_code:, country: }
|
|
128
|
+
# @param notifications [Hash, nil] partial { after_flossing:, weekly_report:,
|
|
129
|
+
# monthly_report:, payment_receipts: }
|
|
130
|
+
# @return [Hash] the full updated account (same shape as #get)
|
|
131
|
+
def update(name: :__omit__, organization: :__omit__, phone: :__omit__, vat_id: :__omit__,
|
|
132
|
+
country: :__omit__, address: :__omit__, notifications: :__omit__)
|
|
133
|
+
body = {}
|
|
134
|
+
body[:name] = name unless name == :__omit__
|
|
135
|
+
body[:organization] = organization unless organization == :__omit__
|
|
136
|
+
body[:phone] = phone unless phone == :__omit__
|
|
137
|
+
body[:vat_id] = vat_id unless vat_id == :__omit__
|
|
138
|
+
body[:country] = country unless country == :__omit__
|
|
139
|
+
body[:address] = address unless address == :__omit__
|
|
140
|
+
body[:notifications] = notifications unless notifications == :__omit__
|
|
141
|
+
client.request(:patch, "/account", body: body)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# GET /organization
|
|
146
|
+
class Organization < Base
|
|
147
|
+
# GET /organization — plan, credits, usage, trial and entitlements.
|
|
148
|
+
def get
|
|
149
|
+
client.request(:get, "/organization")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# GET /integrations and nested connections/keywords.
|
|
154
|
+
class Integrations < Base
|
|
155
|
+
# GET /integrations — all supported ESPs with connection state.
|
|
156
|
+
#
|
|
157
|
+
# @return [Hash] { data: [Integration], pagination: { next_cursor:, has_more: } }
|
|
158
|
+
def list(per_page: nil, cursor: nil)
|
|
159
|
+
client.request(:get, "/integrations", query: { per_page: per_page, cursor: cursor })
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# GET /integrations/{type} — detail for a single ESP.
|
|
163
|
+
#
|
|
164
|
+
# @return [Hash] { type:, connected:, connection_count:, connections:,
|
|
165
|
+
# disconnected_connections: }
|
|
166
|
+
def get(type)
|
|
167
|
+
client.request(:get, "/integrations/#{encode(type)}")
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def connections
|
|
171
|
+
@connections ||= Connections.new(client)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def keywords
|
|
175
|
+
@keywords ||= Keywords.new(client)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# /integrations/{type}/connections/*
|
|
180
|
+
class Connections < Base
|
|
181
|
+
# POST /integrations/{type}/connections — connect an ESP account.
|
|
182
|
+
#
|
|
183
|
+
# @param type [String] ESP slug (e.g. "klaviyo")
|
|
184
|
+
# @param credentials [Hash] per-ESP credential shape (e.g. { api_key: "..." })
|
|
185
|
+
# @param name [String, nil] optional display name
|
|
186
|
+
# @return [Hash] the created connection { id:, name:, status:, created_at:,
|
|
187
|
+
# last_synced_at:, settings: }
|
|
188
|
+
def create(type, credentials:, name: nil, idempotency_key: nil)
|
|
189
|
+
body = { credentials: credentials }
|
|
190
|
+
body[:name] = name if name
|
|
191
|
+
client.request(:post, "/integrations/#{encode(type)}/connections",
|
|
192
|
+
body: body, idempotency_key: idempotency_key)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# GET /integrations/{type}/connections/{id}
|
|
196
|
+
def get(type, id)
|
|
197
|
+
client.request(:get, "/integrations/#{encode(type)}/connections/#{encode(id)}")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# PATCH /integrations/{type}/connections/{id} — update floss settings.
|
|
201
|
+
#
|
|
202
|
+
# @param aggressiveness [String, nil] normal|aggressive|custom
|
|
203
|
+
# @param manual_mode [Boolean, nil]
|
|
204
|
+
# @param autofloss [Boolean, nil]
|
|
205
|
+
# @param decay_protection [Boolean, nil]
|
|
206
|
+
# @param action [String, nil] unsubscribe|delete|update_tags|update_custom_fields|do_nothing
|
|
207
|
+
# @param checks [Hash, nil] partial map of the 12 check gates
|
|
208
|
+
# @return [Hash] the updated connection
|
|
209
|
+
def update(type, id, aggressiveness: nil, manual_mode: nil, autofloss: nil,
|
|
210
|
+
decay_protection: nil, action: nil, checks: nil)
|
|
211
|
+
body = {}
|
|
212
|
+
body[:aggressiveness] = aggressiveness unless aggressiveness.nil?
|
|
213
|
+
body[:manual_mode] = manual_mode unless manual_mode.nil?
|
|
214
|
+
body[:autofloss] = autofloss unless autofloss.nil?
|
|
215
|
+
body[:decay_protection] = decay_protection unless decay_protection.nil?
|
|
216
|
+
body[:action] = action unless action.nil?
|
|
217
|
+
body[:checks] = checks unless checks.nil?
|
|
218
|
+
client.request(:patch, "/integrations/#{encode(type)}/connections/#{encode(id)}", body: body)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# DELETE /integrations/{type}/connections/{id} — disconnect (soft-disable).
|
|
222
|
+
#
|
|
223
|
+
# @return [Hash] { id:, type:, status:, disconnected_at: }
|
|
224
|
+
def delete(type, id)
|
|
225
|
+
client.request(:delete, "/integrations/#{encode(type)}/connections/#{encode(id)}")
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# POST /integrations/{type}/connections/{id}/sync — trigger a sync.
|
|
229
|
+
#
|
|
230
|
+
# @return [Hash] the connection after the sync was queued
|
|
231
|
+
def sync(type, id, idempotency_key: nil)
|
|
232
|
+
client.request(:post, "/integrations/#{encode(type)}/connections/#{encode(id)}/sync",
|
|
233
|
+
idempotency_key: idempotency_key)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# POST /integrations/{type}/connections/{id}/test — test stored credentials.
|
|
237
|
+
#
|
|
238
|
+
# @return [Hash] { id:, type:, credential_valid:, tested_at:, reason: }
|
|
239
|
+
def test(type, id, idempotency_key: nil)
|
|
240
|
+
client.request(:post, "/integrations/#{encode(type)}/connections/#{encode(id)}/test",
|
|
241
|
+
idempotency_key: idempotency_key)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# /integrations/{type}/connections/{id}/keywords/{list}*
|
|
246
|
+
class Keywords < Base
|
|
247
|
+
# GET .../keywords/{list} — list keyword rules (blacklist or whitelist).
|
|
248
|
+
#
|
|
249
|
+
# @param list [String] "blacklist" or "whitelist"
|
|
250
|
+
# @return [Hash] { data: [Rule], pagination: { next_cursor:, has_more: } }
|
|
251
|
+
def list(type, id, list, per_page: nil, cursor: nil)
|
|
252
|
+
client.request(:get, keywords_path(type, id, list),
|
|
253
|
+
query: { per_page: per_page, cursor: cursor })
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# POST .../keywords/{list} — add keyword rules (1-1000, all-or-nothing).
|
|
257
|
+
#
|
|
258
|
+
# @param rules [Array<Hash>] each { keyword:, match: "exact"|"contains",
|
|
259
|
+
# applies_to: { localpart:, domain:, email: } }
|
|
260
|
+
# @return [Hash] { data: [Rule] } — the created rules with ids
|
|
261
|
+
def add(type, id, list, rules:, idempotency_key: nil)
|
|
262
|
+
client.request(:post, keywords_path(type, id, list),
|
|
263
|
+
body: { rules: rules }, idempotency_key: idempotency_key)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# DELETE .../keywords/{list}/{ruleId} — remove a keyword rule.
|
|
267
|
+
#
|
|
268
|
+
# @return [Hash] { deleted:, id: }
|
|
269
|
+
def delete(type, id, list, rule_id)
|
|
270
|
+
client.request(:delete, "#{keywords_path(type, id, list)}/#{encode(rule_id)}")
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
private
|
|
274
|
+
|
|
275
|
+
def keywords_path(type, id, list)
|
|
276
|
+
"/integrations/#{encode(type)}/connections/#{encode(id)}/keywords/#{encode(list)}"
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# POST /erasures
|
|
281
|
+
class Erasures < Base
|
|
282
|
+
# POST /erasures — GDPR/CCPA delete-my-data requests.
|
|
283
|
+
#
|
|
284
|
+
# @param emails [Array<String>] addresses to erase
|
|
285
|
+
# @param webhook_url [String, nil] optional completion callback URL
|
|
286
|
+
# @return [Hash] { success: }
|
|
287
|
+
def create(emails:, webhook_url: nil, idempotency_key: nil)
|
|
288
|
+
body = { emails: emails }
|
|
289
|
+
body[:webhook_url] = webhook_url if webhook_url
|
|
290
|
+
client.request(:post, "/erasures", body: body, idempotency_key: idempotency_key)
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "uri"
|
|
5
|
+
|
|
6
|
+
module Mailfloss
|
|
7
|
+
# Low-level HTTP transport. Any object that responds to
|
|
8
|
+
# +call(method, url, headers, body)+ and returns an object with
|
|
9
|
+
# +status+, +headers+ and +body+ (or an equivalent Hash) can be injected
|
|
10
|
+
# into Mailfloss::Client via the +transport:+ kwarg — this is the seam
|
|
11
|
+
# used by the test suite.
|
|
12
|
+
class Transport
|
|
13
|
+
Response = Struct.new(:status, :headers, :body)
|
|
14
|
+
|
|
15
|
+
# Errors considered transient connection failures (retried by the client).
|
|
16
|
+
CONNECTION_ERRORS = [
|
|
17
|
+
Errno::ECONNREFUSED,
|
|
18
|
+
Errno::ECONNRESET,
|
|
19
|
+
Errno::EHOSTUNREACH,
|
|
20
|
+
Errno::ETIMEDOUT,
|
|
21
|
+
Errno::EPIPE,
|
|
22
|
+
SocketError,
|
|
23
|
+
EOFError,
|
|
24
|
+
Net::OpenTimeout,
|
|
25
|
+
Net::ReadTimeout,
|
|
26
|
+
OpenSSL::SSL::SSLError
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
def initialize(timeout: 30)
|
|
30
|
+
@timeout = timeout
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param method [Symbol] :get, :post, :patch, :delete
|
|
34
|
+
# @param url [String] absolute URL (query string already appended)
|
|
35
|
+
# @param headers [Hash{String => String}]
|
|
36
|
+
# @param body [String, nil] already-serialized request body
|
|
37
|
+
# @return [Response]
|
|
38
|
+
def call(method, url, headers, body)
|
|
39
|
+
uri = URI.parse(url)
|
|
40
|
+
request = build_request(method, uri, headers, body)
|
|
41
|
+
|
|
42
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
43
|
+
http.use_ssl = uri.scheme == "https"
|
|
44
|
+
http.open_timeout = @timeout
|
|
45
|
+
http.read_timeout = @timeout
|
|
46
|
+
http.write_timeout = @timeout if http.respond_to?(:write_timeout=)
|
|
47
|
+
|
|
48
|
+
response = http.start { |conn| conn.request(request) }
|
|
49
|
+
|
|
50
|
+
response_headers = {}
|
|
51
|
+
response.each_header { |key, value| response_headers[key.downcase] = value }
|
|
52
|
+
|
|
53
|
+
Response.new(response.code.to_i, response_headers, response.body)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def build_request(method, uri, headers, body)
|
|
59
|
+
klass = case method
|
|
60
|
+
when :get then Net::HTTP::Get
|
|
61
|
+
when :post then Net::HTTP::Post
|
|
62
|
+
when :patch then Net::HTTP::Patch
|
|
63
|
+
when :delete then Net::HTTP::Delete
|
|
64
|
+
else
|
|
65
|
+
raise ArgumentError, "Unsupported HTTP method: #{method.inspect}"
|
|
66
|
+
end
|
|
67
|
+
request = klass.new(uri.request_uri)
|
|
68
|
+
headers.each { |key, value| request[key] = value }
|
|
69
|
+
request.body = body if body
|
|
70
|
+
request
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/mailfloss.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
require_relative "mailfloss/version"
|
|
6
|
+
require_relative "mailfloss/errors"
|
|
7
|
+
require_relative "mailfloss/transport"
|
|
8
|
+
require_relative "mailfloss/resources"
|
|
9
|
+
require_relative "mailfloss/client"
|
|
10
|
+
|
|
11
|
+
# Official Ruby SDK for the mailfloss email verification API.
|
|
12
|
+
# https://developers.mailfloss.com
|
|
13
|
+
module Mailfloss
|
|
14
|
+
end
|
data/sig/mailfloss.rbs
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module Mailfloss
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
class Error < StandardError
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class ConfigurationError < Error
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class APIError < Error
|
|
11
|
+
attr_reader status: Integer
|
|
12
|
+
attr_reader code: String
|
|
13
|
+
attr_reader type: String?
|
|
14
|
+
attr_reader request_id: String?
|
|
15
|
+
|
|
16
|
+
def initialize: (status: Integer, ?body: String?) -> void
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Transport
|
|
20
|
+
class Response < Struct[untyped]
|
|
21
|
+
attr_accessor status: Integer
|
|
22
|
+
attr_accessor headers: Hash[String, String]
|
|
23
|
+
attr_accessor body: String?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
CONNECTION_ERRORS: Array[Class]
|
|
27
|
+
|
|
28
|
+
def initialize: (?timeout: Numeric) -> void
|
|
29
|
+
|
|
30
|
+
def call: (Symbol method, String url, Hash[String, String] headers, String? body) -> Response
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Duck type for injectable transports: anything with
|
|
34
|
+
# call(method, url, headers, body) returning status/headers/body.
|
|
35
|
+
interface _Transport
|
|
36
|
+
def call: (Symbol method, String url, Hash[String, String] headers, String? body) -> untyped
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
interface _Sleeper
|
|
40
|
+
def call: (Numeric seconds) -> void
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class Client
|
|
44
|
+
DEFAULT_BASE_URL: String
|
|
45
|
+
DEFAULT_MAX_RETRIES: Integer
|
|
46
|
+
DEFAULT_TIMEOUT: Integer
|
|
47
|
+
RETRY_BASE_DELAY: Float
|
|
48
|
+
RETRY_MAX_DELAY: Float
|
|
49
|
+
USER_AGENT: String
|
|
50
|
+
|
|
51
|
+
attr_reader base_url: String
|
|
52
|
+
attr_reader max_retries: Integer
|
|
53
|
+
attr_reader timeout: Numeric
|
|
54
|
+
|
|
55
|
+
def initialize: (?api_key: String?, ?base_url: String, ?max_retries: Integer,
|
|
56
|
+
?timeout: Numeric, ?transport: _Transport?, ?sleeper: _Sleeper?) -> void
|
|
57
|
+
|
|
58
|
+
# GET /verify
|
|
59
|
+
def verify: (email: String, ?timeout: (Numeric | String)?) -> Types::verify_result
|
|
60
|
+
|
|
61
|
+
# GET /check-key
|
|
62
|
+
def check_key: (?api_key: String?, ?public_key: String?, ?check_plan: boolish?,
|
|
63
|
+
?get_token: boolish?, ?check_credits: boolish?) -> Types::check_key_result
|
|
64
|
+
|
|
65
|
+
def batch_verify: () -> Resources::BatchVerify
|
|
66
|
+
def jobs: () -> Resources::Jobs
|
|
67
|
+
def users: () -> Resources::Users
|
|
68
|
+
def reports: () -> Resources::Reports
|
|
69
|
+
def account: () -> Resources::Account
|
|
70
|
+
def organization: () -> Resources::Organization
|
|
71
|
+
def integrations: () -> Resources::Integrations
|
|
72
|
+
def erasures: () -> Resources::Erasures
|
|
73
|
+
|
|
74
|
+
def request: (Symbol method, String path, ?query: Hash[Symbol, untyped]?,
|
|
75
|
+
?body: Hash[Symbol, untyped]?, ?idempotency_key: String?) -> untyped
|
|
76
|
+
end
|
|
77
|
+
end
|
data/sig/resources.rbs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Mailfloss
|
|
2
|
+
module Resources
|
|
3
|
+
class Base
|
|
4
|
+
def initialize: (Client client) -> void
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
attr_reader client: Client
|
|
9
|
+
|
|
10
|
+
def encode: (untyped segment) -> String
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class BatchVerify < Base
|
|
14
|
+
def create: (emails: Array[String], ?webhook_url: String?,
|
|
15
|
+
?idempotency_key: String?) -> Types::batch_create_result
|
|
16
|
+
def status: (String id) -> Types::batch_status_result
|
|
17
|
+
def results: (String id, ?per_page: Integer?, ?next_cursor: String?) -> Types::batch_results_result
|
|
18
|
+
def cancel: (String id, ?idempotency_key: String?) -> Types::batch_cancel_result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Jobs < Base
|
|
22
|
+
def list: (?per_page: Integer?, ?cursor: String?, ?source: String?,
|
|
23
|
+
?status: String?) -> Types::jobs_list
|
|
24
|
+
def get: (String id) -> Types::job
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Users < Base
|
|
28
|
+
def list: (?per_page: Integer?, ?cursor: String?) -> Types::users_list
|
|
29
|
+
def get: (String user_id) -> Types::user
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Reports < Base
|
|
33
|
+
def usage: (?period: String?, ?connection_id: String?) -> Types::usage_report
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class Account < Base
|
|
37
|
+
def get: () -> Types::account
|
|
38
|
+
def update: (?name: String?, ?organization: String?, ?phone: String?,
|
|
39
|
+
?vat_id: String?, ?country: String?,
|
|
40
|
+
?address: Hash[Symbol, String?]?,
|
|
41
|
+
?notifications: Hash[Symbol, bool]?) -> Types::account
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Organization < Base
|
|
45
|
+
def get: () -> Types::organization
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Integrations < Base
|
|
49
|
+
def list: (?per_page: Integer?, ?cursor: String?) -> Types::integrations_list
|
|
50
|
+
def get: (String type) -> Types::integration_detail
|
|
51
|
+
def connections: () -> Connections
|
|
52
|
+
def keywords: () -> Keywords
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Connections < Base
|
|
56
|
+
def create: (String type, credentials: Hash[Symbol, String], ?name: String?,
|
|
57
|
+
?idempotency_key: String?) -> Types::connection
|
|
58
|
+
def get: (String type, String id) -> Types::connection
|
|
59
|
+
def update: (String type, String id, ?aggressiveness: String?,
|
|
60
|
+
?manual_mode: bool?, ?autofloss: bool?, ?decay_protection: bool?,
|
|
61
|
+
?action: String?, ?checks: Hash[Symbol, bool]?) -> Types::connection
|
|
62
|
+
def delete: (String type, String id) -> Types::disconnect_result
|
|
63
|
+
def sync: (String type, String id, ?idempotency_key: String?) -> Types::connection
|
|
64
|
+
def test: (String type, String id, ?idempotency_key: String?) -> Types::credential_test_result
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class Keywords < Base
|
|
68
|
+
def list: (String type, String id, String list, ?per_page: Integer?,
|
|
69
|
+
?cursor: String?) -> Types::keyword_rules_list
|
|
70
|
+
def add: (String type, String id, String list,
|
|
71
|
+
rules: Array[Types::keyword_rule_input],
|
|
72
|
+
?idempotency_key: String?) -> Types::keyword_rules_created
|
|
73
|
+
def delete: (String type, String id, String list, String rule_id) -> Types::keyword_rule_deleted
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def keywords_path: (String type, String id, String list) -> String
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class Erasures < Base
|
|
81
|
+
def create: (emails: Array[String], ?webhook_url: String?,
|
|
82
|
+
?idempotency_key: String?) -> Types::erasure_result
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|