mailcatcher 0.5.8 → 0.5.9

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.
data/lib/mail_catcher.rb CHANGED
@@ -1,22 +1,13 @@
1
- require 'open3'
2
-
3
- require 'active_support/all'
1
+ require 'active_support/core_ext'
4
2
  require 'eventmachine'
3
+ require 'open3'
5
4
  require 'optparse'
6
5
  require 'rbconfig'
7
6
  require 'thin'
8
7
 
9
- module MailCatcher
10
- extend ActiveSupport::Autoload
11
-
12
- autoload :Events
13
- autoload :Growl
14
- autoload :Mail
15
- autoload :Smtp
16
- autoload :Web
17
-
18
- module_function
8
+ require 'mail_catcher/version'
19
9
 
10
+ module MailCatcher extend self
20
11
  def which command
21
12
  Open3.popen3 'which', 'command' do |stdin, stdout, stderr|
22
13
  return stdout.read.chomp.presence
@@ -55,7 +46,7 @@ module_function
55
46
  end
56
47
  end
57
48
 
58
- @@defaults = {
49
+ @defaults = {
59
50
  :smtp_ip => '127.0.0.1',
60
51
  :smtp_port => '1025',
61
52
  :http_ip => '127.0.0.1',
@@ -66,11 +57,11 @@ module_function
66
57
  :browse => false,
67
58
  }
68
59
 
69
- def parse! arguments=ARGV, defaults=@@defaults
70
- @@defaults.dup.tap do |options|
60
+ def parse! arguments=ARGV, defaults=@defaults
61
+ @defaults.dup.tap do |options|
71
62
  OptionParser.new do |parser|
72
63
  parser.banner = "Usage: mailcatcher [options]"
73
- parser.version = File.read(File.expand_path("../../VERSION", __FILE__))
64
+ parser.version = VERSION
74
65
 
75
66
  parser.on("--ip IP", "Set the ip address of both servers") do |ip|
76
67
  options[:smtp_ip] = options[:http_ip] = ip
@@ -131,7 +122,7 @@ module_function
131
122
 
132
123
  def run! options=nil
133
124
  # If we are passed options, fill in the blanks
134
- options &&= @@defaults.merge options
125
+ options &&= @defaults.merge options
135
126
  # Otherwise, parse them from ARGV
136
127
  options ||= parse!
137
128
 
@@ -182,7 +173,6 @@ module_function
182
173
  end
183
174
 
184
175
  protected
185
- module_function
186
176
 
187
177
  def rescue_port port
188
178
  begin
@@ -192,10 +182,16 @@ module_function
192
182
  rescue RuntimeError
193
183
  if $!.to_s =~ /\bno acceptor\b/
194
184
  puts "~~> ERROR: Something's using port #{port}. Are you already running MailCatcher?"
195
- exit -1
185
+ exit(-1)
196
186
  else
197
187
  raise
198
188
  end
199
189
  end
200
190
  end
201
191
  end
192
+
193
+ require 'mail_catcher/events'
194
+ require 'mail_catcher/growl'
195
+ require 'mail_catcher/mail'
196
+ require 'mail_catcher/smtp'
197
+ require 'mail_catcher/web'
@@ -2,4 +2,4 @@ require 'eventmachine'
2
2
 
3
3
  module MailCatcher::Events
4
4
  MessageAdded = EventMachine::Channel.new
5
- end
5
+ end
@@ -1,6 +1,5 @@
1
1
  module MailCatcher
2
- module Growl
3
- module_function
2
+ module Growl extend self
4
3
  def start
5
4
  MailCatcher::Events::MessageAdded.subscribe MailCatcher::Growl.method :notify
6
5
  end
@@ -1,12 +1,11 @@
1
+ require 'active_support/json'
1
2
  require 'mail'
2
3
  require 'sqlite3'
3
4
  require 'eventmachine'
4
5
 
5
- module MailCatcher::Mail
6
- module_function
7
-
6
+ module MailCatcher::Mail extend self
8
7
  def db
9
- @@__db ||= begin
8
+ @__db ||= begin
10
9
  SQLite3::Database.new(':memory:', :type_translation => true).tap do |db|
11
10
  db.execute(<<-SQL)
12
11
  CREATE TABLE message (
@@ -39,10 +38,10 @@ module_function
39
38
  end
40
39
 
41
40
  def add_message(message)
42
- @@add_message_query ||= db.prepare("INSERT INTO message (sender, recipients, subject, source, type, size, created_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now'))")
41
+ @add_message_query ||= db.prepare("INSERT INTO message (sender, recipients, subject, source, type, size, created_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now'))")
43
42
 
44
43
  mail = Mail.new(message[:source])
45
- result = @@add_message_query.execute(message[:sender], message[:recipients].to_json, mail.subject, message[:source], mail.mime_type || 'text/plain', message[:source].length)
44
+ @add_message_query.execute(message[:sender], message[:recipients].to_json, mail.subject, message[:source], mail.mime_type || 'text/plain', message[:source].length)
46
45
  message_id = db.last_insert_row_id
47
46
  parts = mail.all_parts
48
47
  parts = [mail] if parts.empty?
@@ -60,18 +59,18 @@ module_function
60
59
  end
61
60
 
62
61
  def add_message_part(*args)
63
- @@add_message_part_query ||= db.prepare "INSERT INTO message_part (message_id, cid, type, is_attachment, filename, charset, body, size, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))"
64
- @@add_message_part_query.execute(*args)
62
+ @add_message_part_query ||= db.prepare "INSERT INTO message_part (message_id, cid, type, is_attachment, filename, charset, body, size, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))"
63
+ @add_message_part_query.execute(*args)
65
64
  end
66
65
 
67
66
  def latest_created_at
68
- @@latest_created_at_query ||= db.prepare "SELECT created_at FROM message ORDER BY created_at DESC LIMIT 1"
69
- @@latest_created_at_query.execute.next
67
+ @latest_created_at_query ||= db.prepare "SELECT created_at FROM message ORDER BY created_at DESC LIMIT 1"
68
+ @latest_created_at_query.execute.next
70
69
  end
71
70
 
72
71
  def messages
73
- @@messages_query ||= db.prepare "SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at ASC"
74
- @@messages_query.execute.map do |row|
72
+ @messages_query ||= db.prepare "SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at ASC"
73
+ @messages_query.execute.map do |row|
75
74
  Hash[row.fields.zip(row)].tap do |message|
76
75
  message["recipients"] &&= ActiveSupport::JSON.decode message["recipients"]
77
76
  end
@@ -79,46 +78,46 @@ module_function
79
78
  end
80
79
 
81
80
  def message(id)
82
- @@message_query ||= db.prepare "SELECT * FROM message WHERE id = ? LIMIT 1"
83
- row = @@message_query.execute(id).next
81
+ @message_query ||= db.prepare "SELECT * FROM message WHERE id = ? LIMIT 1"
82
+ row = @message_query.execute(id).next
84
83
  row && Hash[row.fields.zip(row)].tap do |message|
85
84
  message["recipients"] &&= ActiveSupport::JSON.decode message["recipients"]
86
85
  end
87
86
  end
88
87
 
89
88
  def message_has_html?(id)
90
- @@message_has_html_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type IN ('application/xhtml+xml', 'text/html') LIMIT 1"
91
- (!!@@message_has_html_query.execute(id).next) || ['text/html', 'application/xhtml+xml'].include?(message(id)["type"])
89
+ @message_has_html_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type IN ('application/xhtml+xml', 'text/html') LIMIT 1"
90
+ (!!@message_has_html_query.execute(id).next) || ['text/html', 'application/xhtml+xml'].include?(message(id)["type"])
92
91
  end
93
92
 
94
93
  def message_has_plain?(id)
95
- @@message_has_plain_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type = 'text/plain' LIMIT 1"
96
- (!!@@message_has_plain_query.execute(id).next) || message(id)["type"] == "text/plain"
94
+ @message_has_plain_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type = 'text/plain' LIMIT 1"
95
+ (!!@message_has_plain_query.execute(id).next) || message(id)["type"] == "text/plain"
97
96
  end
98
97
 
99
98
  def message_parts(id)
100
- @@message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? ORDER BY filename ASC"
101
- @@message_parts_query.execute(id).map do |row|
99
+ @message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? ORDER BY filename ASC"
100
+ @message_parts_query.execute(id).map do |row|
102
101
  Hash[row.fields.zip(row)]
103
102
  end
104
103
  end
105
104
 
106
105
  def message_attachments(id)
107
- @@message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? AND is_attachment = 1 ORDER BY filename ASC"
108
- @@message_parts_query.execute(id).map do |row|
106
+ @message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? AND is_attachment = 1 ORDER BY filename ASC"
107
+ @message_parts_query.execute(id).map do |row|
109
108
  Hash[row.fields.zip(row)]
110
109
  end
111
110
  end
112
111
 
113
112
  def message_part(message_id, part_id)
114
- @@message_part_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND id = ? LIMIT 1"
115
- row = @@message_part_query.execute(message_id, part_id).next
113
+ @message_part_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND id = ? LIMIT 1"
114
+ row = @message_part_query.execute(message_id, part_id).next
116
115
  row && Hash[row.fields.zip(row)]
117
116
  end
118
117
 
119
118
  def message_part_type(message_id, part_type)
120
- @@message_part_type_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND type = ? AND is_attachment = 0 LIMIT 1"
121
- row = @@message_part_type_query.execute(message_id, part_type).next
119
+ @message_part_type_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND type = ? AND is_attachment = 0 LIMIT 1"
120
+ row = @message_part_type_query.execute(message_id, part_type).next
122
121
  row && Hash[row.fields.zip(row)]
123
122
  end
124
123
 
@@ -136,19 +135,19 @@ module_function
136
135
  end
137
136
 
138
137
  def message_part_cid(message_id, cid)
139
- @@message_part_cid_query ||= db.prepare 'SELECT * FROM message_part WHERE message_id = ?'
140
- @@message_part_cid_query.execute(message_id).map do |row|
141
- part = Hash[row.fields.zip(row)]
138
+ @message_part_cid_query ||= db.prepare 'SELECT * FROM message_part WHERE message_id = ?'
139
+ @message_part_cid_query.execute(message_id).map do |row|
140
+ Hash[row.fields.zip(row)]
142
141
  end.find do |part|
143
142
  part["cid"] == cid
144
143
  end
145
144
  end
146
145
 
147
146
  def delete!
148
- @@delete_messages_query ||= db.prepare 'DELETE FROM message'
149
- @@delete_message_parts_query ||= db.prepare 'DELETE FROM message_part'
147
+ @delete_messages_query ||= db.prepare 'DELETE FROM message'
148
+ @delete_message_parts_query ||= db.prepare 'DELETE FROM message_part'
150
149
 
151
- @@delete_messages_query.execute and
152
- @@delete_message_parts_query.execute
150
+ @delete_messages_query.execute and
151
+ @delete_message_parts_query.execute
153
152
  end
154
153
  end
@@ -34,7 +34,10 @@ class MailCatcher::Smtp < EventMachine::Protocols::SmtpServer
34
34
 
35
35
  def receive_data_chunk(lines)
36
36
  current_message[:source] ||= ""
37
- current_message[:source] += lines.join("\n")
37
+ lines.each do |line|
38
+ # RFC821 4.5.2 says leading periods should be stripped from the body data.
39
+ current_message[:source] << line.sub(/\A\./, "") << "\n"
40
+ end
38
41
  true
39
42
  end
40
43
 
@@ -0,0 +1,3 @@
1
+ module MailCatcher
2
+ VERSION = "0.5.9"
3
+ end
Binary file
@@ -16,77 +16,93 @@ time, mark, audio, video {
16
16
  border: 0;
17
17
  font-size: 100%;
18
18
  font: inherit;
19
- vertical-align: baseline; }
19
+ vertical-align: baseline;
20
+ }
20
21
 
21
22
  body {
22
- line-height: 1; }
23
+ line-height: 1;
24
+ }
23
25
 
