mailclerk 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e38216e89dcd97a31456876ff58694230dfc67b2285c3540ff0677092d5db47
4
- data.tar.gz: 90fc4a982810cc11a85adc7276d69bffbc168d034bdda9e6147ac546e50c6dd5
3
+ metadata.gz: a0411122cd662e0f7e37bfeb21853e818ecc8ec6e91fa54ad21ead1fad9ac998
4
+ data.tar.gz: 4b62af5e3f1b1e4e252c31f97d488cec0ee2e59d2023761c2b69fb83c7afa8d1
5
5
  SHA512:
6
- metadata.gz: 6fe8289fad0d470fc1a664a5ec30d8e4c4de8ec6bd6500aa9e0c6fa87a96ad5279b3f7f842a1897e04f3c734f0c7ed38ba1592b58acfe4871152339ead2272e7
7
- data.tar.gz: eb9d243468bc8205fdde9f62f460355595eddd9bebc66b80ebab8e7435c3197ee4939c05531219d08c18ad59c2e28880b5a4b140ff9ecda8a47e54d0a0261169
6
+ metadata.gz: 47d25d797fd25b415c8c251e464539df9544dd9863716ad37cc2b6bae843fe61f49c39f6853ff74d994239e920895db290282b84f64016672e590129bf443d37
7
+ data.tar.gz: 4eeea9f9278a145646f3fad23e0672c191c7b6b53ce148cf561dd7a76f268bfa729feec32bf5a0871270bf10c4f39d7aaac5896d237e0c202fb89aed24499186
data/README.md CHANGED
@@ -16,8 +16,9 @@ Mailclerk helps anyone on your team design great emails, improve their performan
16
16
  - [Setup](#setup)
17
17
  - [API Key & URL](#api-key--url)
18
18
  - [Usage](#usage)
19
+ - [Usage in Test Environments](#usage-in-test-environments)
19
20
  - [Varying API Keys](#varying-api-keys)
20
- - [Tests](#tests)
21
+ - [Gem Tests](#gem-tests)
21
22
  - [Versioning](#versioning)
22
23
  - [Code of Conduct](#code-of-conduct)
23
24
  - [Contributions](#contributions)
@@ -28,7 +29,7 @@ Mailclerk helps anyone on your team design great emails, improve their performan
28
29
 
29
30
  ## Requirements
30
31
 
31
- 1. [Ruby 2.7.0](https://www.ruby-lang.org)
32
+ 1. [Ruby 2.4.0](https://www.ruby-lang.org)
32
33
 
33
34
  ## Setup
34
35
 
@@ -50,9 +51,9 @@ To set the Mailclerk API Key (begins with `mc_`), you can provide it as an
50
51
  environmental variable: `MAILCLERK_API_KEY`. Alternatively, you can
51
52
  set it directly on the Mailclerk module:
52
53
 
53
- ```
54
+ ```ruby
54
55
  # config/initializers/mailclerk.rb
55
- Mailclerk.api_key = "mc_yourprivatekey"
56
+ Mailclerk.api_key = "mc_live_yourprivatekey"
56
57
  ```
57
58
 
58
59
  _If you are using version control like git, we strongly recommend storing your
@@ -67,44 +68,114 @@ You'll need an active account and at least one template (in the example `welcome
67
68
 
68
69
  To send an email to "alice@example.com":
69
70
 
70
- ```
71
+ ```ruby
71
72
  Mailclerk.deliver("welcome-email", "alice@example.com")
73
+ Mailclerk.deliver("welcome-email", "Alice Adams <alice@example.com>")
74
+ Mailclerk.deliver("welcome-email", { name: "Alice Adams", address: "<alice@example.com>" })
72
75
  ```
73
76
 
74
77
  If the template has any dynamic data, you can include it in the third parameter
75
78
  as a hash:
76
79
 
77
- ```
80
+ ```ruby
78
81
  Mailclerk.deliver("welcome-email", "alice@example.com", { name: "Alice" })
79
82
  ```
80
83
 
81
84
  See [Mailclerk documentation](https://dashboard.mailclerk.app/docs) for more details.
82
85
 
86
+ ## Usage in Test Environments
87
+
88
+ Your Mailclerk environment has two API keys: a production key (beginning with `mc_live`)
89
+ and a test key (beginning with `mc_test`). If you use the test key, emails will
90
+ not be delivered, but will show up in the logs on your Mailclerk account and can be
91
+ previewed there. This replaces tools like [Letter Opener](https://github.com/ryanb/letter_opener) for previewing emails in development.
92
+
93
+ To avoid cluttering up your Mailclerk test logs with sends triggered by your
94
+ automated test suite, call `Mailclerk.outbox.enable` in the file that
95
+ configures your tests. For example, in Rspec with Rails, add:
96
+
97
+ ```ruby
98
+ # spec/rails_helper.rb
99
+ Mailclerk.outbox.enable
100
+ ```
101
+
102
+ This will also enable utility methods which you can use to write tests that check
103
+ emails are sent with the correct data:
104
+
105
+ ```ruby
106
+ # Number of emails "sent"
107
+ Mailclerk.outbox.length
108
+
109
+ # Returns all emails of matching a template or email recipient. See method
110
+ Mailclerk.outbox.filter(template: "welcome-email")
111
+ Mailclerk.outbox.filter(recipient_email: "felix@example.com")
112
+
113
+ # Returns the most recent email (instance of Mailclerk::TestEmail):
114
+ email = Mailclerk.outbox.last
115
+ email.template # "welcome-email"
116
+ email.recipient_email # "felix@example.com"
117
+ email.subject # "Welcome to Acme Felix"
118
+ email.html # "<html><body>..."
119
+ ```
120
+
121
+ In between test cases, you should clear the stored emails by calling `Mailclerk.outbox.reset`.
122
+
123
+ For example, in Rspec with Rails:
124
+
125
+ ```ruby
126
+ # spec/rails_helper.rb
127
+ RSpec.configure do |config|
128
+ config.before(:each) do
129
+ Mailclerk.outbox.reset
130
+ end
131
+ end
132
+ ```
133
+
134
+ `Mailclerk::OutboxEmail` has the following attributes:
135
+
136
+ | Attribute | Description |
137
+ | ----------------- | -------------------------------------------------------------------------- |
138
+ | `template` | Slug of the template sent (1st argument to `Mailclerk.deliver`) |
139
+ | `recipient` | Hash representing the send recipient (2nd argument to `Mailclerk.deliver`) |
140
+ | `recipient_email` | Email of the send recipient |
141
+ | `recipient_name` | Name of the send recipient (nil if not specified) |
142
+ | `data` | Dynamic data for the send (3rd argument to `Mailclerk.deliver`) |
143
+ | `options` | Options specified for the send (4th argument to `Mailclerk.deliver`) |
144
+ | `from` | From Mailclerk: Hash with `name` and `address` of the sender |
145
+ | `subject` | From Mailclerk: Text of the send's subject line |
146
+ | `preheader` | From Mailclerk: Text of the send's preheader |
147
+ | `html` | From Mailclerk: Rendered body HTML for the send |
148
+ | `text` | From Mailclerk: Rendered plaintext version of the send |
149
+ | `headers` | From Mailclerk: Extra email headers (e.g. `reply-to`) |
150
+
151
+ See the [Mailclerk testing documentation](https://dashboard.mailclerk.app/docs#testing)
152
+ for more details.
153
+
83
154
  ## Varying API Keys
84
155
 
85
156
  If you need to use multiple API keys, you can also initialize `Mailclerk::Client`
86
157
  instances with different keys. This:
87
158
 
88
- ```
89
- mc_client = Mailclerk.new("mc_yourprivatekey")
159
+ ```ruby
160
+ mc_client = Mailclerk.new("mc_live_yourprivatekey")
90
161
  mc_client.deliver("welcome-email", "bob@example.com")
91
162
  ```
92
163
 
93
164
  Is equivalent to this:
94
165
 
95
- ```
96
- Mailclerk.api_key = "mc_yourprivatekey"
166
+ ```ruby
167
+ Mailclerk.api_key = "mc_live_yourprivatekey"
97
168
  Mailclerk.deliver("welcome-email", "bob@example.com")
98
169
  ```
99
170
 
100
- ## Tests
101
-
102
- Tests aren't currently implemented. When they are, to test, run:
171
+ ## Gem Tests
103
172
 
104
173
  ```
105
- bundle exec rake
174
+ bundle exec rspec
106
175
  ```
107
176
 
177
+ Requires values in .env file as well
178
+
108
179
  ## Versioning
109
180
 
110
181
  Read [Semantic Versioning](https://semver.org) for details. Briefly, it means:
data/lib/client.rb ADDED
@@ -0,0 +1,62 @@
1
+ module Mailclerk
2
+ class Client
3
+ def initialize(api_key, api_url=nil)
4
+ @api_key = api_key
5
+ @api_url = api_url || ENV['MAILCLERK_API_URL'] || DEFAULT_API_URL
6
+
7
+ if @api_key.nil?
8
+ raise MailclerkError.new(
9
+ "No Mailclerk API Key provided. Set `Mailclerk.api_key`"
10
+ )
11
+ end
12
+
13
+ if @api_url.nil? || @api_url.empty?
14
+ raise MailclerkError.new("Mailclerk API URL empty")
15
+ end
16
+ end
17
+
18
+ def deliver(template, recipient, data={}, options={})
19
+ conn = Faraday.new(url: @api_url)
20
+ conn.basic_auth(@api_key, '')
21
+
22
+ if Mailclerk.outbox_enabled?
23
+ options = options.merge(
24
+ "local_outbox" => true
25
+ )
26
+ options.delete(:local_outbox)
27
+ end
28
+
29
+ params = {
30
+ 'template' => template,
31
+ 'recipient' => recipient,
32
+ 'data' => data,
33
+ 'options' => options
34
+ }
35
+
36
+ response = conn.post('deliver', params.to_json, {
37
+ 'Content-Type' => 'application/json',
38
+ 'X-Client-Version' => Identity.version_label
39
+ })
40
+
41
+ if response.status >= 400
42
+ begin
43
+ message = JSON.parse(response.body)["message"] || "Unknown"
44
+ description = "Mailclerk API Error: #{ message }"
45
+ rescue JSON::ParserError
46
+ description = "Mailclerk API Unknown Error"
47
+ end
48
+
49
+ raise MailclerkAPIError.new(
50
+ description, response.status, response
51
+ )
52
+ end
53
+
54
+ if Mailclerk.outbox_enabled?
55
+ params["options"].delete("local_outbox")
56
+ Mailclerk.outbox.add_send(params, JSON.parse(response.body)["delivery"])
57
+ end
58
+
59
+ return response
60
+ end
61
+ end
62
+ end
data/lib/errors.rb ADDED
@@ -0,0 +1,15 @@
1
+ module Mailclerk
2
+ class MailclerkError < StandardError
3
+ end
4
+
5
+ class MailclerkAPIError < MailclerkError
6
+ attr_accessor :http_status
7
+ attr_accessor :http_response
8
+
9
+ def initialize(description, http_status=nil, http_response=nil)
10
+ super(description)
11
+ self.http_status = http_status
12
+ self.http_response = http_response
13
+ end
14
+ end
15
+ end
data/lib/mailclerk.rb CHANGED
@@ -3,6 +3,10 @@
3
3
  require 'faraday'
4
4
  require 'json'
5
5
 
6
+ require "client"
7
+ require "errors"
8
+ require "outbox"
9
+
6
10
  module Mailclerk
7
11
  DEFAULT_API_URL = "https://api.mailclerk.app"
8
12
 
@@ -22,7 +26,7 @@ module Mailclerk
22
26
  end
23
27
 
24
28
  def self.version
25
- "1.0.2"
29
+ "1.1.0"
26
30
  end
27
31
 
28
32
  def self.version_label
@@ -30,75 +34,19 @@ module Mailclerk
30
34
  end
31
35
  end
32
36
 
33
- class MailclerkError < StandardError
34
- end
35
-
36
- class MailclerkAPIError < MailclerkError
37
- attr_accessor :http_status
38
- attr_accessor :http_response
39
-
40
- def initialize(description, http_status=nil, http_response=nil)
41
- super(description)
42
- self.http_status = http_status
43
- self.http_response = http_response
44
- end
45
-
46
- end
47
-
48
- class Client
49
- def initialize(api_key, api_url=nil)
50
- @api_key = api_key
51
- @api_url = api_url || ENV['MAILCLERK_API_URL'] || DEFAULT_API_URL
52
-
53
- if @api_key.nil?
54
- raise MailclerkError.new(
55
- "No Mailclerk API Key provided. Set `Mailclerk.api_key`"
56
- )
57
- end
58
-
59
- if @api_url.nil? || @api_url.empty?
60
- raise MailclerkError.new("Mailclerk API URL empty")
61
- end
62
- end
63
-
64
- def deliver(template, recipient, data={}, options={})
65
- conn = Faraday.new(url: @api_url)
66
- conn.basic_auth(@api_key, '')
67
-
68
- response = conn.post('deliver', {
69
- 'template' => template,
70
- 'recipient' => recipient,
71
- 'data' => data,
72
- 'options' => options
73
- }.to_json, {
74
- 'Content-Type' => 'application/json',
75
- 'X-Client-Version' => Identity.version_label
76
- })
77
-
78
- if response.status >= 400
79
- begin
80
- message = JSON.parse(response.body)["message"] || "Unknown"
81
- description = "Mailclerk API Error: #{ message }"
82
- rescue JSON::ParserError
83
- description = "Mailclerk API Unknown Error"
84
- end
85
-
86
- raise MailclerkAPIError.new(
87
- description, response.status, response
88
- )
89
-
90
- end
91
-
92
- return response
93
- end
94
- end
95
-
96
37
  # Syntax intended to emulate ActionMailer
97
38
  def self.deliver(*args)
98
39
  api_key = self.api_key || ENV['MAILCLERK_API_KEY']
99
40
 
100
- client = Client.new(api_key, self.api_url)
41
+ client = Mailclerk::Client.new(api_key, self.api_url)
101
42
  return client.deliver(*args)
102
43
  end
44
+
45
+ def self.outbox
46
+ @outbox ||= Mailclerk::Outbox.new
47
+ end
103
48
 
104
- end
49
+ def self.outbox_enabled?
50
+ !!(@outbox && @outbox.enabled)
51
+ end
52
+ end
data/lib/outbox.rb ADDED
@@ -0,0 +1,93 @@
1
+ module Mailclerk
2
+ class Outbox < Array
3
+ attr_accessor :enabled
4
+
5
+ def initialize
6
+ self.enabled = false
7
+ end
8
+
9
+ def enable
10
+ self.enabled = true
11
+ end
12
+
13
+ def reset
14
+ self.clear
15
+ end
16
+
17
+ # Not just an alias for 'select'
18
+ def filter(query)
19
+ puts query
20
+ self.select do |email|
21
+ query.all? do |key, value|
22
+ puts email[key]
23
+ email[key] == value
24
+ end
25
+ end
26
+ end
27
+
28
+ def add_send(request, response)
29
+ email = OutboxEmail.new(
30
+ OutboxEmail.recursive_init(
31
+ response.merge(request)
32
+ )
33
+ )
34
+ self << email
35
+ end
36
+ end
37
+
38
+ class OutboxEmail < OpenStruct
39
+
40
+ def self.recursive_init(data)
41
+
42
+ data.each do |key, val|
43
+ if val.is_a?(Hash)
44
+ data[key] = self.recursive_init(val)
45
+ else
46
+ data[key] = val
47
+ end
48
+ end
49
+
50
+ return OpenStruct.new(data)
51
+ end
52
+
53
+ # Custom getters
54
+
55
+ def recipient_email
56
+ return parse_recipient[:address]
57
+ end
58
+
59
+ def recipient_name
60
+ return parse_recipient[:name]
61
+ end
62
+
63
+ private
64
+
65
+ def parse_recipient
66
+ return {} unless self.recipient
67
+
68
+ if self.recipient.is_a?(OpenStruct)
69
+ return self.recipient
70
+ end
71
+
72
+ text = self.recipient.strip
73
+
74
+ if text =~ /^[^<]+<[^<]+>$/
75
+ parts = text.split("<", 2);
76
+
77
+ name = parts[0].strip.gsub('"', "")
78
+
79
+ address = parts[1].strip.gsub(">", "")
80
+
81
+ return {
82
+ name: name,
83
+ address: address
84
+ }
85
+ else
86
+ return {
87
+ name: nil,
88
+ address: text
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailclerk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noah Litvin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-16 00:00:00.000000000 Z
12
+ date: 2021-03-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -109,6 +109,20 @@ dependencies:
109
109
  - - "~>"
110
110
  - !ruby/object:Gem::Version
111
111
  version: '3.9'
112
+ - !ruby/object:Gem::Dependency
113
+ name: dotenv
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
112
126
  description:
113
127
  email:
114
128
  - developers@mailclerk.app
@@ -120,7 +134,10 @@ extra_rdoc_files:
120
134
  files:
121
135
  - LICENSE.md
122
136
  - README.md
137
+ - lib/client.rb
138
+ - lib/errors.rb
123
139
  - lib/mailclerk.rb
140
+ - lib/outbox.rb
124
141
  homepage: https://github.com/mailclerk/mailclerk-ruby
125
142
  licenses:
126
143
  - MIT