Skip to content

Commit 7cb093b

Browse files
committed
Import Email, EmailFormat, EmailsController
1 parent 0a5ef70 commit 7cb093b

File tree

11 files changed

+333
-19
lines changed

11 files changed

+333
-19
lines changed

.rspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--color

Gemfile.lock

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ GEM
3636
multi_json (~> 1.0)
3737
arel (3.0.2)
3838
builder (3.0.4)
39+
diff-lcs (1.1.3)
3940
erubis (2.7.0)
4041
hike (1.2.1)
4142
i18n (0.6.1)
@@ -76,6 +77,19 @@ GEM
7677
rake (0.9.2.2)
7778
rdoc (3.12)
7879
json (~> 1.4)
80+
rspec (2.11.0)
81+
rspec-core (~> 2.11.0)
82+
rspec-expectations (~> 2.11.0)
83+
rspec-mocks (~> 2.11.0)
84+
rspec-core (2.11.1)
85+
rspec-expectations (2.11.3)
86+
diff-lcs (~> 1.1.3)
87+
rspec-mocks (2.11.3)
88+
rspec-rails (2.11.4)
89+
actionpack (>= 3.0)
90+
activesupport (>= 3.0)
91+
railties (>= 3.0)
92+
rspec (~> 2.11.0)
7993
sprockets (2.1.3)
8094
hike (~> 1.2)
8195
rack (~> 1.0)
@@ -94,4 +108,5 @@ PLATFORMS
94108
DEPENDENCIES
95109
griddler!
96110
jquery-rails
111+
rspec-rails
97112
sqlite3

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
`config/initializer/griddler.rb`
32