24
26
  ol, ul {
25
- list-style: none; }
27
+ list-style: none;
28
+ }
26
29
 
27
30
  table {
28
31
  border-collapse: collapse;
29
- border-spacing: 0; }
32
+ border-spacing: 0;
33
+ }
30
34
 
31
35
  caption, th, td {
32
36
  text-align: left;
33
37
  font-weight: normal;
34
- vertical-align: middle; }
38
+ vertical-align: middle;
39
+ }
35
40
 
36
41
  q, blockquote {
37
- quotes: none; }
38
- q:before, q:after, blockquote:before, blockquote:after {
39
- content: "";
40
- content: none; }
42
+ quotes: none;
43
+ }
44
+ q:before, q:after, blockquote:before, blockquote:after {
45
+ content: "";
46
+ content: none;
47
+ }
41
48
 
42
49
  a img {
43
- border: none; }
50
+ border: none;
51
+ }
44
52
 
45
53
  article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
46
- display: block; }
54
+ display: block;
55
+ }
47
56
 
48
57
  html, body {
49
58
  width: 100%;
50
- height: 100%; }
59
+ height: 100%;
60
+ }
51
61
 
52
62
  body {
53
- display: -moz-box;
54
63
  display: -webkit-box;
64
+ display: -moz-box;
55
65
  display: -ms-box;
56
66
  display: box;
57
- -moz-box-orient: vertical;
58
67
  -webkit-box-orient: vertical;
68
+ -moz-box-orient: vertical;
59
69
  -ms-box-orient: vertical;
60
70
  box-orient: vertical;
61
71
  background: #eeeeee;
62
72
  color: black;
63
73
  font-size: 12px;
64
- font-family: Helvetica, sans-serif; }
65
- body body {
66
- font-size: 75%;
67
- line-height: 2em; }
68
- body html > body {
69
- font-size: 12px; }
70
- body.iframe {
71
- background: white; }
72
- body.iframe h1 {
73
- font-size: 1.3em;
74
- margin: 12px; }
75
- body.iframe p, body.iframe form {
76
- margin: 0 12px 12px 12px;
77
- line-height: 1.25; }
78
- body.iframe .loading {
79
- color: #666666;
80
- margin-left: 0.5em; }
74
+ font-family: Helvetica, sans-serif;
75
+ }
76
+ body body {
77
+ font-size: 75%;
78
+ line-height: 2em;
79
+ }
80
+ body html > body {
81
+ font-size: 12px;
82
+ }
83
+ body.iframe {
84
+ background: white;
85
+ }
86
+ body.iframe h1 {
87
+ font-size: 1.3em;
88
+ margin: 12px;
89
+ }
90
+ body.iframe p, body.iframe form {
91
+ margin: 0 12px 12px 12px;
92
+ line-height: 1.25;
93
+ }
94
+ body.iframe .loading {
95
+ color: #666666;
96
+ margin-left: 0.5em;
97
+ }
81
98
 
