Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ LetterOpener.configure do |config|
# scheme doesn't work for you.
# Default value is blank
config.file_uri_scheme = 'file://///wsl$/Ubuntu-18.04'

# To control whether emails are automatically opened in the browser.
# Default value is `true`
config.open_in_browser = true

# You can also disable automatic opening completely
config.open_in_browser = false

# Or use a callable to conditionally open emails based on email properties
config.open_in_browser = ->(mail) { mail.to.include?('[email protected]') }

# Example: Only open emails with "urgent" in the subject
config.open_in_browser = ->(mail) { mail.subject&.include?('urgent') }
end
```

Expand All @@ -47,7 +60,9 @@ If you aren't using Rails, this can be easily set up with the Mail gem. Just set
```rb
require "letter_opener"
Mail.defaults do
delivery_method LetterOpener::DeliveryMethod, location: File.expand_path('../tmp/letter_opener', __FILE__)
delivery_method LetterOpener::DeliveryMethod,
location: File.expand_path('../tmp/letter_opener', __FILE__),
open_in_browser: false # Optional: disable automatic browser opening
end
```

Expand All @@ -57,15 +72,20 @@ The method is similar if you're using the Pony gem:
require "letter_opener"
Pony.options = {
via: LetterOpener::DeliveryMethod,
via_options: {location: File.expand_path('../tmp/letter_opener', __FILE__)}
via_options: {
location: File.expand_path('../tmp/letter_opener', __FILE__),
open_in_browser: false # Optional: disable automatic browser opening
}
}
```

Alternatively, if you are using ActionMailer directly (without Rails) you will need to add the delivery method.

```rb
require "letter_opener"
ActionMailer::Base.add_delivery_method :letter_opener, LetterOpener::DeliveryMethod, :location => File.expand_path('../tmp/letter_opener', __FILE__)
ActionMailer::Base.add_delivery_method :letter_opener, LetterOpener::DeliveryMethod,
location: File.expand_path('../tmp/letter_opener', __FILE__),
open_in_browser: false # Optional: disable automatic browser opening
ActionMailer::Base.delivery_method = :letter_opener
```

Expand Down
3 changes: 2 additions & 1 deletion lib/letter_opener/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module LetterOpener
class Configuration
attr_accessor :location, :message_template, :file_uri_scheme
attr_accessor :location, :message_template, :file_uri_scheme, :open_in_browser

def initialize
@location = Rails.root.join('tmp', 'letter_opener') if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
@message_template = 'default'
@file_uri_scheme = nil
@open_in_browser = true
end
end
end
12 changes: 11 additions & 1 deletion lib/letter_opener/delivery_method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def initialize(options = {})
options[:message_template] ||= LetterOpener.configuration.message_template
options[:location] ||= LetterOpener.configuration.location
options[:file_uri_scheme] ||= LetterOpener.configuration.file_uri_scheme
options[:open_in_browser] = options.fetch(:open_in_browser, LetterOpener.configuration.open_in_browser)

raise InvalidOption, "A location option is required when using the Letter Opener delivery method" if options[:location].nil?

Expand All @@ -22,7 +23,16 @@ def deliver!(mail)
location = File.join(settings[:location], "#{Time.now.to_f.to_s.tr('.', '_')}_#{Digest::SHA1.hexdigest(mail.encoded)[0..6]}")

messages = Message.rendered_messages(mail, location: location, message_template: settings[:message_template])
::Launchy.open("#{settings[:file_uri_scheme]}#{messages.first.filepath}")

open_in_browser = settings[:open_in_browser]
should_open = case open_in_browser
when Proc
open_in_browser.call(mail)
else
open_in_browser
end

::Launchy.open("#{settings[:file_uri_scheme]}#{messages.first.filepath}") if should_open
end

private
Expand Down
152 changes: 152 additions & 0 deletions spec/letter_opener/delivery_method_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -413,4 +413,156 @@
end
end
end

context 'open_in_browser configuration' do
after do
LetterOpener.configure do |config|
config.open_in_browser = true
end
end

context 'when open_in_browser is true (default)' do
it 'opens the email in browser' do
expect(Launchy).to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Test message'
end
end
end

context 'when open_in_browser is false' do
before do
Mail.defaults do
delivery_method LetterOpener::DeliveryMethod,
location: File.expand_path('../../../tmp/letter_opener', __FILE__),
open_in_browser: false
end
end

it 'does not open the email in browser' do
expect(Launchy).not_to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Test message'
end
end

it 'still creates the email files' do
expect(Launchy).not_to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Test message'
end

expect(File.exist?(plain_file)).to be_truthy
end
end

context 'when open_in_browser is a proc' do
context 'returning true' do
before do
Mail.defaults do
delivery_method LetterOpener::DeliveryMethod,
location: File.expand_path('../../../tmp/letter_opener', __FILE__),
open_in_browser: ->(mail) { mail.to.include?('[email protected]') }
end
end

it 'opens emails matching the condition' do
expect(Launchy).to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Important message'
end
end

it 'does not open emails not matching the condition' do
expect(Launchy).not_to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Regular message'
end
end
end

context 'with access to mail properties' do
before do
Mail.defaults do
delivery_method LetterOpener::DeliveryMethod,
location: File.expand_path('../../../tmp/letter_opener', __FILE__),
open_in_browser: ->(mail) {
mail.subject && mail.subject.include?('urgent')
}
end
end

it 'opens emails with urgent subject' do
expect(Launchy).to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
subject 'urgent: Please review'
body 'Important message'
end
end

it 'does not open emails without urgent subject' do
expect(Launchy).not_to receive(:open)

Mail.deliver do
from '[email protected]'
to '[email protected]'
subject 'Regular update'
body 'Regular message'
end
end
end
end

context 'when open_in_browser is set via delivery_method options' do
it 'overrides the global configuration when false' do
expect(Launchy).not_to receive(:open)

Mail.defaults do
delivery_method LetterOpener::DeliveryMethod,
location: File.expand_path('../../../tmp/letter_opener', __FILE__),
open_in_browser: false
end

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Test message'
end
end

it 'overrides the global configuration when proc' do
expect(Launchy).to receive(:open)

Mail.defaults do
delivery_method LetterOpener::DeliveryMethod,
location: File.expand_path('../../../tmp/letter_opener', __FILE__),
open_in_browser: ->(mail) { mail.to.include?('[email protected]') }
end

Mail.deliver do
from '[email protected]'
to '[email protected]'
body 'Test message'
end
end
end
end
end