43
```

Rakefile

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,9 @@ begin
44
rescue LoadError
55
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
66
end
7-
begin
8-
require 'rdoc/task'
9-
rescue LoadError
10-
require 'rdoc/rdoc'
11-
require 'rake/rdoctask'
12-
RDoc::Task = Rake::RDocTask
13-
end
14-
15-
RDoc::Task.new(:rdoc) do |rdoc|
16-
rdoc.rdoc_dir = 'rdoc'
17-
rdoc.title = 'Griddler'
18-
rdoc.options << '--line-numbers'
19-
rdoc.rdoc_files.include('README.rdoc')
20-
rdoc.rdoc_files.include('lib/**/*.rb')
21-
end
22-
23-
24-
257

268
Bundler::GemHelper.install_tasks
279

10+
require 'rspec/core/rake_task'
11+
RSpec::Core::RakeTask.new(:spec)
12+
task default: :spec

app/controllers/emails_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Griddler::EmailsController < ApplicationController
2+
def create
3+
Griddler::Email.new(params)
4+
head :ok
5+
end
6+
end

config/initializers/griddler.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require 'griddler/email'
2+
require 'griddler/email_format'

lib/griddler/email.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'iconv'
2+
3+
class Griddler::Email
4+
attr_accessor :to, :from, :body, :user, :comment
5+
6+
def initialize(params)
7+
@to = extract_email_address(params[:to])
8+
@from = extract_email_address(params[:from])
9+
@subject = params[:subject]
10+
if params[:charsets]
11+
charsets = ActiveSupport::JSON.decode(params[:charsets])
12+
@body = extract_reply_body(Iconv.new('utf-8', charsets['text']).iconv(params[:text]))
13+
else
14+
@body = extract_reply_body(params[:text])
15+
end
16+
end
17+
18+
private
19+
20+
def extract_email_address(address)
21+
if address
22+
address = address.split('<').last
23+
if matches = address.match(Griddler::EmailFormat::Regex)
24+
address = matches[0]
25+
end
26+
end
27+
address
28+
end
29+
30+
def parse_email(address)
31+
address =~ /^(\d+)@/
32+
end
33+
34+
def extract_reply_body(body)
35+
if body
36+
body.split('Reply ABOVE THIS LINE').first.
37+
split(/^\s*[-]+\s*Original Message\s*[-]+\s*$/).first.
38+
split(/^\s*--\s*$/).first.
39+
split(/[\r]*\n/).reject { |line|
40+
line =~ /^\s*>/ || line =~ /^\s*On.*wrote:$/ || line =~ /^\s*Sent from my /
41+
}.join("\r\n").gsub(/^\s*On.*\r?\n?\s*.*\s*wrote:$/,'').strip
42+
end
43+
end
44+
end

lib/griddler/email_format.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Griddler::EmailFormat
2+
LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~')
3+
LocalPartUnquoted = '(([[:alnum:]' + LocalPartSpecialChars + ']+[\.\+]+))*[[:alnum:]' + LocalPartSpecialChars + '+]+'
4+
LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\u0001-\uFFFF]))*)\"'
5+
Regex = Regexp.new('((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+)|(\w+\.))*\w{1,63}\.[a-z]{2,6})', Regexp::EXTENDED | Regexp::IGNORECASE)
6+
end
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
require 'spec_helper'
2+
3+
describe Griddler::EmailsController do
4+
end

spec/griddler/email_spec.rb

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
require 'spec_helper'
2+
3+
describe Griddler::Email do
4+
it "should handle 'On [date] [soandso] wrote:' format" do
5+
body = <<-EOF
6+
Hello.
7+
8+
On 2010-01-01 12:00:00 Tristan wrote:
9+
> Check out this report.
10+
>
11+
> It's pretty cool.
12+
>
13+
> Thanks, Tristan
14+
EOF
15+
16+
email = Griddler::Email.new(text: body)
17+
email.body.should == 'Hello.'
18+
end
19+
20+
it "should handle 'On [date] [soandso] <[email protected]> wrote:' format" do
21+
body = <<-EOF
22+
Hello.
23+
24+
On 2010-01-01 12:00:00 Tristan <[email protected]> wrote:
25+
> Check out this report.
26+
>
27+
> It's pretty cool.
28+
>
29+
> Thanks, Tristan
30+
EOF
31+
32+
email = Griddler::Email.new(text: body)
33+
email.body.should == 'Hello.'
34+
end
35+
36+
it "should handle 'On [date] [soandso]\n<[email protected]> wrote:' format" do
37+
body = <<-EOF
38+
Hello.
39+
40+
On 2010-01-01 12:00:00 Tristan\n <[email protected]> wrote:
41+
> Check out this report.
42+
>
43+
> It's pretty cool.
44+
>
45+
> Thanks, Tristan
46+
EOF
47+
48+
email = Griddler::Email.new(text: body)
49+
email.body.should == 'Hello.'
50+
end
51+
52+
it "should handle '-----Original Message-----' format" do
53+
body = <<-EOF
54+
Hello.
55+
56+
-----Original Message-----
57+
58+
Sent: Today
59+
Subject: Awesome report.
60+
61+
Check out this report!
62+
EOF
63+
64+
email = Griddler::Email.new(text: body)
65+
email.body.should == 'Hello.'
66+
end
67+
68+
it "should handle 'Reply ABOVE THIS LINE' format" do
69+
body = <<-EOF
70+
Hello.
71+
72+
Reply ABOVE THIS LINE
73+
74+
Hey!
75+
EOF
76+
77+
email = Griddler::Email.new(text: body)
78+
email.body.should == 'Hello.'
79+
end
80+
81+
it "should remove any noncontent things above Reply ABOVE THIS LINE" do
82+
body = <<-EOF
83+
Hello.
84+
85+
On 2010-01-01 12:00:00 Tristan wrote:
86+
87+
> Reply ABOVE THIS LINE
88+
89+
Hey!
90+
EOF
91+
92+
email = Griddler::Email.new(text: body)
93+
email.body.should == 'Hello.'
94+
end
95+
96+
it "should remove any iphone things above Reply ABOVE THIS LINE" do
97+
body = <<-EOF
98+
Hello.
99+
100+
Sent from my iPhone
101+
102+
> Reply ABOVE THIS LINE
103+
104+
Hey!
105+
EOF
106+
107+
email = Griddler::Email.new(text: body)
108+
email.body.should == 'Hello.'
109+
end
110+
111+
it "should remove any signature above Reply ABOVE THIS LINE" do
112+
body = <<-EOF
113+
Hello.
114+
115+
--
116+
Mr. Smith
117+
CEO, company
118+
t: 6174821300
119+
120+
> Reply ABOVE THIS LINE
121+
122+
> Hey!
123+
EOF
124+
125+
email = Griddler::Email.new(text: body)
126+
email.body.should == 'Hello.'
127+
end
128+
129+
it "should remove any signature without space above Reply ABOVE THIS LINE" do
130+
body = <<-EOF
131+
Hello.
132+
133+
--
134+
Mr. Smith
135+
CEO, company
136+
t: 6174821300
137+
138+
> Reply ABOVE THIS LINE
139+
140+
> Hey!
141+
EOF
142+
143+
email = Griddler::Email.new(text: body)
144+
email.body.should == 'Hello.'
145+
end
146+
147+
it "properly handles a json charsets" do
148+
body = <<-EOF
149+
Hello.
150+
151+
--
152+
Mr. Smith
153+
CEO, company
154+
t: 6174821300
155+
156+
> Reply ABOVE THIS LINE
157+
158+
> Hey!
159+
EOF
160+
charsets = {
161+
to: 'UTF-8',
162+
html: 'utf-8',
163+
subject: 'UTF-8',
164+
from: 'UTF-8',
165+
text: 'utf-8'
166+
}.to_json
167+
email = Griddler::Email.new(text: body, charsets: charsets)
168+
169+
email.body.should == 'Hello.'
170+
end
171+
172+
it "should preserve empty lines" do
173+
body = "Hello.\r\n\r\nWhat's up?"
174+
175+
email = Griddler::Email.new(text: body)
176+
email.body.should == body
177+
end
178+
179+
describe "extracting email address" do
180+
before do
181+
@address = "[email protected]"
182+
end
183+
184+
it "should handle normal e-mail address" do
185+
email = Griddler::Email.new(to: @address, from: @address)
186+
email.to.should == @address
187+
email.from.should == @address
188+
end
189+
190+
it "should handle new lines" do
191+
email = Griddler::Email.new(to: "#{@address}\n", from: "#{@address}\n")
192+
email.to.should == @address
193+
email.from.should == @address
194+
end
195+
196+
it "should handle angle brackets around address" do
197+
email = Griddler::Email.new(to: "<#{@address}>", from: "<#{@address}>")
198+
email.to.should == @address
199+
email.from.should == @address
200+
end
201+
202+
it "should handle name and angle brackets around address" do
203+
email = Griddler::Email.new(to: "Bob <#{@address}>", from: "Bob <#{@address}>")
204+
email.to.should == @address
205+
email.from.should == @address
206+
end
207+
208+
it "should handle multiple e-mails, with priority to the bracketed" do
209+
email = Griddler::Email.new(to: "[email protected] <#{@address}>", from: "[email protected] <#{@address}>")
210+
email.to.should == @address
211+
email.to.should == @address
212+
end
213+
end
214+
end

spec/spec_helper.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This file is copied to spec/ when you run 'rails generate rspec:install'
2+
ENV["RAILS_ENV"] ||= 'test'
3+
require File.expand_path("../dummy/config/environment", __FILE__)
4+
require 'rspec/rails'
5+
require 'rspec/autorun'
6+
7+
# Requires supporting ruby files with custom matchers and macros, etc,
8+
# in spec/support/ and its subdirectories.
9+
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10+
11+
RSpec.configure do |config|
12+
# ## Mock Framework
13+
#
14+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
15+
#
16+
# config.mock_with :mocha
17+
# config.mock_with :flexmock
18+
# config.mock_with :rr
19+
20+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
21+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
22+
23+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
24+
# examples within a transaction, remove the following line or assign false
25+
# instead of true.
26+
config.use_transactional_fixtures = true
27+
28+
# If true, the base class of anonymous controllers will be inferred
29+
# automatically. This will be the default behavior in future versions of
30+
# rspec-rails.
31+
config.infer_base_class_for_anonymous_controllers = false
32+
33+
# Run specs in random order to surface order dependencies. If you find an
34+
# order dependency and want to debug it, you can fix the order by providing
35+
# the seed, which is printed after each run.
36+
# --seed 1234
37+
config.order = "random"
38+
end

0 commit comments

Comments
 (0)