mailbluster 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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +120 -0
- data/lib/mailbluster/client.rb +106 -0
- data/lib/mailbluster/configuration.rb +9 -0
- data/lib/mailbluster/resource.rb +24 -0
- data/lib/mailbluster/resource_type.rb +68 -0
- data/lib/mailbluster/utils.rb +20 -0
- data/lib/mailbluster/version.rb +3 -0
- data/lib/mailbluster.rb +16 -0
- metadata +71 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 89c061011879b9528428b63e1e63487718ee20f457c5f9ae5445785455009830
|
|
4
|
+
data.tar.gz: 34be79b1a3b0f6227a0acfdf00683b83962198e2897a148852dd7806f9cfd703
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: aecf52c361f5576b1d13723972bbd9053dd09ae82f1352c51315fda9a2c75a7247bc9151ca4a2306ee1fee7f704974197fc96f04907057a70b46646517bb9ca2
|
|
7
|
+
data.tar.gz: 61c30ab79c442ef4df52d64b345a6bf51beec468ace1753b5c6a900d77c5cad64cc2b8ffe49f9040dd3ac3d5ed10658028585230d00aef51f556c28a43a88344
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Tanay Lakhani
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# mailbluster
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/mailbluster)
|
|
4
|
+
[](https://github.com/tanaylakhani/mailbluster-ruby/actions/workflows/ci.yml)
|
|
5
|
+
|
|
6
|
+
Ruby client for the [Mailbluster API](https://app.mailbluster.com/api-doc).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
- [Quick start](#quick-start)
|
|
11
|
+
- [Usage](#usage)
|
|
12
|
+
- [Demo script](#demo-script)
|
|
13
|
+
- [API Documentation](#api-documentation)
|
|
14
|
+
- [Detailed mailbluster-ruby documentation](#detailed-mailbluster-ruby-documentation)
|
|
15
|
+
- [Support](#support)
|
|
16
|
+
- [License](#license)
|
|
17
|
+
- [Code of conduct](#code-of-conduct)
|
|
18
|
+
- [Contribution guide](#contribution-guide)
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
gem install mailbluster
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
or with bundler:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundler add mailbluster
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
then configure the gem:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
Mailbluster.configure do |config|
|
|
36
|
+
config.api_key = 'your-api-key'
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
or with environment variables:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
env MAILBLUSTER_API_KEY=your-api-key ruby app.rb
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
or directly on the Client instance:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
mailbluster_client = Mailbluster::Client.new('your-api-key')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
mailbluster_client = Mailbluster::Client.new
|
|
56
|
+
lead = mailbluster_client.leads.create(email: 'lead@example.org')
|
|
57
|
+
puts lead.inspect # => #<Mailbluster::Resource @resource_type=#<Mailbluster::ResourceType::Lead>, @raw_attributes={"id"=>262093545 ...}>
|
|
58
|
+
|
|
59
|
+
mailbluster_client.leads.read(lead.email) # => #<Mailbluster::Resource @resource_type=#<Mailbluster::ResourceType::Lead>, @raw_attributes={"id"=>262093545 ...}>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Sample Attributes to create Lead
|
|
63
|
+
```ruby
|
|
64
|
+
create_lead_attributes = {
|
|
65
|
+
"firstName" => "Richard",
|
|
66
|
+
"lastName" => "Hendricks",
|
|
67
|
+
"fields" => {
|
|
68
|
+
"gender" => "Male",
|
|
69
|
+
"address" => "Silicon Valley"
|
|
70
|
+
},
|
|
71
|
+
"email" => "richard@example.com",
|
|
72
|
+
"ipAddress" => "162.213.1.246",
|
|
73
|
+
"subscribed" => false,
|
|
74
|
+
"doubleOptIn" => true,
|
|
75
|
+
"meta" => {
|
|
76
|
+
"company" => "Pied Piper",
|
|
77
|
+
"role" => "CEO"
|
|
78
|
+
},
|
|
79
|
+
"tags" => [
|
|
80
|
+
"iPhone User",
|
|
81
|
+
"Startup"
|
|
82
|
+
],
|
|
83
|
+
"overrideExisting" => true
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Demo script
|
|
89
|
+
In the `bin` directory, there is a `demo` script that you can run to see how to use the gem and to create example leads in Mailbluster. You can run it like this:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
env MAILBLUSTER_API_KEY=your-api-key ruby bin/demo
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Mailbluster API Documentation
|
|
96
|
+
Official documentation for the Mailbluster API can be found at <https://app.mailbluster.com/api-doc>.
|
|
97
|
+
|
|
98
|
+
## Detailed mailbluster-ruby documentation
|
|
99
|
+
|
|
100
|
+
- [Detailed: API Documentation](docs/api_documentation.md)
|
|
101
|
+
- [Detailed: Client](docs/client.md)
|
|
102
|
+
- [Detailed: Configuration](docs/configuration.md)
|
|
103
|
+
- [Detailed: Resources](docs/resources.md)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## Support
|
|
107
|
+
|
|
108
|
+
If you want to report a bug, or have ideas, feedback or questions about the gem, [let me know via GitHub issues](https://github.com/tanaylakhani/mailbluster-ruby/issues/new) and I will do my best to provide a helpful answer. Happy hacking!
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
|
|
113
|
+
|
|
114
|
+
## Code of conduct
|
|
115
|
+
|
|
116
|
+
Everyone interacting in this project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
|
|
117
|
+
|
|
118
|
+
## Contribution guide
|
|
119
|
+
|
|
120
|
+
Pull requests are welcome!
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "rest-client"
|
|
3
|
+
|
|
4
|
+
module Mailbluster
|
|
5
|
+
class Client
|
|
6
|
+
Error = Class.new(StandardError)
|
|
7
|
+
Forbidden = Class.new(Error)
|
|
8
|
+
NotFound = Class.new(Error)
|
|
9
|
+
UnprocessableEntity = Class.new(Error)
|
|
10
|
+
|
|
11
|
+
RESOURCES = ["leads", "fields", "products", "orders"].freeze
|
|
12
|
+
|
|
13
|
+
def initialize(api_key = nil, logger = nil)
|
|
14
|
+
@api_key = api_key ||
|
|
15
|
+
Mailbluster.configuration.api_key ||
|
|
16
|
+
ENV["MAILBLUSTER_API_KEY"]
|
|
17
|
+
@api_url = Mailbluster.configuration.api_url ||
|
|
18
|
+
ENV["MAILBLUSTER_API_URL"]
|
|
19
|
+
|
|
20
|
+
@logger = logger || Mailbluster.configuration.logger
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def resource(resource_type)
|
|
24
|
+
raise ArgumentError, "Invalid resource type" unless RESOURCES.include?(resource_type)
|
|
25
|
+
|
|
26
|
+
ResourceType.new(self, resource_type)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
RESOURCES.each do |resource_type|
|
|
30
|
+
define_method(resource_type) do
|
|
31
|
+
resource(resource_type)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def get(subpath, query_params: nil)
|
|
36
|
+
request(:get, subpath, query_params)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def post(subpath, payload)
|
|
40
|
+
request(:post, subpath, payload)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def put(subpath, payload = {})
|
|
44
|
+
request(:put, subpath, payload)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def delete(subpath)
|
|
48
|
+
request(:delete, subpath)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
attr_reader :api_key, :api_url, :logger
|
|
54
|
+
|
|
55
|
+
def request(method, subpath, payload = {})
|
|
56
|
+
url = URI.parse(api_url + subpath)
|
|
57
|
+
if method == :get && payload != {}
|
|
58
|
+
url = "#{url}?#{URI.encode_www_form(payload.to_a)}"
|
|
59
|
+
payload = {}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
log("Request: #{method} #{url} #{payload}")
|
|
63
|
+
response = ::RestClient::Request.execute(
|
|
64
|
+
prepare_request_options(method, payload, url)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
log("Response: #{response.code} #{response.body}")
|
|
68
|
+
|
|
69
|
+
JSON.parse(response.body)
|
|
70
|
+
rescue RestClient::Forbidden => e
|
|
71
|
+
raise Forbidden, "#{e.message}\nMake sure that you set correct Mailbluster API KEY"
|
|
72
|
+
rescue RestClient::UnprocessableEntity => e
|
|
73
|
+
raise UnprocessableEntity, e.response.body || [
|
|
74
|
+
e.message, "Make sure that you set correct resource attributes"
|
|
75
|
+
].join("\n")
|
|
76
|
+
rescue RestClient::NotFound => e
|
|
77
|
+
raise NotFound, e.message
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def prepare_request_options(method, payload, url)
|
|
81
|
+
{
|
|
82
|
+
method: method,
|
|
83
|
+
url: url.to_s,
|
|
84
|
+
payload: payload&.to_json,
|
|
85
|
+
headers: {
|
|
86
|
+
content_type: :json,
|
|
87
|
+
accept: :json,
|
|
88
|
+
user_agent: mailbluster_user_agent,
|
|
89
|
+
authorization: api_key
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def mailbluster_user_agent
|
|
95
|
+
[
|
|
96
|
+
"mailbluster-ruby",
|
|
97
|
+
Mailbluster::VERSION,
|
|
98
|
+
RestClient::Platform.default_user_agent
|
|
99
|
+
].join("/")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def log(message, level = :info)
|
|
103
|
+
logger&.send(level, "[Mailbluster::Client] #{message}")
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Mailbluster
|
|
2
|
+
class Resource
|
|
3
|
+
attr_reader :raw_attributes
|
|
4
|
+
|
|
5
|
+
def initialize(resource_type, attributes)
|
|
6
|
+
@resource_type = resource_type
|
|
7
|
+
@raw_attributes = attributes
|
|
8
|
+
map_attributes_to_methods
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
attr_reader :resource_type
|
|
14
|
+
|
|
15
|
+
def map_attributes_to_methods
|
|
16
|
+
raw_attributes.each_key do |key|
|
|
17
|
+
method_name = Utils.underscore(key.to_s)
|
|
18
|
+
define_singleton_method(method_name) do
|
|
19
|
+
raw_attributes[key]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Mailbluster
|
|
2
|
+
class ResourceType
|
|
3
|
+
attr_reader :resource_type
|
|
4
|
+
|
|
5
|
+
def initialize(client, resource_type)
|
|
6
|
+
@client = client
|
|
7
|
+
@resource_type = resource_type
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def inspect
|
|
11
|
+
"#<Mailbluster::ResourceType::#{singular_resource_type.capitalize}>"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create(new_attributes)
|
|
15
|
+
raw_resource_attributes = @client.post(resource_type, new_attributes)
|
|
16
|
+
Resource.new(self, raw_resource_attributes[singular_resource_type] || raw_resource_attributes)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def read(id_or_email_md5 = "")
|
|
20
|
+
id_or_email_md5 = Utils.md5(id_or_email_md5) if lead? && id_or_email_md5.include?("@")
|
|
21
|
+
if id_or_email_md5.is_a?(Hash)
|
|
22
|
+
query_params = query_parameterize(id_or_email_md5)
|
|
23
|
+
id_or_email_md5 = ""
|
|
24
|
+
end
|
|
25
|
+
raw_resource_attributes = @client.get("#{resource_type}/#{id_or_email_md5}",
|
|
26
|
+
query_params: query_params)
|
|
27
|
+
map_to_resource(id_or_email_md5, raw_resource_attributes)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def update(id_or_email_md5, new_attributes)
|
|
31
|
+
id_or_email_md5 = Utils.md5(id_or_email_md5) if lead? && id_or_email_md5.include?("@")
|
|
32
|
+
raw_resource_attributes = @client.put("#{resource_type}/#{id_or_email_md5}", new_attributes)
|
|
33
|
+
Resource.new(self, raw_resource_attributes[singular_resource_type] || raw_resource_attributes)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def delete(id_or_email_md5)
|
|
37
|
+
id_or_email_md5 = Utils.md5(id_or_email_md5) if lead? && id_or_email_md5.include?("@")
|
|
38
|
+
@client.delete("#{resource_type}/#{id_or_email_md5}")
|
|
39
|
+
id_or_email_md5
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def lead?
|
|
43
|
+
resource_type == "leads"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def query_parameterize(id_or_email_md5)
|
|
49
|
+
id_or_email_md5.map do |k, v|
|
|
50
|
+
[Utils.camelize(k.to_s), v]
|
|
51
|
+
end.to_h
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def map_to_resource(id_or_email_md5, raw_resource_attributes)
|
|
55
|
+
if id_or_email_md5 == "" && raw_resource_attributes[resource_type].is_a?(Array)
|
|
56
|
+
raw_resource_attributes[resource_type].map do |rra|
|
|
57
|
+
Resource.new(self, rra)
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
Resource.new(self, raw_resource_attributes)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def singular_resource_type
|
|
65
|
+
resource_type[0..-2]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "digest/md5"
|
|
2
|
+
|
|
3
|
+
module Mailbluster
|
|
4
|
+
module Utils
|
|
5
|
+
def self.md5(string)
|
|
6
|
+
Digest::MD5.hexdigest(string)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.underscore(string)
|
|
10
|
+
string.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze).
|
|
11
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2'.freeze).
|
|
12
|
+
tr("-".freeze, "_".freeze).downcase
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.camelize(string)
|
|
16
|
+
# camelize string but don't capitalize the first letter
|
|
17
|
+
string.split("_").map(&:capitalize).join.sub(/^./, &:downcase)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/mailbluster.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Mailbluster
|
|
2
|
+
autoload :VERSION, "mailbluster/version"
|
|
3
|
+
autoload :Utils, "mailbluster/utils"
|
|
4
|
+
autoload :Client, "mailbluster/client"
|
|
5
|
+
autoload :Configuration, "mailbluster/configuration"
|
|
6
|
+
autoload :ResourceType, "mailbluster/resource_type"
|
|
7
|
+
autoload :Resource, "mailbluster/resource"
|
|
8
|
+
|
|
9
|
+
def self.configuration
|
|
10
|
+
@configuration ||= Configuration.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.configure
|
|
14
|
+
yield(configuration)
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mailbluster
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tanay Lakhani
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-03-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rest-client
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2'
|
|
27
|
+
description:
|
|
28
|
+
email:
|
|
29
|
+
- tpl253@nyu.edu
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- LICENSE.txt
|
|
35
|
+
- README.md
|
|
36
|
+
- lib/mailbluster.rb
|
|
37
|
+
- lib/mailbluster/client.rb
|
|
38
|
+
- lib/mailbluster/configuration.rb
|
|
39
|
+
- lib/mailbluster/resource.rb
|
|
40
|
+
- lib/mailbluster/resource_type.rb
|
|
41
|
+
- lib/mailbluster/utils.rb
|
|
42
|
+
- lib/mailbluster/version.rb
|
|
43
|
+
homepage: https://github.com/tanaylakhani/mailbluster-ruby
|
|
44
|
+
licenses:
|
|
45
|
+
- MIT
|
|
46
|
+
metadata:
|
|
47
|
+
bug_tracker_uri: https://github.com/tanaylakhani/mailbluster-ruby/issues
|
|
48
|
+
changelog_uri: https://github.com/tanaylakhani/mailbluster-ruby/releases
|
|
49
|
+
source_code_uri: https://github.com/tanaylakhani/mailbluster-ruby
|
|
50
|
+
homepage_uri: https://github.com/tanaylakhani/mailbluster-ruby
|
|
51
|
+
rubygems_mfa_required: 'true'
|
|
52
|
+
post_install_message:
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
require_paths:
|
|
55
|
+
- lib
|
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '2.3'
|
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
requirements: []
|
|
67
|
+
rubygems_version: 3.1.6
|
|
68
|
+
signing_key:
|
|
69
|
+
specification_version: 4
|
|
70
|
+
summary: A Ruby wrapper for Mailbluster API
|
|
71
|
+
test_files: []
|