letter_opener 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ ## 0.1.0 ##
2
+
3
+ * From and To show name and Email when specified
4
+ * Fix bug when letter_opener couldn't open email in Windows
5
+ * Handle spaces in the application path (thanks Mike Boone)
6
+ * As letter_opener doesn't work with Launchy < 2.0.4 let's depend on >= 2.0.4 (thanks Samnang Chhun)
7
+ * Handle `reply_to` field (thanks Wes Gibbs)
8
+ * Set the charset in email preview (thanks Bruno Michel)
9
+
10
+ ## 0.0.2 ##
11
+
12
+ * Fixing launchy requirement (thanks Bruno Michel)
13
+
14
+ ## 0.0.1 ##
15
+
16
+ * Initial relase
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
1
  source "http://rubygems.org"
2
2
  gemspec
3
+
4
+ gem "rake"
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ryan Bates
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- = Letter Opener
1
+ = Letter Opener {<img src="https://secure.travis-ci.org/ryanb/letter_opener.png" />}[http://travis-ci.org/ryanb/letter_opener]
2
2
 
3
3
  Preview email in the browser instead of sending it. This means you do not need to set up email delivery in your development environment, and you no longer need to worry about accidentally sending a test email to someone else's address.
4
4
 
@@ -28,6 +28,6 @@ If you aren't using Rails, this can be easily set up with the Mail gem. Just set
28
28
 
29
29
  == Development & Feedback
30
30
 
31
- Questions or comments? Please use the {issue tracker}[https://github.com/ryanb/letter_opener/issues]. If you would like to contribute to this project, clone this repository and run +bundle+ and +rake+ to run the tests.
31
+ Questions or problems? Please use the {issue tracker}[https://github.com/ryanb/letter_opener/issues]. If you would like to contribute to this project, fork this repository and run +bundle+ and +rake+ to run the tests. Pull requests appreciated.
32
32
 
33
- Special thanks to the {mail_view}[https://github.com/37signals/mail_view/] gem for inspiring this project and for their mail template.
33
+ Special thanks to the {mail_view}[https://github.com/37signals/mail_view/] gem for inspiring this project and for their mail template. Also thanks to [Vasiliy Ermolovich](https://github.com/nashby) for helping manage this project.
@@ -1,15 +1,17 @@
1
1
  module LetterOpener
2
2
  class DeliveryMethod
3
3
  def initialize(options = {})
4
- @options = {:location => './letter_opener'}.merge!(options)
4
+ self.settings = {:location => './letter_opener'}.merge!(options)
5
5
  end
6
6
 
7
+ attr_accessor :settings
8
+
7
9
  def deliver!(mail)
8
- location = File.join(@options[:location], "#{Time.now.to_i}_#{Digest::SHA1.hexdigest(mail.encoded)[0..6]}")
10
+ location = File.join(settings[:location], "#{Time.now.to_i}_#{Digest::SHA1.hexdigest(mail.encoded)[0..6]}")
9
11
  messages = mail.parts.map { |part| Message.new(location, mail, part) }
10
12
  messages << Message.new(location, mail) if messages.empty?
11
- messages.each { |message| message.render }
12
- Launchy.open("file://#{messages.first.filepath}")
13
+ messages.each(&:render)
14
+ Launchy.open(URI.parse(URI.escape(messages.first.filepath)))
13
15
  end
14
16
  end
15
17
  end
@@ -1,26 +1,25 @@
1
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= encoding %>">
2
+
1
3
  <style type="text/css">
2
4
  #message_headers {
3
- position: absolute;
4
- top: 0px;
5
- left: 0;
6
5
  width: 100%;
7
- height: 85px;
8
6
  padding: 10px 0 0 0;
9
7
  margin: 0;
10
8
  background: #fff;
11
9
  font-size: 12px;
12
10
  font-family: "Lucida Grande";
13
11
  border-bottom: 1px solid #dedede;
14
- overflow: hidden;
12
+ overflow: auto;
15
13
  }
16
14
 
17
15
  #message_headers dl {
18
- margin: 0;
16
+ float: left;
17
+ margin: 0 0 10px 0;
19
18
  padding: 0;
20
19
  }
21
20
 
22
21
  #message_headers dt {
23
- width: 60px;
22
+ width: 62px;
24
23
  padding: 1px;
25
24
  float: left;
26
25
  text-align: right;
@@ -29,14 +28,13 @@
29
28
  }
30
29
 
31
30
  #message_headers dd {
32
- margin-left: 70px;
31
+ margin-left: 72px;
33
32
  padding: 1px;
34
33
  }
35
34
 
36
35
  #message_headers p.alternate {
37
- position: absolute;
38
- top: 0;
39
- right: 15px;
36
+ float: right;
37
+ margin: 0;
40
38
  }
