mail 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mail might be problematic. Click here for more details.
- data/Rakefile +1 -1
- data/lib/mail/message.rb +120 -13
- data/lib/mail/parsers/content_type.rb +12 -7
- data/lib/mail/parsers/content_type.treetop +1 -1
- data/lib/mail/vendor/treetop-1.4.3/examples/lambda_calculus/arithmetic.rb +1 -1
- data/lib/mail/vendor/treetop-1.4.3/examples/lambda_calculus/lambda_calculus.rb +1 -1
- data/lib/mail/vendor/treetop-1.4.3/lib/treetop/compiler/metagrammar.rb +1 -1
- data/lib/mail/version.rb +1 -1
- data/lib/tasks/corpus.rake +4 -3
- metadata +2 -2
data/Rakefile
CHANGED
data/lib/mail/message.rb
CHANGED
@@ -47,10 +47,59 @@ module Mail
|
|
47
47
|
include Patterns
|
48
48
|
include Utilities
|
49
49
|
|
50
|
-
#
|
50
|
+
# ==Making an email
|
51
|
+
#
|
52
|
+
# You can make an new mail object via a block, passing a string, file or direct assignment.
|
53
|
+
#
|
54
|
+
# ===Making an email via a block
|
55
|
+
#
|
56
|
+
# mail = Mail.new do
|
57
|
+
# from 'mikel@test.lindsaar.net'
|
58
|
+
# to 'you@test.lindsaar.net'
|
59
|
+
# subject 'This is a test email'
|
60
|
+
# body File.read('body.txt')
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
|
64
|
+
#
|
65
|
+
# ===Making an email via passing a string
|
66
|
+
#
|
67
|
+
# mail = Mail.new("To: mikel@test.lindsaar.net\r\nSubject: Hello\r\n\r\nHi there!")
|
68
|
+
# mail.body.to_s #=> 'Hi there!'
|
69
|
+
# mail.subject #=> 'Hello'
|
70
|
+
# mail.to #=> 'mikel@test.lindsaar.net'
|
71
|
+
#
|
72
|
+
# ===Making an email from a file
|
73
|
+
#
|
74
|
+
# mail = Mail.read('path/to/file.eml')
|
75
|
+
# mail.body.to_s #=> 'Hi there!'
|
76
|
+
# mail.subject #=> 'Hello'
|
77
|
+
# mail.to #=> 'mikel@test.lindsaar.net'
|
78
|
+
#
|
79
|
+
# ===Making an email via assignment
|
80
|
+
#
|
81
|
+
# You can assign values to a mail object via four approaches:
|
82
|
+
#
|
83
|
+
# * Message#field_name=(value)
|
84
|
+
# * Message#field_name(value)
|
85
|
+
# * Message#['field_name']=(value)
|
86
|
+
# * Message#[:field_name]=(value)
|
87
|
+
#
|
88
|
+
# Examples:
|
89
|
+
#
|
90
|
+
# mail = Mail.new
|
91
|
+
# mail['from'] = 'mikel@test.lindsaar.net'
|
92
|
+
# mail[:to] = 'you@test.lindsaar.net'
|
93
|
+
# mail.subject 'This is a test email'
|
94
|
+
# mail.body = 'This is a body'
|
95
|
+
#
|
96
|
+
# mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
|
97
|
+
#
|
51
98
|
def initialize(*args, &block)
|
52
99
|
@body = nil
|
53
|
-
|
100
|
+
@text_part = nil
|
101
|
+
@html_part = nil
|
102
|
+
|
54
103
|
if args.flatten.first.respond_to?(:each_pair)
|
55
104
|
init_with_hash(args.flatten.first)
|
56
105
|
else
|
@@ -64,10 +113,30 @@ module Mail
|
|
64
113
|
self
|
65
114
|
end
|
66
115
|
|
116
|
+
# Delivers an mail object.
|
117
|
+
#
|
118
|
+
# Examples:
|
119
|
+
#
|
120
|
+
# mail = Mail.read('file.eml')
|
121
|
+
# mail.deliver!
|
67
122
|
def deliver!
|
68
123
|
Deliverable.perform_delivery!(self)
|
69
124
|
end
|
70
125
|
|
126
|
+
# Provides the operator needed for sort et al.
|
127
|
+
#
|
128
|
+
# Compares this mail object with another mail object, this is done by date, so an
|
129
|
+
# email that is older than another will appear first.
|
130
|
+
#
|
131
|
+
# Example:
|
132
|
+
#
|
133
|
+
# mail1 = Mail.new do
|
134
|
+
# date(Time.now)
|
135
|
+
# end
|
136
|
+
# mail2 = Mail.new do
|
137
|
+
# date(Time.now - 86400) # 1 day older
|
138
|
+
# end
|
139
|
+
# [mail2, mail1].sort #=> [mail2, mail1]
|
71
140
|
def <=>(other)
|
72
141
|
if other.nil?
|
73
142
|
1
|
@@ -76,11 +145,48 @@ module Mail
|
|
76
145
|
end
|
77
146
|
end
|
78
147
|
|
148
|
+
# Two emails are the same if they have the same fields and body contents. One
|
149
|
+
# gotcha here is that Mail will insert Message-IDs when calling encoded, so doing
|
150
|
+
# mail1.encoded == mail2.encoded is most probably not going to return what you think
|
151
|
+
# as the assigned Message-IDs by Mail (if not already defined as the same) will ensure
|
152
|
+
# that the two objects are unique, and this comparison will ALWAYS return false.
|
153
|
+
#
|
154
|
+
# So the == operator has been defined like so: Two messages are the same if they have
|
155
|
+
# the same content, ignoring the Message-ID field, unless BOTH emails have a defined and
|
156
|
+
# different Message-ID value, then they are false.
|
157
|
+
#
|
158
|
+
# So, in practice the == operator works like this:
|
159
|
+
#
|
160
|
+
# m1 = Mail.new("Subject: Hello\r\n\r\nHello")
|
161
|
+
# m2 = Mail.new("Subject: Hello\r\n\r\nHello")
|
162
|
+
# m1 == m2 #=> true
|
163
|
+
#
|
164
|
+
# m1 = Mail.new("Subject: Hello\r\n\r\nHello")
|
165
|
+
# m2 = Mail.new("Message-ID: <1234@test>\r\nSubject: Hello\r\n\r\nHello")
|
166
|
+
# m1 == m2 #=> true
|
167
|
+
#
|
168
|
+
# m1 = Mail.new("Message-ID: <1234@test>\r\nSubject: Hello\r\n\r\nHello")
|
169
|
+
# m2 = Mail.new("Subject: Hello\r\n\r\nHello")
|
170
|
+
# m1 == m2 #=> true
|
171
|
+
#
|
172
|
+
# m1 = Mail.new("Message-ID: <1234@test>\r\nSubject: Hello\r\n\r\nHello")
|
173
|
+
# m2 = Mail.new("Message-ID: <1234@test>\r\nSubject: Hello\r\n\r\nHello")
|
174
|
+
# m1 == m2 #=> true
|
175
|
+
#
|
176
|
+
# m1 = Mail.new("Message-ID: <1234@test>\r\nSubject: Hello\r\n\r\nHello")
|
177
|
+
# m2 = Mail.new("Message-ID: <DIFFERENT@test>\r\nSubject: Hello\r\n\r\nHello")
|
178
|
+
# m1 == m2 #=> false
|
79
179
|
def ==(other)
|
80
|
-
unless other.respond_to?(:encoded)
|
81
|
-
|
180
|
+
return false unless other.respond_to?(:encoded)
|
181
|
+
|
182
|
+
if self.message_id && other.message_id
|
183
|
+
result = (self.encoded == other.encoded)
|
82
184
|
else
|
83
|
-
self.
|
185
|
+
self_message_id, other_message_id = self.message_id, other.message_id
|
186
|
+
self.message_id, other.message_id = '<temp@test>', '<temp@test>'
|
187
|
+
result = self.encoded == other.encoded
|
188
|
+
self.message_id, other.message_id = "<#{self_message_id}>", "<#{other_message_id}>"
|
189
|
+
result
|
84
190
|
end
|
85
191
|
end
|
86
192
|
|
@@ -96,10 +202,7 @@ module Mail
|
|
96
202
|
@raw_source
|
97
203
|
end
|
98
204
|
|
99
|
-
|
100
|
-
@raw_source = value.to_crlf
|
101
|
-
end
|
102
|
-
|
205
|
+
# Sets the envelope from for the email
|
103
206
|
def set_envelope( val )
|
104
207
|
@raw_envelope = val
|
105
208
|
@envelope = Mail::Envelope.new( val )
|
@@ -1141,7 +1244,7 @@ module Mail
|
|
1141
1244
|
def html_part(&block)
|
1142
1245
|
if block_given?
|
1143
1246
|
@html_part = Mail::Part.new(&block)
|
1144
|
-
add_multipart_alternate_header
|
1247
|
+
add_multipart_alternate_header unless html_part.blank?
|
1145
1248
|
add_part(@html_part)
|
1146
1249
|
else
|
1147
1250
|
@html_part
|
@@ -1152,7 +1255,7 @@ module Mail
|
|
1152
1255
|
def text_part(&block)
|
1153
1256
|
if block_given?
|
1154
1257
|
@text_part = Mail::Part.new(&block)
|
1155
|
-
add_multipart_alternate_header
|
1258
|
+
add_multipart_alternate_header unless html_part.blank?
|
1156
1259
|
add_part(@text_part)
|
1157
1260
|
else
|
1158
1261
|
@text_part
|
@@ -1168,7 +1271,7 @@ module Mail
|
|
1168
1271
|
else
|
1169
1272
|
@html_part = Mail::Part.new('Content-Type: text/html;')
|
1170
1273
|
end
|
1171
|
-
add_multipart_alternate_header
|
1274
|
+
add_multipart_alternate_header unless text_part.blank?
|
1172
1275
|
add_part(@html_part)
|
1173
1276
|
end
|
1174
1277
|
|
@@ -1181,7 +1284,7 @@ module Mail
|
|
1181
1284
|
else
|
1182
1285
|
@text_part = Mail::Part.new('Content-Type: text/plain;')
|
1183
1286
|
end
|
1184
|
-
add_multipart_alternate_header
|
1287
|
+
add_multipart_alternate_header unless html_part.blank?
|
1185
1288
|
add_part(@text_part)
|
1186
1289
|
end
|
1187
1290
|
|
@@ -1330,6 +1433,10 @@ module Mail
|
|
1330
1433
|
self.body = body_part
|
1331
1434
|
end
|
1332
1435
|
|
1436
|
+
def raw_source=(value)
|
1437
|
+
@raw_source = value.to_crlf
|
1438
|
+
end
|
1439
|
+
|
1333
1440
|
def set_envelope_header
|
1334
1441
|
if match_data = raw_source.to_s.match(/^From\s(#{TEXT}+)#{CRLF}(.*)/m)
|
1335
1442
|
set_envelope(match_data[1])
|
@@ -80,19 +80,24 @@ module Mail
|
|
80
80
|
s5 << r6
|
81
81
|
if r6
|
82
82
|
if has_terminal?(";", false, index)
|
83
|
-
|
83
|
+
r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
84
84
|
@index += 1
|
85
85
|
else
|
86
86
|
terminal_parse_failure(";")
|
87
|
-
|
87
|
+
r8 = nil
|
88
|
+
end
|
89
|
+
if r8
|
90
|
+
r7 = r8
|
91
|
+
else
|
92
|
+
r7 = instantiate_node(SyntaxNode,input, index...index)
|
88
93
|
end
|
89
94
|
s5 << r7
|
90
95
|
if r7
|
91
|
-
|
92
|
-
s5 <<
|
93
|
-
if
|
94
|
-
|
95
|
-
s5 <<
|
96
|
+
r9 = _nt_parameter
|
97
|
+
s5 << r9
|
98
|
+
if r9
|
99
|
+
r10 = _nt_CFWS
|
100
|
+
s5 << r10
|
96
101
|
end
|
97
102
|
end
|
98
103
|
end
|
@@ -5,7 +5,7 @@ module Mail
|
|
5
5
|
include RFC2045
|
6
6
|
|
7
7
|
rule content_type
|
8
|
-
main_type "/" sub_type param_hashes:(CFWS ";" parameter CFWS)* {
|
8
|
+
main_type "/" sub_type param_hashes:(CFWS ";"? parameter CFWS)* {
|
9
9
|
def parameters
|
10
10
|
param_hashes.elements.map do |param|
|
11
11
|
param.parameter.param_hash
|
data/lib/mail/version.rb
CHANGED
data/lib/tasks/corpus.rake
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
namespace :corpus do
|
2
2
|
|
3
3
|
task :load_mail do
|
4
|
+
$:.unshift File.expand_path('../', File.dirname(__FILE__))
|
4
5
|
require 'lib/mail'
|
5
6
|
end
|
6
7
|
|
7
8
|
# Used to run parsing against an arbitrary corpus of email.
|
8
9
|
# For example: http://plg.uwaterloo.ca/~gvcormac/treccorpus/
|
9
|
-
desc "Provide a LOCATION=/some/dir to verify parsing in bulk"
|
10
|
+
desc "Provide a LOCATION=/some/dir to verify parsing in bulk, otherwise defaults"
|
10
11
|
task :verify_all => :load_mail do
|
11
12
|
|
12
|
-
root_of_corpus = ENV['LOCATION']
|
13
|
-
@save_failures_to = ENV['SAVE_TO']
|
13
|
+
root_of_corpus = ENV['LOCATION'] || 'spec/fixtures/corpus/spam'
|
14
|
+
@save_failures_to = ENV['SAVE_TO'] || 'spec/fixtures/emails/failed_emails'
|
14
15
|
@failed_emails = []
|
15
16
|
@checked_count = 0
|
16
17
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Lindsaar
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-04 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|