purelymail 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/README.md +134 -0
- data/lib/purelymail/client.rb +83 -0
- data/lib/purelymail/configuration.rb +29 -0
- data/lib/purelymail/error.rb +13 -0
- data/lib/purelymail/version.rb +5 -0
- data/lib/purelymail.rb +9 -0
- metadata +78 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 5e4bdda524618b9f54fa2db24e50c78720d0e37ed092dd2a90943095a65ef1e1
|
|
4
|
+
data.tar.gz: e4167c8d6e8ff29be55e479bb45acdaf159e97edd30a8ce901a2f643b2902b48
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f3ea3625f9066135040dfc9981b84a9f7f465ea75b4bd634a63be1c8b6da07eeaeae037c9477d80b2bb87cc582f39ad0e8c694d052031dac9fa9de051458b8d2
|
|
7
|
+
data.tar.gz: 56076ffc74848db74ac31a3c8f8b0c1c54f0960e6db801260ccf3c3747ad2026f7b3901e9ac8fd0cb189aae5144e85b61f1cb7dd0c7594f6dcc4a8b44ae19716
|
data/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Purelymail
|
|
2
|
+
|
|
3
|
+
A standalone Ruby client for the [Purelymail API](https://purelymail.com/).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this to your `Gemfile`:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem "purelymail"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then run `bundle install`.
|
|
14
|
+
|
|
15
|
+
Or install it yourself:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gem install purelymail
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Per-Instance Configuration
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
client = Purelymail::Client.new(api_token: "pm-live-xxxxxxxx")
|
|
27
|
+
client.create_domain(name: "example.com")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Global Configuration
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
Purelymail.configure do |config|
|
|
34
|
+
config.api_token = "pm-live-xxxxxxxx"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
client = Purelymail::Client.new
|
|
38
|
+
client.create_user(name: "alice", domain: "example.com", password: "s3cret")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
You can mix both: pass an `api_token` to `Client.new` to override the global config for that instance.
|
|
42
|
+
|
|
43
|
+
### API Methods
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
client = Purelymail::Client.new(api_token: "pm-live-xxxxxxxx")
|
|
47
|
+
|
|
48
|
+
client.create_domain(name: "example.com")
|
|
49
|
+
|
|
50
|
+
client.create_user(name: "alice", domain: "example.com", password: "s3cret")
|
|
51
|
+
|
|
52
|
+
client.change_password(name: "alice", domain: "example.com", password: "newpass")
|
|
53
|
+
|
|
54
|
+
client.create_routing_rule(
|
|
55
|
+
domain_name: "example.com",
|
|
56
|
+
match_user: "alice",
|
|
57
|
+
target_addresses: ["alice@destination.com"],
|
|
58
|
+
prefix: false,
|
|
59
|
+
catchall: false
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
client.configured?
|
|
63
|
+
# => true
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Error Handling
|
|
67
|
+
|
|
68
|
+
All API errors raise `Purelymail::ApiError`:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
begin
|
|
72
|
+
client.create_domain(name: "invalid@domain")
|
|
73
|
+
rescue Purelymail::ApiError => e
|
|
74
|
+
puts e.message # => "[Purelymail] addDomain failed: ..."
|
|
75
|
+
puts e.status # => 400
|
|
76
|
+
puts e.response # => {"type" => "error", "message" => "..."}
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Rails Integration
|
|
81
|
+
|
|
82
|
+
Add the gem to your `Gemfile`:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
gem "purelymail"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Configure via Rails credentials:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
bin/rails credentials:edit
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Add:
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
purelymail:
|
|
98
|
+
api_token: pm-live-xxxxxxxx
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The gem automatically picks up `Rails.application.credentials.dig(:purelymail, :api_token)` as a fallback, so you can use the client without any explicit configuration:
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
# config/initializers/purelymail.rb
|
|
105
|
+
Purelymail.configure do |config|
|
|
106
|
+
# config.api_token is optional here —
|
|
107
|
+
# it will fall back to Rails.application.credentials.purelymail.api_token
|
|
108
|
+
end
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Then anywhere in your app:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
Purelymail::Client.new.create_domain(name: "example.com")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
If you need to override the token at the call site, pass it directly:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
Purelymail::Client.new(api_token: "pm-live-yyyyyyyy")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Development
|
|
124
|
+
|
|
125
|
+
After checking out the repo, run:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
bundle install
|
|
129
|
+
bundle exec rspec
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "faraday"
|
|
4
|
+
require "faraday/retry"
|
|
5
|
+
|
|
6
|
+
module Purelymail
|
|
7
|
+
class Client
|
|
8
|
+
BASE_URL = "https://purelymail.com/api/v0/"
|
|
9
|
+
|
|
10
|
+
def initialize(api_token: nil)
|
|
11
|
+
@api_token = api_token || Purelymail.configuration.api_token
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create_domain(name:)
|
|
15
|
+
post("addDomain", { domainName: name })
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_user(name:, domain:, password:)
|
|
19
|
+
post("createUser", { userName: name, domainName: domain, password: password })
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def change_password(name:, domain:, password:)
|
|
23
|
+
post("changePassword", { userName: name, domainName: domain, password: password })
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_routing_rule(domain_name:, match_user:, target_addresses:, prefix: false, catchall: false)
|
|
27
|
+
post("createRoutingRule", {
|
|
28
|
+
domainName: domain_name,
|
|
29
|
+
matchUser: match_user,
|
|
30
|
+
targetAddresses: Array(target_addresses),
|
|
31
|
+
prefix: prefix,
|
|
32
|
+
catchall: catchall
|
|
33
|
+
})
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def configured?
|
|
37
|
+
!api_token.nil? && api_token.to_s.strip != ""
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
attr_reader :api_token
|
|
43
|
+
|
|
44
|
+
def connection
|
|
45
|
+
@connection ||= Faraday.new(url: BASE_URL) do |f|
|
|
46
|
+
f.options.timeout = 5
|
|
47
|
+
f.options.open_timeout = 3
|
|
48
|
+
f.request :json
|
|
49
|
+
f.response :json
|
|
50
|
+
f.request :retry, max: 3, interval: 0.5, interval_randomness: 0.5,
|
|
51
|
+
backoff_factor: 2,
|
|
52
|
+
exceptions: [Faraday::ServerError, Faraday::TimeoutError, Faraday::ConnectionFailed]
|
|
53
|
+
f.adapter Faraday.default_adapter
|
|
54
|
+
f.headers["Purelymail-Api-Token"] = api_token
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def post(endpoint, body)
|
|
59
|
+
response = connection.post(endpoint, body)
|
|
60
|
+
handle_response(response, endpoint)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def handle_response(response, endpoint)
|
|
64
|
+
body = response.body
|
|
65
|
+
|
|
66
|
+
if response.success? && body.is_a?(Hash) && body["type"] != "error"
|
|
67
|
+
body
|
|
68
|
+
else
|
|
69
|
+
error_msg = if body.is_a?(Hash)
|
|
70
|
+
body["message"] || body["code"]
|
|
71
|
+
else
|
|
72
|
+
"HTTP Status #{response.status}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
raise ApiError.new(
|
|
76
|
+
"[Purelymail] #{endpoint} failed: #{error_msg}",
|
|
77
|
+
status: response.status,
|
|
78
|
+
response: body
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Purelymail
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_writer :api_token
|
|
6
|
+
|
|
7
|
+
def api_token
|
|
8
|
+
@api_token || rails_credentials_token
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def rails_credentials_token
|
|
14
|
+
if defined?(Rails) && Rails.respond_to?(:application) && Rails.application.respond_to?(:credentials)
|
|
15
|
+
Rails.application.credentials.dig(:purelymail, :api_token)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def configuration
|
|
22
|
+
@configuration ||= Configuration.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def configure
|
|
26
|
+
yield(configuration)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Purelymail
|
|
4
|
+
class ApiError < StandardError
|
|
5
|
+
attr_reader :status, :response
|
|
6
|
+
|
|
7
|
+
def initialize(message = nil, status: nil, response: nil)
|
|
8
|
+
super(message)
|
|
9
|
+
@status = status
|
|
10
|
+
@response = response
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/purelymail.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: purelymail
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ben D'Angelo
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: faraday
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: faraday-retry
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.0'
|
|
40
|
+
description: A standalone Ruby gem for interacting with the Purelymail API. Manage
|
|
41
|
+
domains, users, routing rules, and more.
|
|
42
|
+
email:
|
|
43
|
+
- ben@bendangelo.me
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- README.md
|
|
49
|
+
- lib/purelymail.rb
|
|
50
|
+
- lib/purelymail/client.rb
|
|
51
|
+
- lib/purelymail/configuration.rb
|
|
52
|
+
- lib/purelymail/error.rb
|
|
53
|
+
- lib/purelymail/version.rb
|
|
54
|
+
homepage: https://github.com/bendangelo/purelymail-rb
|
|
55
|
+
licenses:
|
|
56
|
+
- MIT
|
|
57
|
+
metadata:
|
|
58
|
+
homepage_uri: https://github.com/bendangelo/purelymail-rb
|
|
59
|
+
source_code_uri: https://github.com/bendangelo/purelymail-rb
|
|
60
|
+
changelog_uri: https://github.com/bendangelo/purelymail-rb/blob/main/CHANGELOG.md
|
|
61
|
+
rdoc_options: []
|
|
62
|
+
require_paths:
|
|
63
|
+
- lib
|
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 2.7.0
|
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0'
|
|
74
|
+
requirements: []
|
|
75
|
+
rubygems_version: 4.0.10
|
|
76
|
+
specification_version: 4
|
|
77
|
+
summary: Ruby client for the Purelymail API
|
|
78
|
+
test_files: []
|