courrier 0.8.1 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b3c205c8fe157cc0eb5b6addc937bed0b256207da068262dddd2a903f474dd9
4
- data.tar.gz: eac8a569f680a755f18f496f3a6118f3f5dccba38ffb8a417ff7c012974df1f6
3
+ metadata.gz: 8a3d93b4337d15e066ffa7ed4626dd254231ee744940de07b7b76be8714afbde
4
+ data.tar.gz: d7ef7a3ed1a8600581b6bdf13f63072c49ad138ad52384e1c358dbcd8f8a45b2
5
5
  SHA512:
6
- metadata.gz: af1f9d97366be5d819114f5d3f0510d01ad2297eca90f0a23217832c1fc9202acf8c99c9b77e9baf4aa2cb87b85ad630797853c9e85b6fe27da78cda70cf5989
7
- data.tar.gz: df77f8fdeeba27658032a99a1435e750b4f336b5a0ef9ec51681c0d6e4df1c744d9c04fd9b147428480abee79c5f0b786ad8c10e8eb91b8bdd6b85b446f5abf1
6
+ metadata.gz: 32d2fba728012eb703ca67044484a2f0caf0177ee0f341b6973566a50136f6531dfc37edfe7347511b4de67291af0364f6f03ad4c22247f5bbd72ca306e13455
7
+ data.tar.gz: 5a3ea2ea5fb0637f025a3577d6e1004a66478e0929b96752b0fdea302af95f6c88af3bed801265dc14f6645a8014adb781cd1cc04ee1809bedf76ca892f4c4f0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- courrier (0.8.1)
4
+ courrier (0.9.0)
5
5
  launchy (>= 3.1, < 4)
6
6
  nokogiri (>= 1.18, < 2)
7
7
 
data/README.md CHANGED
@@ -16,8 +16,9 @@ end
16
16
 
17
17
  OrderEmail.deliver to: "recipient@railsdesigner.com"
18
18
 
19
- # Manage newsletter subscriptions
19
+ # Manage newsletter subscribers
20
20
  Courrier::Subscriber.create "subscriber@example.com"
21
+ Courrier::Subscriber.destroy "subscriber@example.com"
21
22
  ```
22
23
 
23
24
  <a href="https://railsdesigner.com/" target="_blank">
@@ -255,6 +256,39 @@ end
255
256
  ```
256
257
 
257
258
 
259
+ ### Template files
260
+
261
+ Instead of defining `text` and `html` methods, you can create ERB template files:
262
+ ```ruby
263
+ class OrderEmail < Courrier::Email
264
+ def subject = "Your order is ready!"
265
+ # text and html content will be loaded from template files
266
+ end
267
+ ```
268
+
269
+ Create template files alongside your email class:
270
+ - `app/emails/order_email.text.erb`
271
+ - `app/emails/order_email.html.erb`
272
+
273
+ Templates have access to all context options and instance variables:
274
+ ```erb
275
+ <!-- app/emails/order_email.html.erb -->
276
+ <h1>Hello <%= name %>!</h1>
277
+ <p>Your order #<%= order_id %> is ready for pickup.</p>
278
+ ```
279
+
280
+ Method definitions take precedence over template files when both exist. You can mix approaches. For example, define text in a method and use a template for the html:
281
+ ```ruby
282
+ class OrderEmail < Courrier::Email
283
+ def subject = "Your order is ready!"
284
+
285
+ def text = "Hello #{name}! Your order ##{order_id} is ready."
286
+
287
+ # html will be loaded from app/emails/order_email.html.erb
288
+ end
289
+ ```
290
+
291
+
258
292
  ### Auto-generate text from HTML
259
293
 
260
294
  Automatically generate plain text versions from your HTML emails:
@@ -40,8 +40,8 @@ module Courrier
40
40
  end
41
41
 
42
42
  def deliver
43
- raise Courrier::ConfigurationError, "`provider` and `api_key` must be configured for production environment" if configuration_missing_in_production?
44
- raise Courrier::ConfigurationError, "Unknown provider. Choose one of `#{comma_separated_providers}` or provide your own." if @provider.nil? || @provider.to_s.strip.empty?
43
+ raise Courrier::ConfigurationError, "Unknown provider. Choose one of `#{comma_separated_providers}` or provide your own." if provider_invalid?
44
+ raise Courrier::ConfigurationError, "API key must be configured for #{@provider} provider in production environment" if configuration_missing_in_production?
45
45
 
46
46
  provider_class.new(
47
47
  api_key: @api_key,
@@ -53,8 +53,12 @@ module Courrier
53
53
 
54
54
  private
55
55
 
56
+ def provider_invalid?
57
+ @provider.nil? || @provider.to_s.strip.empty?
58
+ end
59
+
56
60
  def configuration_missing_in_production?
57
- production? && required_attributes_blank?
61
+ production? && api_key_required_providers? && api_key_blank?
58
62
  end
59
63
 
60
64
  def comma_separated_providers = PROVIDERS.keys.join(", ")
@@ -65,7 +69,13 @@ module Courrier
65
69
  Object.const_get(@provider)
66
70
  end
67
71
 
68
- def required_attributes_blank? = @api_key.empty?
72
+ def api_key_required_providers?
73
+ !%w[logger inbox].include?(@provider.to_s)
74
+ end
75
+
76
+ def api_key_blank?
77
+ @api_key.nil? || @api_key.to_s.strip.empty?
78
+ end
69
79
 
70
80
  def production?
71
81
  defined?(Rails) && Rails.env.production?
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "erb"
4
+
3
5
  require "courrier/email/address"
4
6
  require "courrier/jobs/email_delivery_job" if defined?(Rails)
5
7
  require "courrier/email/layouts"
@@ -133,7 +135,25 @@ module Courrier
133
135
  ENV["COURRIER_EMAIL_DISABLED"] == "true" || ENV["COURRIER_EMAIL_ENABLED"] == "false"
134
136
  end
135
137
 
136
- def method_missing(name, *) = @context_options[name]
138
+ def method_missing(name, *)
139
+ if name == :text || name == :html
140
+ render_template(name.to_s)
141
+ else
142
+ @context_options[name]
143
+ end
144
+ end
145
+
146
+ def render_template(format)
147
+ template_path = template_file_path(format)
148
+
149
+ File.exist?(template_path) ? ERB.new(File.read(template_path)).result(binding) : nil
150
+ end
151
+
152
+ def template_file_path(format)
153
+ class_path = self.class.name.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
154
+
155
+ File.join(Courrier.configuration&.email_path, "#{class_path}.#{format}.erb")
156
+ end
137
157
 
138
158
  def respond_to_missing?(name, include_private = false) = true
139
159
  end
@@ -1,3 +1,3 @@
1
1
  module Courrier
2
- VERSION = "0.8.1"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -3,13 +3,13 @@ Courrier.configure do |config|
3
3
 
4
4
  # Set your email delivery provider
5
5
  # config.email = {
6
- # provider = "", # default, `logger`, choose from: <%= Courrier::Email::Provider::PROVIDERS.keys.join(", ") %>
7
- # api_key = "" your transactional email provider's API key
6
+ # provider: "", # default, `logger`, choose from: <%= Courrier::Email::Provider::PROVIDERS.keys.join(", ") %>
7
+ # api_key: "" your transactional email provider's API key
8
8
  # }
9
9
 
10
10
  # Set your marketing email provider
11
11
  # config.subscriber = {
12
- # provider = ""
12
+ # provider: ""
13
13
  # }
14
14
 
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: courrier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rails Designer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-09 00:00:00.000000000 Z
11
+ date: 2026-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: launchy