paubox 0.3.2 → 1.0.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 +4 -4
- data/.github/scripts/assert_specs_ran.rb +40 -0
- data/.github/workflows/ci.yml +40 -0
- data/.github/workflows/pr-title.yml +36 -0
- data/.github/workflows/release-please.yml +88 -0
- data/.gitignore +4 -1
- data/.release-please-manifest.json +3 -0
- data/CHANGELOG.md +74 -0
- data/CLAUDE.md +114 -0
- data/README.md +255 -12
- data/api.md +283 -0
- data/lib/paubox/client.rb +15 -5
- data/lib/paubox/dynamic_templates.rb +58 -0
- data/lib/paubox/form.rb +51 -0
- data/lib/paubox/form_submission.rb +34 -0
- data/lib/paubox/forms_client.rb +211 -0
- data/lib/paubox/version.rb +1 -1
- data/lib/paubox.rb +10 -2
- data/paubox_ruby.gemspec +4 -0
- data/release-please-config.json +14 -0
- metadata +44 -7
- data/.travis.yml +0 -5
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paubox
|
|
4
|
+
class DynamicTemplates
|
|
5
|
+
|
|
6
|
+
attr_accessor :id, :name, :api_customer_id, :body
|
|
7
|
+
|
|
8
|
+
def initialize(args = {})
|
|
9
|
+
@id = args['id']
|
|
10
|
+
@name = args['name']
|
|
11
|
+
@api_customer_id = args['api_customer_id']
|
|
12
|
+
@body = args['body']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def update(template_file_path, template_name = nil)
|
|
16
|
+
path = "dynamic_templates/#{id}"
|
|
17
|
+
payload = {
|
|
18
|
+
data: {
|
|
19
|
+
name: template_name,
|
|
20
|
+
body: File.new(template_file_path)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Paubox::Client.new.send_request(method: :patch, payload: payload, path: path)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def delete
|
|
28
|
+
path = "dynamic_templates/#{id}"
|
|
29
|
+
Paubox::Client.new.send_request(method: :delete, path: path)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
def create(template_name, template_file_path)
|
|
34
|
+
path = "dynamic_templates"
|
|
35
|
+
payload = {
|
|
36
|
+
data: {
|
|
37
|
+
name: template_name,
|
|
38
|
+
body: File.new(template_file_path)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
Paubox::Client.new.send_request(method: :post, payload: payload, path: path)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def find(template_id)
|
|
45
|
+
path = "dynamic_templates/#{template_id.to_s}"
|
|
46
|
+
response = Paubox::Client.new.send_request(method: :get, path: path)
|
|
47
|
+
data = JSON.parse(response.body)
|
|
48
|
+
Paubox::DynamicTemplates.new(data)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def list
|
|
52
|
+
path = "dynamic_templates"
|
|
53
|
+
response = Paubox::Client.new.send_request(method: :get, path: path)
|
|
54
|
+
JSON.parse(response.body)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/paubox/form.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paubox
|
|
4
|
+
class Form
|
|
5
|
+
attr_reader :id, :title, :description, :form_html, :form_json, :form_css,
|
|
6
|
+
:vanity_url, :version, :active, :customer_id, :signable,
|
|
7
|
+
:signature_confirmation_label, :submission_count, :type,
|
|
8
|
+
:deleted, :archived, :created_at, :updated_at,
|
|
9
|
+
:recipient, :subscription_list_id, :old_form_id
|
|
10
|
+
|
|
11
|
+
def initialize(args = {})
|
|
12
|
+
@id = args['id']
|
|
13
|
+
@title = args['title']
|
|
14
|
+
@description = args['description']
|
|
15
|
+
@form_html = args['form_html']
|
|
16
|
+
@form_json = args['form_json']
|
|
17
|
+
@form_css = args['form_css']
|
|
18
|
+
@vanity_url = args['vanity_url']
|
|
19
|
+
@version = args['version']
|
|
20
|
+
@active = args['active']
|
|
21
|
+
@customer_id = args['customer_id']
|
|
22
|
+
@signable = args['signable']
|
|
23
|
+
@signature_confirmation_label = args['signature_confirmation_label']
|
|
24
|
+
@submission_count = args['submission_count']
|
|
25
|
+
@type = args['type']
|
|
26
|
+
@deleted = args['deleted']
|
|
27
|
+
@archived = args['archived']
|
|
28
|
+
@created_at = args['created_at']
|
|
29
|
+
@updated_at = args['updated_at']
|
|
30
|
+
@recipient = args['recipient']
|
|
31
|
+
@subscription_list_id = args['subscription_list_id']
|
|
32
|
+
@old_form_id = args['old_form_id']
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def active?
|
|
36
|
+
@active
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def deleted?
|
|
40
|
+
@deleted
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def archived?
|
|
44
|
+
@archived
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def signable?
|
|
48
|
+
@signable
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paubox
|
|
4
|
+
class FormSubmission
|
|
5
|
+
attr_reader :id, :form_id, :form_data, :storage_type, :storage_url,
|
|
6
|
+
:submitter_email, :recipients, :attachment_name,
|
|
7
|
+
:attachment_url, :attachment_type, :created_at
|
|
8
|
+
|
|
9
|
+
def initialize(args = {})
|
|
10
|
+
@id = args['id']
|
|
11
|
+
@form_id = args['form_id']
|
|
12
|
+
@form_data = parse_form_data(args['form_data'])
|
|
13
|
+
@storage_type = args['storage_type']
|
|
14
|
+
@storage_url = args['storage_url']
|
|
15
|
+
@submitter_email = args['submitter_email']
|
|
16
|
+
@recipients = args['recipients']
|
|
17
|
+
@attachment_name = args['attachment_name']
|
|
18
|
+
@attachment_url = args['attachment_url']
|
|
19
|
+
@attachment_type = args['attachment_type']
|
|
20
|
+
@created_at = args['created_at']
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def parse_form_data(form_data)
|
|
26
|
+
return {} if form_data.nil?
|
|
27
|
+
return form_data if form_data.is_a?(Hash)
|
|
28
|
+
|
|
29
|
+
JSON.parse(form_data)
|
|
30
|
+
rescue JSON::ParserError
|
|
31
|
+
{}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cgi'
|
|
4
|
+
require 'rest-client'
|
|
5
|
+
|
|
6
|
+
module Paubox
|
|
7
|
+
class FormsClient
|
|
8
|
+
FORMS_HOST = 'api.paubox.com'
|
|
9
|
+
FORMS_PROTOCOL = 'https://'
|
|
10
|
+
FORMS_BASE = '/forms'
|
|
11
|
+
|
|
12
|
+
TIMEOUT_SECONDS = 30
|
|
13
|
+
|
|
14
|
+
UUID_RE = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i
|
|
15
|
+
|
|
16
|
+
LIST_FORMS_PARAMS = %i[customer_id form_id search order order_by
|
|
17
|
+
archived active page items].freeze
|
|
18
|
+
LIST_SUBMISSIONS_PARAMS = %i[submission_id order_by order page items].freeze
|
|
19
|
+
|
|
20
|
+
# Raised on any non-2xx response from the Forms API. Carries only
|
|
21
|
+
# status_code / url / response_body so error reporters that capture
|
|
22
|
+
# raising-frame locals never see the Authorization header or api_key.
|
|
23
|
+
class Error < StandardError
|
|
24
|
+
attr_reader :status_code, :url, :response_body
|
|
25
|
+
|
|
26
|
+
def initialize(message, status_code: nil, url: nil, response_body: nil)
|
|
27
|
+
super(message)
|
|
28
|
+
@status_code = status_code
|
|
29
|
+
@url = url
|
|
30
|
+
@response_body = response_body
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def initialize(args = {})
|
|
35
|
+
@host = args[:host] || FORMS_HOST
|
|
36
|
+
@protocol = args[:protocol] || FORMS_PROTOCOL
|
|
37
|
+
@base = args[:base] || FORMS_BASE
|
|
38
|
+
@api_key = args[:api_key] ||
|
|
39
|
+
(Paubox.configuration && Paubox.configuration.forms_api_key)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_form(form_id)
|
|
43
|
+
assert_uuid!(form_id, 'form_id')
|
|
44
|
+
url = "#{@protocol}#{@host}#{@base}/public/form_data/#{encode_segment(form_id)}"
|
|
45
|
+
response = request(method: :get, url: url, headers: { accept: :json })
|
|
46
|
+
Paubox::Form.new(JSON.parse(response.body))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def submit_form(form_id, form_data:, attachments: [])
|
|
50
|
+
assert_uuid!(form_id, 'form_id')
|
|
51
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}/submissions"
|
|
52
|
+
payload = { form_data: form_data }
|
|
53
|
+
payload[:attachments] = attachments unless attachments.empty?
|
|
54
|
+
request(method: :post, url: url, payload: payload.to_json,
|
|
55
|
+
headers: { content_type: :json, accept: :json })
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def list_forms(params = {})
|
|
59
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms"
|
|
60
|
+
query = params.transform_keys(&:to_sym)
|
|
61
|
+
.select { |k, _v| LIST_FORMS_PARAMS.include?(k) }
|
|
62
|
+
if query[:customer_id].nil?
|
|
63
|
+
raise ArgumentError, 'customer_id is required for list_forms and must ' \
|
|
64
|
+
"match the API key's customer, e.g. " \
|
|
65
|
+
'client.list_forms(customer_id: 123)'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
response = request(method: :get, url: url,
|
|
69
|
+
headers: auth_headers.merge(params: query))
|
|
70
|
+
body = JSON.parse(response.body)
|
|
71
|
+
forms = (body['results'] || []).map { |form| Paubox::Form.new(form) }
|
|
72
|
+
{ forms: forms, page_info: body['page_info'] }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def create_form(attrs)
|
|
76
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms"
|
|
77
|
+
response = request(method: :post, url: url, payload: attrs.to_json,
|
|
78
|
+
headers: auth_headers.merge(content_type: :json))
|
|
79
|
+
JSON.parse(response.body)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def find_form(form_id)
|
|
83
|
+
assert_uuid!(form_id, 'form_id')
|
|
84
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}"
|
|
85
|
+
response = request(method: :get, url: url, headers: auth_headers)
|
|
86
|
+
Paubox::Form.new(JSON.parse(response.body)['data'])
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def update_form(form_id, attrs)
|
|
90
|
+
assert_uuid!(form_id, 'form_id')
|
|
91
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}"
|
|
92
|
+
response = request(method: :put, url: url, payload: attrs.to_json,
|
|
93
|
+
headers: auth_headers.merge(content_type: :json))
|
|
94
|
+
JSON.parse(response.body)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def archive_form(form_id)
|
|
98
|
+
assert_uuid!(form_id, 'form_id')
|
|
99
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}/archive"
|
|
100
|
+
response = request(method: :post, url: url, payload: '{}',
|
|
101
|
+
headers: auth_headers.merge(content_type: :json))
|
|
102
|
+
JSON.parse(response.body)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def unarchive_form(form_id)
|
|
106
|
+
assert_uuid!(form_id, 'form_id')
|
|
107
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}/unarchive"
|
|
108
|
+
response = request(method: :post, url: url, payload: '{}',
|
|
109
|
+
headers: auth_headers.merge(content_type: :json))
|
|
110
|
+
JSON.parse(response.body)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def copy_form(form_id, title:)
|
|
114
|
+
assert_uuid!(form_id, 'form_id')
|
|
115
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/copy"
|
|
116
|
+
payload = { form_id: form_id, title: title }
|
|
117
|
+
response = request(method: :post, url: url, payload: payload.to_json,
|
|
118
|
+
headers: auth_headers.merge(content_type: :json))
|
|
119
|
+
Paubox::Form.new(JSON.parse(response.body))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def form_stats(customer_id: nil)
|
|
123
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/stats"
|
|
124
|
+
headers = auth_headers
|
|
125
|
+
headers = headers.merge(params: { customer_id: customer_id }) unless customer_id.nil?
|
|
126
|
+
response = request(method: :get, url: url, headers: headers)
|
|
127
|
+
JSON.parse(response.body)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def list_submissions(form_id, params = {})
|
|
131
|
+
assert_uuid!(form_id, 'form_id')
|
|
132
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}/submissions"
|
|
133
|
+
query = params.transform_keys(&:to_sym)
|
|
134
|
+
.select { |k, _v| LIST_SUBMISSIONS_PARAMS.include?(k) }
|
|
135
|
+
response = request(method: :get, url: url,
|
|
136
|
+
headers: auth_headers.merge(params: query))
|
|
137
|
+
body = JSON.parse(response.body)
|
|
138
|
+
submissions = (body['data'] || []).map { |s| Paubox::FormSubmission.new(s) }
|
|
139
|
+
{ submissions: submissions, total: body['total'], page: body['page'],
|
|
140
|
+
items: body['items'] }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def submissions_csv(form_id, submission_id: nil)
|
|
144
|
+
assert_uuid!(form_id, 'form_id')
|
|
145
|
+
base = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}" \
|
|
146
|
+
'/submissions/submission-csv'
|
|
147
|
+
url = if submission_id.nil?
|
|
148
|
+
base
|
|
149
|
+
else
|
|
150
|
+
assert_uuid!(submission_id, 'submission_id')
|
|
151
|
+
"#{base}/#{encode_segment(submission_id)}"
|
|
152
|
+
end
|
|
153
|
+
request(method: :get, url: url, headers: auth_headers(accept: 'text/csv')).body
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def submission_pdf(form_id, submission_id)
|
|
157
|
+
assert_uuid!(form_id, 'form_id')
|
|
158
|
+
assert_uuid!(submission_id, 'submission_id')
|
|
159
|
+
url = "#{@protocol}#{@host}#{@base}/api/forms/#{encode_segment(form_id)}/submissions/" \
|
|
160
|
+
"#{encode_segment(submission_id)}/submission-pdf"
|
|
161
|
+
request(method: :get, url: url, headers: auth_headers(accept: 'application/pdf')).body
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
private
|
|
165
|
+
|
|
166
|
+
def auth_headers(accept: :json)
|
|
167
|
+
if @api_key.nil? || @api_key.to_s.empty?
|
|
168
|
+
raise ArgumentError, "api_key is required for this endpoint. Pass a scoped " \
|
|
169
|
+
"API key with the 'forms' scope: " \
|
|
170
|
+
'Paubox::FormsClient.new(api_key: ...)'
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
{ authorization: "Bearer #{@api_key}", accept: accept }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def assert_uuid!(value, name)
|
|
177
|
+
return if value.is_a?(String) && value.match?(UUID_RE)
|
|
178
|
+
|
|
179
|
+
raise ArgumentError, "#{name} must be a UUID string (received #{value.inspect})"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def encode_segment(value)
|
|
183
|
+
CGI.escape(value.to_s)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Funnels every request through RestClient::Request.execute so we can
|
|
187
|
+
# always set an explicit timeout (rest-client's default is nil) and
|
|
188
|
+
# translate ExceptionWithResponse into Paubox::FormsClient::Error,
|
|
189
|
+
# which carries only status_code / url / response_body — never the
|
|
190
|
+
# Authorization header or api_key. Keeps the Bearer token out of any
|
|
191
|
+
# error reporter that captures raising-frame locals.
|
|
192
|
+
def request(method:, url:, headers: {}, payload: nil)
|
|
193
|
+
RestClient::Request.execute(
|
|
194
|
+
method: method,
|
|
195
|
+
url: url,
|
|
196
|
+
payload: payload,
|
|
197
|
+
headers: headers,
|
|
198
|
+
timeout: TIMEOUT_SECONDS
|
|
199
|
+
)
|
|
200
|
+
rescue RestClient::ExceptionWithResponse => e
|
|
201
|
+
response = e.response
|
|
202
|
+
raise Error.new(
|
|
203
|
+
"Paubox Forms API request failed: #{e.class.name.split('::').last} " \
|
|
204
|
+
"(status #{response && response.code || 'unknown'})",
|
|
205
|
+
status_code: response && response.code,
|
|
206
|
+
url: url,
|
|
207
|
+
response_body: response && response.body
|
|
208
|
+
)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
data/lib/paubox/version.rb
CHANGED
data/lib/paubox.rb
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
require 'paubox/version'
|
|
4
4
|
require 'paubox/client'
|
|
5
|
+
require 'paubox/dynamic_templates'
|
|
5
6
|
require 'paubox/format_helper'
|
|
6
7
|
require 'paubox/mail_to_message'
|
|
7
8
|
require 'paubox/message'
|
|
8
9
|
require 'paubox/templated_message'
|
|
9
10
|
require 'paubox/email_disposition'
|
|
11
|
+
require 'paubox/form'
|
|
12
|
+
require 'paubox/form_submission'
|
|
13
|
+
require 'paubox/forms_client'
|
|
10
14
|
require 'mail/paubox'
|
|
11
15
|
|
|
12
16
|
module Paubox
|
|
@@ -20,6 +24,10 @@ module Paubox
|
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
class Configuration
|
|
23
|
-
attr_accessor :api_key, :
|
|
27
|
+
attr_accessor :api_key, :forms_api_key
|
|
28
|
+
|
|
29
|
+
# Deprecated: api_user is no longer used by the Email API client.
|
|
30
|
+
# Kept only for backward compatibility; it has no effect on requests.
|
|
31
|
+
attr_accessor :api_user
|
|
24
32
|
end
|
|
25
|
-
end
|
|
33
|
+
end
|
data/paubox_ruby.gemspec
CHANGED
|
@@ -29,6 +29,10 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
|
30
30
|
spec.add_development_dependency 'webmock', '~> 2.1'
|
|
31
31
|
|
|
32
|
+
# base64 and ostruct left the default gems (base64 in Ruby 3.4, ostruct in
|
|
33
|
+
# 4.0). lib/ requires both, so they must be declared or the gem fails to load.
|
|
34
|
+
spec.add_dependency 'base64'
|
|
35
|
+
spec.add_dependency 'ostruct'
|
|
32
36
|
spec.add_dependency 'mail', '>= 2.5'
|
|
33
37
|
spec.add_dependency 'rest-client', '~> 2.0', '>= 2.0.2'
|
|
34
38
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
|
3
|
+
"packages": {
|
|
4
|
+
".": {
|
|
5
|
+
"release-type": "ruby",
|
|
6
|
+
"package-name": "paubox",
|
|
7
|
+
"version-file": "lib/paubox/version.rb",
|
|
8
|
+
"include-component-in-tag": false,
|
|
9
|
+
"include-v-in-tag": true,
|
|
10
|
+
"draft": false,
|
|
11
|
+
"prerelease": false
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: paubox
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paubox
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: bundler
|
|
@@ -80,6 +79,34 @@ dependencies:
|
|
|
80
79
|
- - "~>"
|
|
81
80
|
- !ruby/object:Gem::Version
|
|
82
81
|
version: '2.1'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: base64
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: ostruct
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
83
110
|
- !ruby/object:Gem::Dependency
|
|
84
111
|
name: mail
|
|
85
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -121,31 +148,42 @@ executables: []
|
|
|
121
148
|
extensions: []
|
|
122
149
|
extra_rdoc_files: []
|
|
123
150
|
files:
|
|
151
|
+
- ".github/scripts/assert_specs_ran.rb"
|
|
152
|
+
- ".github/workflows/ci.yml"
|
|
153
|
+
- ".github/workflows/pr-title.yml"
|
|
154
|
+
- ".github/workflows/release-please.yml"
|
|
124
155
|
- ".gitignore"
|
|
156
|
+
- ".release-please-manifest.json"
|
|
125
157
|
- ".rspec"
|
|
126
|
-
-
|
|
158
|
+
- CHANGELOG.md
|
|
159
|
+
- CLAUDE.md
|
|
127
160
|
- Gemfile
|
|
128
161
|
- LICENSE.txt
|
|
129
162
|
- README.md
|
|
130
163
|
- Rakefile
|
|
164
|
+
- api.md
|
|
131
165
|
- bin/console
|
|
132
166
|
- bin/setup
|
|
133
167
|
- lib/mail/paubox.rb
|
|
134
168
|
- lib/paubox.rb
|
|
135
169
|
- lib/paubox/client.rb
|
|
170
|
+
- lib/paubox/dynamic_templates.rb
|
|
136
171
|
- lib/paubox/email_disposition.rb
|
|
172
|
+
- lib/paubox/form.rb
|
|
173
|
+
- lib/paubox/form_submission.rb
|
|
137
174
|
- lib/paubox/format_helper.rb
|
|
175
|
+
- lib/paubox/forms_client.rb
|
|
138
176
|
- lib/paubox/mail_to_message.rb
|
|
139
177
|
- lib/paubox/message.rb
|
|
140
178
|
- lib/paubox/templated_message.rb
|
|
141
179
|
- lib/paubox/version.rb
|
|
142
180
|
- lib/paubox_ruby.rb
|
|
143
181
|
- paubox_ruby.gemspec
|
|
182
|
+
- release-please-config.json
|
|
144
183
|
homepage: https://www.paubox.com
|
|
145
184
|
licenses:
|
|
146
185
|
- Apache-2.0
|
|
147
186
|
metadata: {}
|
|
148
|
-
post_install_message:
|
|
149
187
|
rdoc_options: []
|
|
150
188
|
require_paths:
|
|
151
189
|
- lib
|
|
@@ -160,8 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
160
198
|
- !ruby/object:Gem::Version
|
|
161
199
|
version: '0'
|
|
162
200
|
requirements: []
|
|
163
|
-
rubygems_version: 3.
|
|
164
|
-
signing_key:
|
|
201
|
+
rubygems_version: 3.6.9
|
|
165
202
|
specification_version: 4
|
|
166
203
|
summary: Paubox's Official Ruby SDK
|
|
167
204
|
test_files: []
|