82
99
  .button {
83
100
  padding: 0.5em 1em;
84
101
  border: 1px solid #cccccc;
85
- -moz-border-radius: 2px;
86
102
  -webkit-border-radius: 2px;
87
- -o-border-radius: 2px;
103
+ -moz-border-radius: 2px;
88
104
  -ms-border-radius: 2px;
89
- -khtml-border-radius: 2px;
105
+ -o-border-radius: 2px;
90
106
  border-radius: 2px;
91
107
  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f4f4f4), color-stop(100%, #ececec)), #ececec;
92
108
  background: -webkit-linear-gradient(#f4f4f4, #ececec), #ececec;
@@ -96,99 +112,115 @@ body {
96
112
  background: linear-gradient(#f4f4f4, #ececec), #ececec;
97
113
  color: #666666;
98
114
  text-shadow: 1px 1px 0 white;
99
- text-decoration: none; }
100
- .button:hover, .button:focus {
101
- border-color: #999999;
102
- border-bottom-color: #666666;
103
- background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)), #dddddd;
104
- background: -webkit-linear-gradient(#eeeeee, #dddddd), #dddddd;
105
- background: -moz-linear-gradient(#eeeeee, #dddddd), #dddddd;
106
- background: -o-linear-gradient(#eeeeee, #dddddd), #dddddd;
107
- background: -ms-linear-gradient(#eeeeee, #dddddd), #dddddd;
108
- background: linear-gradient(#eeeeee, #dddddd), #dddddd;
109
- color: #333333;
110
- text-decoration: none; }
111
- .button:active, .button.active {
112
- border-color: #666666;
113
- border-bottom-color: #999999;
114
- background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dddddd), color-stop(100%, #eeeeee)), #eeeeee;
115
- background: -webkit-linear-gradient(#dddddd, #eeeeee), #eeeeee;
116
- background: -moz-linear-gradient(#dddddd, #eeeeee), #eeeeee;
117
- background: -o-linear-gradient(#dddddd, #eeeeee), #eeeeee;
118
- background: -ms-linear-gradient(#dddddd, #eeeeee), #eeeeee;
119
- background: linear-gradient(#dddddd, #eeeeee), #eeeeee;
120
- color: #333333;
121
- text-decoration: none;
122
- text-shadow: -1px -1px 0 #eeeeee; }
115
+ text-decoration: none;
116
+ }
117
+ .button:hover, .button:focus {
118
+ border-color: #999999;
119
+ border-bottom-color: #666666;
120
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)), #dddddd;
121
+ background: -webkit-linear-gradient(#eeeeee, #dddddd), #dddddd;
122
+ background: -moz-linear-gradient(#eeeeee, #dddddd), #dddddd;
123
+ background: -o-linear-gradient(#eeeeee, #dddddd), #dddddd;
124
+ background: -ms-linear-gradient(#eeeeee, #dddddd), #dddddd;
125
+ background: linear-gradient(#eeeeee, #dddddd), #dddddd;
126
+ color: #333333;
127
+ text-decoration: none;
128
+ }
129
+ .button:active, .button.active {
130
+ border-color: #666666;
131
+ border-bottom-color: #999999;
132
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dddddd), color-stop(100%, #eeeeee)), #eeeeee;
133
+ background: -webkit-linear-gradient(#dddddd, #eeeeee), #eeeeee;
134
+ background: -moz-linear-gradient(#dddddd, #eeeeee), #eeeeee;
135
+ background: -o-linear-gradient(#dddddd, #eeeeee), #eeeeee;
136
+ background: -ms-linear-gradient(#dddddd, #eeeeee), #eeeeee;
137
+ background: linear-gradient(#dddddd, #eeeeee), #eeeeee;
138
+ color: #333333;
139
+ text-decoration: none;
140
+ text-shadow: -1px -1px 0 #eeeeee;
141
+ }
123
142
 
124
143
  body > header {
125
144
  overflow: hidden;
126
145
  *zoom: 1;
127
- border-bottom: 1px solid #cccccc; }
128
- body > header h1 {
129
- float: left;
130
- margin-left: 6px;
131
- padding: 6px;
132
- padding-left: 30px;
133
- background: url(/images/logo.png) left no-repeat;
134
- font-size: 18px;
135
- font-weight: bold; }
136
- body > header h1 a {
137
- color: black;
138
- text-decoration: none;
139
- text-shadow: 0 1px 0 white;
140
- -moz-transition: 0.1s ease;
141
- -webkit-transition: 0.1s ease;
142
- -o-transition: 0.1s ease;
143
- transition: 0.1s ease; }
144
- body > header h1 a:hover {
145
- color: #4183c4; }
146
- body > header nav {
147
- border-left: 1px solid #cccccc; }
148
- body > header nav.project {
149
- float: left; }
150
- body > header nav.app {
151
- float: right; }
152
- body > header nav li {
153
- display: block;
154
- float: left;
155
- border-left: 1px solid white;
156
- border-right: 1px solid #cccccc; }
157
- body > header nav li input {
158
- margin: 6px; }
159
- body > header nav li a {
160
- display: block;
161
- padding: 10px;
162
- text-decoration: none;
163
- text-shadow: 0 1px 0 white;
164
- background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f4f4f4), color-stop(100%, #ececec)), #ececec;
165
- background: -webkit-linear-gradient(#f4f4f4, #ececec), #ececec;
166
- background: -moz-linear-gradient(#f4f4f4, #ececec), #ececec;
167
- background: -o-linear-gradient(#f4f4f4, #ececec), #ececec;
168
- background: -ms-linear-gradient(#f4f4f4, #ececec), #ececec;
169
- background: linear-gradient(#f4f4f4, #ececec), #ececec;
170
- color: #666666;
171
- text-shadow: 1px 1px 0 white;
172
- text-decoration: none; }
173
- body > header nav li a:hover, body > header nav li a:focus {
174
- background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)), #dddddd;
175
- background: -webkit-linear-gradient(#eeeeee, #dddddd), #dddddd;
176
- background: -moz-linear-gradient(#eeeeee, #dddddd), #dddddd;
177
- background: -o-linear-gradient(#eeeeee, #dddddd), #dddddd;
178
- background: -ms-linear-gradient(#eeeeee, #dddddd), #dddddd;
179
- background: linear-gradient(#eeeeee, #dddddd), #dddddd;
180
- color: #333333;
181
- text-decoration: none; }
182
- body > header nav li a:active, body > header nav li a.active {
183
- background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dddddd), color-stop(100%, #eeeeee)), #eeeeee;
184
- background: -webkit-linear-gradient(#dddddd, #eeeeee), #eeeeee;
185
- background: -moz-linear-gradient(#dddddd, #eeeeee), #eeeeee;
186
- background: -o-linear-gradient(#dddddd, #eeeeee), #eeeeee;
187
- background: -ms-linear-gradient(#dddddd, #eeeeee), #eeeeee;
188
- background: linear-gradient(#dddddd, #eeeeee), #eeeeee;
189
- color: #333333;
190
- text-decoration: none;
191
- text-shadow: -1px -1px 0 #eeeeee; }
146
+ border-bottom: 1px solid #cccccc;
147
+ }
148
+ body > header h1 {
149
+ float: left;
150
+ margin-left: 6px;
151
+ padding: 6px;
152
+ padding-left: 30px;
153
+ background: url(/images/logo.png) left no-repeat;
154
+ font-size: 18px;
155
+ font-weight: bold;
156
+ }
157
+ body > header h1 a {
158
+ color: black;
159
+ text-decoration: none;
160
+ text-shadow: 0 1px 0 white;
161
+ -webkit-transition: 0.1s ease;
162
+ -moz-transition: 0.1s ease;
163
+ -ms-transition: 0.1s ease;
164
+ -o-transition: 0.1s ease;
165
+ transition: 0.1s ease;
166
+ }
167
+ body > header h1 a:hover {
168
+ color: #4183c4;
169
+ }
170
+ body > header nav {
171
+ border-left: 1px solid #cccccc;
172
+ }
173
+ body > header nav.project {
174
+ float: left;
175
+ }
176
+ body > header nav.app {
177
+ float: right;
178
+ }
179
+ body > header nav li {
180
+ display: block;
181
+ float: left;
182
+ border-left: 1px solid white;
183
+ border-right: 1px solid #cccccc;
184
+ }
185
+ body > header nav li input {
186
+ margin: 6px;
187
+ }
188
+ body > header nav li a {
189
+ display: block;
190
+ padding: 10px;
191
+ text-decoration: none;
192
+ text-shadow: 0 1px 0 white;
193
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f4f4f4), color-stop(100%, #ececec)), #ececec;
194
+ background: -webkit-linear-gradient(#f4f4f4, #ececec), #ececec;
195
+ background: -moz-linear-gradient(#f4f4f4, #ececec), #ececec;
196
+ background: -o-linear-gradient(#f4f4f4, #ececec), #ececec;
197
+ background: -ms-linear-gradient(#f4f4f4, #ececec), #ececec;
198
+ background: linear-gradient(#f4f4f4, #ececec), #ececec;
199
+ color: #666666;
200
+ text-shadow: 1px 1px 0 white;
201
+ text-decoration: none;
202
+ }
203
+ body > header nav li a:hover, body > header nav li a:focus {
204
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)), #dddddd;
205
+ background: -webkit-linear-gradient(#eeeeee, #dddddd), #dddddd;
206
+ background: -moz-linear-gradient(#eeeeee, #dddddd), #dddddd;
207
+ background: -o-linear-gradient(#eeeeee, #dddddd), #dddddd;
208
+ background: -ms-linear-gradient(#eeeeee, #dddddd), #dddddd;
209
+ background: linear-gradient(#eeeeee, #dddddd), #dddddd;
210
+ color: #333333;
211
+ text-decoration: none;
212
+ }
213
+ body > header nav li a:active, body > header nav li a.active {
214
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dddddd), color-stop(100%, #eeeeee)), #eeeeee;
215
+ background: -webkit-linear-gradient(#dddddd, #eeeeee), #eeeeee;
216
+ background: -moz-linear-gradient(#dddddd, #eeeeee), #eeeeee;
217
+ background: -o-linear-gradient(#dddddd, #eeeeee), #eeeeee;
218
+ background: -ms-linear-gradient(#dddddd, #eeeeee), #eeeeee;
219
+ background: linear-gradient(#dddddd, #eeeeee), #eeeeee;
220
+ color: #333333;
221
+ text-decoration: none;
222
+ text-shadow: -1px -1px 0 #eeeeee;
223
+ }
192
224
 
193
225
  #messages {
194
226
  width: 100%;
@@ -196,182 +228,226 @@ body > header {
196
228
  min-height: 3em;
197
229
  overflow: auto;
198
230
  background: white;
199
- border-top: 1px solid white; }
200
- #messages table {
201
- overflow: hidden;
202
- *zoom: 1;
203
- width: 100%; }
204
- #messages table thead tr {
205
- background: #eeeeee;
206
- color: #333333; }
207
- #messages table thead tr th {
208
- padding: 0.25em;
209
- font-weight: bold;
210
- color: #666666;
211
- text-shadow: 0 1px 0 white; }
212
- #messages table tbody tr {
213
- cursor: pointer;
214
- -moz-transition: 0.1s ease;
215
- -webkit-transition: 0.1s ease;
216
- -o-transition: 0.1s ease;
217
- transition: 0.1s ease;
218
- color: #333333; }
219
- #messages table tbody tr:hover {
220
- color: black; }
221
- #messages table tbody tr:nth-child(even) {
222
- background: #f0f0f0; }
223
- #messages table tbody tr.selected {
224
- background: Highlight;
225
- color: HighlightText; }
226
- #messages table tbody tr td {
227
- padding: 0.25em; }
228
- #messages table tbody tr td.blank {
229
- color: #666666;
230
- font-style: italic; }
231
+ border-top: 1px solid white;
232
+ }
233
+ #messages table {
234
+ overflow: hidden;
235
+ *zoom: 1;
236
+ width: 100%;
237
+ }
238
+ #messages table thead tr {
239
+ background: #eeeeee;
240
+ color: #333333;
241
+ }
242
+ #messages table thead tr th {
243
+ padding: 0.25em;
244
+ font-weight: bold;
245
+ color: #666666;
246
+ text-shadow: 0 1px 0 white;
247
+ }
248
+ #messages table tbody tr {
249
+ cursor: pointer;
250
+ -webkit-transition: 0.1s ease;
251
+ -moz-transition: 0.1s ease;
252
+ -ms-transition: 0.1s ease;
253
+ -o-transition: 0.1s ease;
254
+ transition: 0.1s ease;
255
+ color: #333333;
256
+ }
257
+ #messages table tbody tr:hover {
258
+ color: black;
259
+ }
260
+ #messages table tbody tr:nth-child(even) {
261
+ background: #f0f0f0;
262
+ }
263
+ #messages table tbody tr.selected {
264
+ background: Highlight;
265
+ color: HighlightText;
266
+ }
267
+ #messages table tbody tr td {
268
+ padding: 0.25em;
269
+ }
270
+ #messages table tbody tr td.blank {
271
+ color: #666666;
272
+ font-style: italic;
273
+ }
231
274
 
232
275
  #resizer {
233
276
  padding-bottom: 5px;
234
- cursor: ns-resize; }
235
- #resizer .ruler {
236
- border-top: 1px solid #cccccc;
237
- border-bottom: 1px solid white; }
277
+ cursor: ns-resize;
278
+ }
279
+ #resizer .ruler {
280
+ border-top: 1px solid #cccccc;
281
+ border-bottom: 1px solid white;
282
+ }
238
283
 
239
284
  #message {
240
- display: -moz-box;
241
285
  display: -webkit-box;
286
+ display: -moz-box;
242
287
  display: -ms-box;
243
288
  display: box;
244
- -moz-box-orient: vertical;
245
289
  -webkit-box-orient: vertical;
290
+ -moz-box-orient: vertical;
246
291
  -ms-box-orient: vertical;
247
292
  box-orient: vertical;
248
- -moz-box-flex: 1;
249
293
  -webkit-box-flex: 1;
294
+ -moz-box-flex: 1;
250
295
  -ms-box-flex: 1;
251
- box-flex: 1; }
252
- #message > header {
253
- overflow: hidden;
254
- *zoom: 1; }
255
- #message > header .metadata {
256
- overflow: hidden;
257
- *zoom: 1;
258
- padding: 0.5em;
259
- padding-top: 0; }
260
- #message > header .metadata dt, #message > header .metadata dd {
261
- padding: 0.25em; }
262
- #message > header .metadata dt {
263
- float: left;
264
- clear: left;
265
- width: 8em;
266
- margin-right: 0.5em;
267
- text-align: right;
268
- font-weight: bold;
269
- color: #666666;
270
- text-shadow: 0 1px 0 white; }
271
- #message > header .metadata dd.subject {
272
- font-weight: bold; }
273
- #message > header .metadata .attachments {
274
- display: none; }
275
- #message > header .metadata .attachments ul {
276
- display: inline; }
277
- #message > header .metadata .attachments ul li {
278
- display: -moz-inline-box;
279
- -moz-box-orient: vertical;
280
- display: inline-block;
281
- vertical-align: middle;
282
- *vertical-align: auto;
283
- margin-right: 0.5em; }
284
- #message > header .metadata .attachments ul li {
285
- *display: inline; }
286
- #message > header .views ul {
287
- padding: 0 0.5em;
288
- border-bottom: 1px solid #cccccc; }
289
- #message > header .views .tab {
290
- display: -moz-inline-box;
291
- -moz-box-orient: vertical;
292
- display: inline-block;
293
- vertical-align: middle;
294
- *vertical-align: auto; }
295
- #message > header .views .tab {
296
- *display: inline; }
297
- #message > header .views .tab a {
298
- display: -moz-inline-box;
299
- -moz-box-orient: vertical;
300
- display: inline-block;
301
- vertical-align: middle;
302
- *vertical-align: auto;
303
- padding: 0.5em;
304
- border: 1px solid #cccccc;
305
- background: #dddddd;
306
- color: #333333;
307
- border-width: 1px 1px 0 1px;
308
- cursor: pointer;
309
- text-shadow: 0 1px 0 #eeeeee;
310
- text-decoration: none; }
311
- #message > header .views .tab a {
312
- *display: inline; }
313
- #message > header .views .tab:not(.selected):hover a {
314
- background-color: #eeeeee; }
315
- #message > header .views .tab.selected a {
316
- background: white;
317
- color: black;
318
- height: 13px;
319
- -moz-box-shadow: 1px 1px 0 #cccccc;
320
- -webkit-box-shadow: 1px 1px 0 #cccccc;
321
- -o-box-shadow: 1px 1px 0 #cccccc;
322
- box-shadow: 1px 1px 0 #cccccc;
323
- margin-bottom: -2px;
324
- cursor: default; }
325
- #message > header .views .action {
326
- display: -moz-inline-box;
327
- -moz-box-orient: vertical;
328
- display: inline-block;
329
- vertical-align: middle;
330
- *vertical-align: auto;
331
- float: right;
332
- margin: 0 0.25em; }
333
- #message > header .views .action {
334
- *display: inline; }
296
+ box-flex: 1;
297
+ }
298
+ #message > header {
299
+ overflow: hidden;
300
+ *zoom: 1;
301
+ }
302
+ #message > header .metadata {
303
+ overflow: hidden;
304
+ *zoom: 1;
305
+ padding: 0.5em;
306
+ padding-top: 0;
307
+ }
308
+ #message > header .metadata dt, #message > header .metadata dd {
309
+ padding: 0.25em;
310
+ }
311
+ #message > header .metadata dt {
312
+ float: left;
313
+ clear: left;
314
+ width: 8em;
315
+ margin-right: 0.5em;
316
+ text-align: right;
317
+ font-weight: bold;
318
+ color: #666666;
319
+ text-shadow: 0 1px 0 white;
320
+ }
321
+ #message > header .metadata dd.subject {
322
+ font-weight: bold;
323
+ }
324
+ #message > header .metadata .attachments {
325
+ display: none;
326
+ }
327
+ #message > header .metadata .attachments ul {
328
+ display: inline;
329
+ }
330
+ #message > header .metadata .attachments ul li {
331
+ display: -moz-inline-box;
332
+ -moz-box-orient: vertical;
333
+ display: inline-block;
334
+ vertical-align: middle;
335
+ *vertical-align: auto;
336
+ margin-right: 0.5em;
337
+ }
338
+ #message > header .metadata .attachments ul li {
339
+ *display: inline;
340
+ }
341
+ #message > header .views ul {
342
+ padding: 0 0.5em;
343
+ border-bottom: 1px solid #cccccc;
344
+ }
345
+ #message > header .views .tab {
346
+ display: -moz-inline-box;
347
+ -moz-box-orient: vertical;
348
+ display: inline-block;
349
+ vertical-align: middle;
350
+ *vertical-align: auto;
351
+ }
352
+ #message > header .views .tab {
353
+ *display: inline;
354
+ }
355
+ #message > header .views .tab a {
356
+ display: -moz-inline-box;
357
+ -moz-box-orient: vertical;
358
+ display: inline-block;
359
+ vertical-align: middle;
360
+ *vertical-align: auto;
361
+ padding: 0.5em;
362
+ border: 1px solid #cccccc;
363
+ background: #dddddd;
364
+ color: #333333;
365
+ border-width: 1px 1px 0 1px;
366
+ cursor: pointer;
367
+ text-shadow: 0 1px 0 #eeeeee;
368
+ text-decoration: none;
369
+ }
370
+ #message > header .views .tab a {
371
+ *display: inline;
372
+ }
373
+ #message > header .views .tab:not(.selected):hover a {
374
+ background-color: #eeeeee;
375
+ }
376
+ #message > header .views .tab.selected a {
377
+ background: white;
378
+ color: black;
379
+ height: 13px;
380
+ -webkit-box-shadow: 1px 1px 0 #cccccc;
381
+ -moz-box-shadow: 1px 1px 0 #cccccc;
382
+ box-shadow: 1px 1px 0 #cccccc;
383
+ margin-bottom: -2px;
384
+ cursor: default;
385
+ }
386
+ #message > header .views .action {
387
+ display: -moz-inline-box;
388
+ -moz-box-orient: vertical;
389
+ display: inline-block;
390
+ vertical-align: middle;
391
+ *vertical-align: auto;
392
+ float: right;
393
+ margin: 0 0.25em;
394
+ }
395
+ #message > header .views .action {
396
+ *display: inline;
397
+ }
335
398
 