41
39
 
42
40
  #message_headers p.alternate a {
@@ -47,16 +45,17 @@
47
45
  padding: 10px;
48
46
  word-wrap: break-word;
49
47
  }
50
-
51
- body {
52
- margin-top: 96px;
53
- }
54
48
  </style>
55
49
 
56
50
  <div id="message_headers">
57
51
  <dl>
58
52
  <dt>From:</dt>
59
- <dd><%= mail.from.join(", ") %></dd>
53
+ <dd><%= from %></dd>
54
+
55
+ <% unless reply_to.empty? %>
56
+ <dt>Reply-To:</dt>
57
+ <dd><%= reply_to %></dd>
58
+ <% end %>
60
59
 
61
60
  <dt>Subject:</dt>
62
61
  <dd><strong><%= mail.subject %></strong></dd>
@@ -64,8 +63,20 @@
64
63
  <dt>Date:</dt>
65
64
  <dd><%= Time.now.strftime("%b %e, %Y %I:%M:%S %p %Z") %></dd>
66
65
 
67
- <dt>To:</dt>
68
- <dd><%= mail.to.join(", ") %></dd>
66
+ <% unless to.empty? %>
67
+ <dt>To:</dt>
68
+ <dd><%= to %></dd>
69
+ <% end %>
70
+
71
+ <% if mail.cc %>
72
+ <dt>CC:</dt>
73
+ <dd><%= mail.cc.join(", ") %></dd>
74
+ <% end %>
75
+
76
+ <% if mail.bcc %>
77
+ <dt>BCC:</dt>
78
+ <dd><%= mail.bcc.join(", ") %></dd>
79
+ <% end %>
69
80
  </dl>
70
81
 
71
82
  <% if mail.multipart? %>
@@ -84,3 +95,4 @@
84
95
  <% else %>
85
96
  <%= body %>
86
97
  <% end %>
98
+
@@ -28,11 +28,28 @@ module LetterOpener
28
28
  end
29
29
 
30
30
  def body
31
- (@part && @part.body || @mail.body).to_s
31
+ @body ||= (@part && @part.body || @mail.body).to_s
32
+ end
33
+
34
+ def from
35
+ @from ||= Array(@mail.from).join(", ")
36
+ end
37
+
38
+ def to
39
+ @to ||= Array(@mail.to).join(", ")
40
+ end
41
+
42
+ def reply_to
43
+ @reply_to ||= Array(@mail.reply_to).join(", ")
32
44
  end
33
45
 
34
46
  def type
35
47
  content_type =~ /html/ ? "rich" : "plain"
36
48
  end
49
+
50
+ def encoding
51
+ body.respond_to?(:encoding) ? body.encoding : "utf-8"
52
+ end
37
53
  end
38
54
  end
55
+
@@ -1,49 +1,160 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe LetterOpener::DeliveryMethod do
4
- before(:each) do
4
+ let(:location) { File.expand_path('../../../tmp/letter_opener', __FILE__) }
5
+
6
+ before do
5
7
  Launchy.stub(:open)
6
- location = File.expand_path('../../../tmp/letter_opener', __FILE__)
7
8
  FileUtils.rm_rf(location)
9
+ context = self
10
+
8
11
  Mail.defaults do
9
- delivery_method LetterOpener::DeliveryMethod, :location => location
12
+ delivery_method LetterOpener::DeliveryMethod, :location => context.location
10
13
  end
11
- @location = location
12
14
  end
13
15
 