336
399
  .fractal-analysis {
337
- margin: 12px 0; }
338
- .fractal-analysis .report-intro {
339
- font-weight: bold; }
340
- .fractal-analysis .report-intro.valid {
341
- color: #009900; }
342
- .fractal-analysis .report-intro.invalid {
343
- color: #cc3333; }
344
- .fractal-analysis code {
345
- font-family: Monaco, "Courier New", Courier, monospace;
346
- background-color: #f8f8ff;
347
- color: #444444;
348
- padding: 0 0.2em;
349
- border: 1px solid #dedede; }
350
- .fractal-analysis ul {
351
- margin: 1em 0 1em 1em;
352
- list-style-type: square; }
353
- .fractal-analysis ol {
354
- margin: 1em 0 1em 2em;
355
- list-style-type: decimal; }
356
- .fractal-analysis ul li, .fractal-analysis ol li {
357
- display: list-item;
358
- margin: 0.5em 0 0.5em 1em; }
359
- .fractal-analysis .error-intro strong {
360
- font-weight: bold; }
361
- .fractal-analysis .unsupported-clients dt {
362
- padding-left: 1em; }
363
- .fractal-analysis .unsupported-clients dd {
364
- padding-left: 2em; }
365
- .fractal-analysis .unsupported-clients dd ul li {
366
- display: list-item; }
400
+ margin: 12px 0;
401
+ }
402
+ .fractal-analysis .report-intro {
403
+ font-weight: bold;
404
+ }
405
+ .fractal-analysis .report-intro.valid {
406
+ color: #009900;
407
+ }
408
+ .fractal-analysis .report-intro.invalid {
409
+ color: #cc3333;
410
+ }
411
+ .fractal-analysis code {
412
+ font-family: Monaco, "Courier New", Courier, monospace;
413
+ background-color: #f8f8ff;
414
+ color: #444444;
415
+ padding: 0 0.2em;
416
+ border: 1px solid #dedede;
417
+ }
418
+ .fractal-analysis ul {
419
+ margin: 1em 0 1em 1em;
420
+ list-style-type: square;
421
+ }
422
+ .fractal-analysis ol {
423
+ margin: 1em 0 1em 2em;
424
+ list-style-type: decimal;
425
+ }
426
+ .fractal-analysis ul li, .fractal-analysis ol li {
427
+ display: list-item;
428
+ margin: 0.5em 0 0.5em 1em;
429
+ }
430
+ .fractal-analysis .error-intro strong {
431
+ font-weight: bold;
432
+ }
433
+ .fractal-analysis .unsupported-clients dt {
434
+ padding-left: 1em;
435
+ }
436
+ .fractal-analysis .unsupported-clients dd {
437
+ padding-left: 2em;
438
+ }
439
+ .fractal-analysis .unsupported-clients dd ul li {
440
+ display: list-item;
441
+ }
367
442
 
368
443
  iframe {
369
- display: -moz-box;
370
444
  display: -webkit-box;
445
+ display: -moz-box;
371
446
  display: -ms-box;
372
447
  display: box;
373
- -moz-box-flex: 1;
374
448
  -webkit-box-flex: 1;
449
+ -moz-box-flex: 1;
375
450
  -ms-box-flex: 1;
376
451
  box-flex: 1;
377
- background: white; }
452
+ background: white;
453
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailcatcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.8
4
+ version: 0.5.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-17 00:00:00.000000000 Z
12
+ date: 2012-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: '0.12'
37
+ version: '1.0'
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: '0.12'
45
+ version: '1.0'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: haml
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -92,16 +92,13 @@ dependencies:
92
92
  - !ruby/object:Gem::Version
93
93
  version: '1.2'
94
94
  - !ruby/object:Gem::Dependency
95
- name: skinny
95
+ name: sqlite3
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
99
99
  - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: '0.2'
102
- - - ! '>='
103
- - !ruby/object:Gem::Version
104
- version: 0.2.1
101
+ version: '1.3'
105
102
  type: :runtime
106
103
  prerelease: false
107
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -109,74 +106,71 @@ dependencies:
109
106
  requirements:
110
107
  - - ~>
111
108
  - !ruby/object:Gem::Version
112
- version: '0.2'
113
- - - ! '>='
114
- - !ruby/object:Gem::Version
115
- version: 0.2.1
109
+ version: '1.3'
116
110
  - !ruby/object:Gem::Dependency
117
- name: sqlite3
111
+ name: thin
118
112
  requirement: !ruby/object:Gem::Requirement
119
113
  none: false
120
114
  requirements:
121
- - - ~>
115
+ - - ! '>='
122
116
  - !ruby/object:Gem::Version
123
- version: '1.3'
117
+ version: '0'
124
118
  type: :runtime
125
119
  prerelease: false
126
120
  version_requirements: !ruby/object:Gem::Requirement
127
121
  none: false
128
122
  requirements:
129
- - - ~>
123
+ - - ! '>='
130
124
  - !ruby/object:Gem::Version
131
- version: '1.3'
125
+ version: '0'
132
126
  - !ruby/object:Gem::Dependency
133
- name: thin
127
+ name: skinny
134
128
  requirement: !ruby/object:Gem::Requirement
135
129
  none: false
136
130
  requirements:
137
- - - ~>
131
+ - - ! '>='
138
132
  - !ruby/object:Gem::Version
139
- version: '1.2'
133
+ version: '0'
140
134
  type: :runtime
141
135
  prerelease: false
142
136
  version_requirements: !ruby/object:Gem::Requirement
143
137
  none: false
144
138
  requirements:
145
- - - ~>
139
+ - - ! '>='
146
140
  - !ruby/object:Gem::Version
147
- version: '1.2'
141
+ version: '0'
148
142
  - !ruby/object:Gem::Dependency
149
143
  name: coffee-script
150
144
  requirement: !ruby/object:Gem::Requirement
151
145
  none: false
152
146
  requirements:
153
- - - ~>
147
+ - - ! '>='
154
148
  - !ruby/object:Gem::Version
155
- version: '2.2'
149
+ version: '0'
156
150
  type: :development
157
151
  prerelease: false
158
152
  version_requirements: !ruby/object:Gem::Requirement
159
153
  none: false
160
154
  requirements:
161
- - - ~>
155
+ - - ! '>='
162
156
  - !ruby/object:Gem::Version
163
- version: '2.2'
157
+ version: '0'
164
158
  - !ruby/object:Gem::Dependency
165
159
  name: compass
166
160
  requirement: !ruby/object:Gem::Requirement
167
161
  none: false
168
162
  requirements:
169
- - - ~>
163
+ - - ! '>='
170
164
  - !ruby/object:Gem::Version
171
- version: 0.11.1
165
+ version: '0'
172
166
  type: :development
173
167
  prerelease: false
174
168
  version_requirements: !ruby/object:Gem::Requirement
175
169
  none: false
176
170
  requirements:
177
- - - ~>
171
+ - - ! '>='
178
172
  - !ruby/object:Gem::Version
179
- version: 0.11.1
173
+ version: '0'
180
174
  - !ruby/object:Gem::Dependency
181
175
  name: rake
182
176
  requirement: !ruby/object:Gem::Requirement
@@ -214,17 +208,17 @@ dependencies:
214
208
  requirement: !ruby/object:Gem::Requirement
215
209
  none: false
216
210
  requirements:
217
- - - ~>
211
+ - - ! '>='
218
212
  - !ruby/object:Gem::Version
219
- version: '3.1'
213
+ version: '0'
220
214
  type: :development
221
215
  prerelease: false
222
216
  version_requirements: !ruby/object:Gem::Requirement
223
217
  none: false
224
218
  requirements:
225
- - - ~>
219
+ - - ! '>='
226
220
  - !ruby/object:Gem::Version
227
- version: '3.1'
221
+ version: '0'
228
222
  description: ! " MailCatcher runs a super simple SMTP server which catches any\n
229
223
  \ message sent to it to display in a web interface. Run\n mailcatcher, set
230
224
  your favourite app to deliver to\n smtp://127.0.0.1:1025 instead of your default
@@ -240,15 +234,16 @@ extra_rdoc_files:
240
234
  files:
241
235
  - README.md
242
236
  - LICENSE
243
- - VERSION
244
237
  - bin/catchmail
245
238
  - bin/mailcatcher
246
239
  - lib/mail_catcher/events.rb
247
240
  - lib/mail_catcher/growl.rb
248
241
  - lib/mail_catcher/mail.rb
249
242
  - lib/mail_catcher/smtp.rb
243
+ - lib/mail_catcher/version.rb
250
244
  - lib/mail_catcher/web.rb
251
245
  - lib/mail_catcher.rb
246
+ - public/favicon.ico
252
247
  - public/images/logo.png
253
248
  - public/images/logo_large.png
254
249
  - public/javascripts/application.js
@@ -286,3 +281,4 @@ signing_key:
286
281
  specification_version: 3
287
282
  summary: Runs an SMTP server, catches and displays email in a web interface.
288
283
  test_files: []
284
+ has_rdoc:
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.5.8