14
- it "saves text into html document" do
15
- Launchy.should_receive(:open)
16
- mail = Mail.deliver do
17
- from 'foo@example.com'
18
- to 'bar@example.com'
19
- subject 'Hello'
20
- body 'World!'
21
- end
22
- text = File.read(Dir["#{@location}/*/plain.html"].first)
23
- text.should include("foo@example.com")
24
- text.should include("bar@example.com")
25
- text.should include("Hello")
26
- text.should include("World!")
16
+ context 'content' do
17
+ let(:plain_file) { Dir["#{location}/*/plain.html"].first }
18
+ let(:plain) { File.read(plain_file) }
19
+
20
+ context 'plain' do
21
+ before do
22
+ Launchy.should_receive(:open)
23
+
24
+ Mail.deliver do
25
+ from 'Foo foo@example.com'
26
+ reply_to 'No Reply no-reply@example.com'
27
+ to 'Bar bar@example.com'
28
+ subject 'Hello'
29
+ body 'World!'
30
+ end
31
+ end
32
+
33
+ it 'creates plain html document' do
34
+ File.exist?(plain_file).should be_true
35
+ end
36
+
37
+ it 'saves From field' do
38
+ plain.should include("Foo foo@example.com")
39
+ end
40
+
41
+ it 'saves Reply-to field' do
42
+ plain.should include("No Reply no-reply@example.com")
43
+ end
44
+
45
+ it 'saves To field' do
46
+ plain.should include("Bar bar@example.com")
47
+ end
48
+
49
+ it 'saves Subject field' do
50
+ plain.should include("Hello")
51
+ end
52
+
53
+ it 'saves Body field' do
54
+ plain.should include("World!")
55
+ end
56
+ end
57
+
58
+ context 'multipart' do
59
+ let(:rich_file) { Dir["#{location}/*/rich.html"].first }
60
+ let(:rich) { File.read(rich_file) }
61
+
62
+ before do
63
+ Launchy.should_receive(:open)
64
+
65
+ Mail.deliver do
66
+ from 'foo@example.com'
67
+ to 'bar@example.com'
68
+ subject 'Many parts'
69
+ text_part do
70
+ body 'This is <plain> text'
71
+ end
72
+ html_part do
73
+ content_type 'text/html; charset=UTF-8'
74
+ body '<h1>This is HTML</h1>'
75
+ end
76
+ end
77
+ end
78
+
79
+ it 'creates plain html document' do
80
+ File.exist?(plain_file).should be_true
81
+ end
82
+
83
+ it 'creates rich html document' do
84
+ File.exist?(rich_file).should be_true
85
+ end
86
+
87
+ it 'shows link to rich html version' do
88
+ plain.should include("View HTML version")
89
+ end
90
+
91
+ it 'saves text part' do
92
+ plain.should include("This is &lt;plain&gt; text")
93
+ end
94
+
95
+ it 'saves html part' do
96
+ rich.should include("<h1>This is HTML</h1>")
97
+ end
98
+ end
27
99
  end
28
100
 
29
- it "saves multipart email into html document" do
30
- mail = Mail.deliver do
31
- from 'foo@example.com'
32
- to 'bar@example.com'
33
- subject 'Many parts'
34
- text_part do
35
- body 'This is <plain> text'
36
- end
37
- html_part do
38
- content_type 'text/html; charset=UTF-8'
39
- body '<h1>This is HTML</h1>'
40
- end
41
- end
42
- text = File.read(Dir["#{@location}/*/plain.html"].first)
43
- text.should include("View HTML version")
44
- text.should include("This is &lt;plain&gt; text")
45
- html = File.read(Dir["#{@location}/*/rich.html"].first)
46
- html.should include("View plain text version")
47
- html.should include("<h1>This is HTML</h1>")
101
+ context 'document with spaces in name' do
102
+ let(:location) { File.expand_path('../../../tmp/letter_opener with space', __FILE__) }
103
+ let(:file) { Dir["#{location}/*/plain.html"].first }
104
+ let(:plain) { File.read(file) }
105
+
106
+ before do
107
+ Launchy.should_receive(:open)
108
+
109
+ Mail.deliver do
110
+ from 'Foo foo@example.com'
111
+ to 'bar@example.com'
112
+ subject 'Hello'
113
+ body 'World!'
114
+ end
115
+ end
116
+
117
+ it 'creates plain html document' do
118
+ File.exist?(file)
119
+ end
120
+
121
+ it 'saves From filed' do
122
+ plain.should include("Foo foo@example.com")
123
+ end
124
+ end
125
+
126
+ context 'using deliver! method' do
127
+ let(:plain_file) { Dir["#{location}/*/plain.html"].first }
128
+ let(:plain) { File.read(plain_file) }
129
+
130
+ before do
131
+ Launchy.should_receive(:open)
132
+ Mail.new do
133
+ from 'foo@example.com'
134
+ to 'bar@example.com'
135
+ subject 'Hello'
136
+ body 'World!'
137
+ end.deliver!
138
+ end
139
+
140
+ it 'creates plain html document' do
141
+ File.exist?(plain_file).should be_true
142
+ end
143
+
144
+ it 'saves From field' do
145
+ plain.should include("foo@example.com")
146
+ end
147
+
148
+ it 'saves To field' do
149
+ plain.should include("bar@example.com")
150
+ end
151
+
152
+ it 'saves Subject field' do
153
+ plain.should include("Hello")
154
+ end
155
+
156
+ it 'saves Body field' do
157
+ plain.should include("World!")
158
+ end
48
159
  end
49
160
  end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe LetterOpener::Message do
4
+ let(:location) { File.expand_path('../../../tmp/letter_opener', __FILE__) }
5
+
6
+ describe '#reply_to' do
7
+ it 'handles one email as a string' do
8
+ message = described_class.new(location, mock(reply_to: 'test@example.com'))
9
+ message.reply_to.should eq('test@example.com')
10
+ end
11
+
12
+ it 'handles array of emails' do
13
+ message = described_class.new(location, mock(reply_to: ['test1@example.com', 'test2@example.com']))
14
+ message.reply_to.should eq('test1@example.com, test2@example.com')
15
+ end
16
+ end
17
+
18
+ describe '#to' do
19
+ it 'handles one email as a string' do
20
+ message = described_class.new(location, mock(to: 'test@example.com'))
21
+ message.to.should eq('test@example.com')
22
+ end
23
+
24
+ it 'handles array of emails' do
25
+ message = described_class.new(location, mock(to: ['test1@example.com', 'test2@example.com']))
26
+ message.to.should eq('test1@example.com, test2@example.com')
27
+ end
28
+ end
29
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,7 +3,9 @@ require 'bundler/setup'
3
3
  Bundler.require(:default)
4
4
 
5
5
  require "mail"
6
- require "launchy"
7
6
 
8
7
  RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.filter_run :focus => true
10
+ config.run_all_when_everything_filtered = true
9
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: letter_opener
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,23 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-07 00:00:00.000000000 -07:00
13
- default_executable:
12
+ date: 2012-10-01 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: launchy
17
- requirement: &2152659820 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
21
20
  - !ruby/object:Gem::Version
22
- version: '0'
21
+ version: 2.0.4
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *2152659820
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.4
26
30
  - !ruby/object:Gem::Dependency
27
31
  name: rspec
28
- requirement: &2152659300 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
29
33
  none: false
30
34
  requirements:
31
35
  - - ~>
@@ -33,10 +37,15 @@ dependencies:
33
37
  version: 2.6.0
34
38
  type: :development
35
39
  prerelease: false
36
- version_requirements: *2152659300
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.6.0
37
46
  - !ruby/object:Gem::Dependency
38
47
  name: mail
39
- requirement: &2152658800 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
40
49
  none: false
41
50
  requirements:
42
51
  - - ~>
@@ -44,7 +53,12 @@ dependencies:
44
53
  version: 2.3.0
45
54
  type: :development
46
55
  prerelease: false
47
- version_requirements: *2152658800
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.0
48
62
  description: When mail is sent from your application, Letter Opener will open a preview
49
63
  in the browser instead of sending.
50
64
  email: ryan@railscasts.com
@@ -58,11 +72,13 @@ files:
58
72
  - lib/letter_opener/railtie.rb
59
73
  - lib/letter_opener.rb
60
74
  - spec/letter_opener/delivery_method_spec.rb
75
+ - spec/letter_opener/message_spec.rb
61
76
  - spec/spec_helper.rb
77
+ - CHANGELOG.md
62
78
  - Gemfile
79
+ - LICENSE
63
80
  - Rakefile
64
81
  - README.rdoc
65
- has_rdoc: true
66
82
  homepage: http://github.com/ryanb/letter_opener
67
83
  licenses: []
68
84
  post_install_message:
@@ -83,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
99
  version: 1.3.4
84
100
  requirements: []
85
101
  rubyforge_project: letter_opener
86
- rubygems_version: 1.6.2
102
+ rubygems_version: 1.8.23
87
103
  signing_key:
88
104
  specification_version: 3
89
105
  summary: Preview mail in browser instead of sending.