mail 2.5.5 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +8 -9
  3. data/CONTRIBUTING.md +13 -0
  4. data/Dependencies.txt +0 -1
  5. data/Gemfile +7 -24
  6. data/README.md +36 -15
  7. data/Rakefile +10 -2
  8. data/VERSION +4 -0
  9. data/lib/mail.rb +1 -1
  10. data/lib/mail/body.rb +2 -2
  11. data/lib/mail/check_delivery_params.rb +10 -47
  12. data/lib/mail/core_extensions/string.rb +12 -2
  13. data/lib/mail/elements/address.rb +38 -82
  14. data/lib/mail/elements/address_list.rb +19 -42
  15. data/lib/mail/elements/content_disposition_element.rb +3 -7
  16. data/lib/mail/elements/content_location_element.rb +2 -6
  17. data/lib/mail/elements/content_transfer_encoding_element.rb +3 -10
  18. data/lib/mail/elements/content_type_element.rb +4 -8
  19. data/lib/mail/elements/date_time_element.rb +3 -7
  20. data/lib/mail/elements/envelope_from_element.rb +3 -11
  21. data/lib/mail/elements/message_ids_element.rb +1 -6
  22. data/lib/mail/elements/mime_version_element.rb +3 -7
  23. data/lib/mail/elements/phrase_list.rb +2 -7
  24. data/lib/mail/elements/received_element.rb +3 -7
  25. data/lib/mail/encodings.rb +0 -1
  26. data/lib/mail/envelope.rb +0 -5
  27. data/lib/mail/field.rb +53 -17
  28. data/lib/mail/field_list.rb +18 -18
  29. data/lib/mail/fields/common/common_address.rb +15 -20
  30. data/lib/mail/fields/common/common_date.rb +0 -7
  31. data/lib/mail/fields/common/common_field.rb +1 -1
  32. data/lib/mail/fields/content_transfer_encoding_field.rb +0 -6
  33. data/lib/mail/fields/resent_sender_field.rb +1 -1
  34. data/lib/mail/fields/sender_field.rb +1 -1
  35. data/lib/mail/fields/unstructured_field.rb +7 -1
  36. data/lib/mail/header.rb +8 -22
  37. data/lib/mail/mail.rb +12 -0
  38. data/lib/mail/matchers/has_sent_mail.rb +34 -1
  39. data/lib/mail/message.rb +18 -11
  40. data/lib/mail/multibyte/unicode.rb +1 -1
  41. data/lib/mail/network/delivery_methods/exim.rb +10 -6
  42. data/lib/mail/network/delivery_methods/file_delivery.rb +8 -4
  43. data/lib/mail/network/delivery_methods/sendmail.rb +7 -9
  44. data/lib/mail/network/delivery_methods/smtp.rb +5 -2
  45. data/lib/mail/network/delivery_methods/smtp_connection.rb +6 -2
  46. data/lib/mail/network/delivery_methods/test_mailer.rb +8 -5
  47. data/lib/mail/network/retriever_methods/imap.rb +18 -13
  48. data/lib/mail/parsers.rb +26 -0
  49. data/lib/mail/parsers/address_lists_parser.rb +132 -0
  50. data/lib/mail/parsers/content_disposition_parser.rb +67 -0
  51. data/lib/mail/parsers/content_location_parser.rb +35 -0
  52. data/lib/mail/parsers/content_transfer_encoding_parser.rb +33 -0
  53. data/lib/mail/parsers/content_type_parser.rb +64 -0
  54. data/lib/mail/parsers/date_time_parser.rb +36 -0
  55. data/lib/mail/parsers/envelope_from_parser.rb +45 -0
  56. data/lib/mail/parsers/message_ids_parser.rb +39 -0
  57. data/lib/mail/parsers/mime_version_parser.rb +41 -0
  58. data/lib/mail/parsers/phrase_lists_parser.rb +33 -0
  59. data/lib/mail/parsers/ragel.rb +17 -0
  60. data/lib/mail/parsers/ragel/common.rl +184 -0
  61. data/lib/mail/parsers/ragel/date_time.rl +30 -0
  62. data/lib/mail/parsers/ragel/parser_info.rb +61 -0
  63. data/lib/mail/parsers/ragel/ruby.rb +29 -0
  64. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +14864 -0
  65. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +37 -0
  66. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +751 -0
  67. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +37 -0
  68. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +614 -0
  69. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +37 -0
  70. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +447 -0
  71. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +37 -0
  72. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +825 -0
  73. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +37 -0
  74. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +817 -0
  75. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +37 -0
  76. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +2129 -0
  77. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +37 -0
  78. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +1570 -0
  79. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +37 -0
  80. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +440 -0
  81. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +37 -0
  82. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +564 -0
  83. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +37 -0
  84. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +51 -0
  85. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +5144 -0
  86. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +37 -0
  87. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +37 -0
  88. data/lib/mail/parsers/received_parser.rb +47 -0
  89. data/lib/mail/parts_list.rb +4 -2
  90. data/lib/mail/patterns.rb +3 -1
  91. data/lib/mail/utilities.rb +3 -1
  92. data/lib/mail/version.rb +1 -1
  93. data/lib/mail/version_specific/ruby_1_8.rb +1 -1
  94. data/lib/mail/version_specific/ruby_1_9.rb +13 -1
  95. metadata +55 -51
  96. data/lib/VERSION +0 -4
  97. data/lib/load_parsers.rb +0 -35
  98. data/lib/mail/parsers/address_lists.rb +0 -64
  99. data/lib/mail/parsers/address_lists.treetop +0 -19
  100. data/lib/mail/parsers/content_disposition.rb +0 -535
  101. data/lib/mail/parsers/content_disposition.treetop +0 -46
  102. data/lib/mail/parsers/content_location.rb +0 -139
  103. data/lib/mail/parsers/content_location.treetop +0 -20
  104. data/lib/mail/parsers/content_transfer_encoding.rb +0 -201
  105. data/lib/mail/parsers/content_transfer_encoding.treetop +0 -18
  106. data/lib/mail/parsers/content_type.rb +0 -971
  107. data/lib/mail/parsers/content_type.treetop +0 -68
  108. data/lib/mail/parsers/date_time.rb +0 -114
  109. data/lib/mail/parsers/date_time.treetop +0 -11
  110. data/lib/mail/parsers/envelope_from.rb +0 -194
  111. data/lib/mail/parsers/envelope_from.treetop +0 -32
  112. data/lib/mail/parsers/message_ids.rb +0 -45
  113. data/lib/mail/parsers/message_ids.treetop +0 -15
  114. data/lib/mail/parsers/mime_version.rb +0 -144
  115. data/lib/mail/parsers/mime_version.treetop +0 -19
  116. data/lib/mail/parsers/phrase_lists.rb +0 -45
  117. data/lib/mail/parsers/phrase_lists.treetop +0 -15
  118. data/lib/mail/parsers/received.rb +0 -71
  119. data/lib/mail/parsers/received.treetop +0 -11
  120. data/lib/mail/parsers/rfc2045.rb +0 -421
  121. data/lib/mail/parsers/rfc2045.treetop +0 -35
  122. data/lib/mail/parsers/rfc2822.rb +0 -5397
  123. data/lib/mail/parsers/rfc2822.treetop +0 -408
  124. data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
  125. data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
  126. data/lib/tasks/corpus.rake +0 -125
  127. data/lib/tasks/treetop.rake +0 -10
@@ -1,241 +0,0 @@
1
- module Mail
2
- grammar RFC2822Obsolete
3
-
4
- rule obs_qp
5
- "\\" [\x00-\x7F]
6
- end
7
-
8
- rule obs_text
9
- LF* CR* (obs_char LF* CR*)*
10
- end
11
-
12
- rule obs_char
13
- [\x00-\x09] / # %d0-127 except CR and
14
- [\x0B-\x0C] / # LF
15
- [\x0E-\x7F]
16
- end
17
-
18
- rule obs_utext
19
- obs_text
20
- end
21
-
22
- rule obs_phrase
23
- (word / "." / "@")+
24
- end
25
-
26
- rule obs_phrase_list
27
- phrase / (phrase? CFWS? "," CFWS?)+ phrase?
28
- end
29
-
30
- rule obs_FWS
31
- WSP+ (CRLF WSP+)*
32
- end
33
-
34
- rule obs_day_of_week
35
- CFWS? day_name CFWS?
36
- end
37
-
38
- rule obs_year
39
- CFWS? (DIGIT DIGIT) CFWS?
40
- end
41
-
42
- rule obs_month
43
- CFWS month_name CFWS
44
- end
45
-
46
- rule obs_day
47
- CFWS? (DIGIT / (DIGIT DIGIT)) CFWS?
48
- end
49
-
50
- rule obs_hour
51
- CFWS? (DIGIT DIGIT) CFWS?
52
- end
53
-
54
- rule obs_minute
55
- CFWS? (DIGIT DIGIT) CFWS?
56
- end
57
-
58
- rule obs_second
59
- CFWS? (DIGIT DIGIT) CFWS?
60
- end
61
-
62
- rule obs_zone
63
- "UT" / "GMT" / # Universal Time
64
- # North American UT
65
- # offsets
66
- "EST" / "EDT" / # Eastern: - 5/ - 4
67
- "CST" / "CDT" / # Central: - 6/ - 5
68
- "MST" / "MDT" / # Mountain: - 7/ - 6
69
- "PST" / "PDT" / # Pacific: - 8/ - 7
70
- #
71
- [\x41-\x49] / # Military zones - "A"
72
- [\x4B-\x5A] / # through "I" and "K"
73
- [\x61-\x69] / # through "Z", both
74
- [\x6B-\x7A] # upper and lower case
75
- end
76
-
77
- rule obs_angle_addr
78
- CFWS? "<" obs_route? addr_spec ">" CFWS?
79
- end
80
-
81
- rule obs_route
82
- CFWS? obs_domain_list ":" CFWS?
83
- end
84
-
85
- rule obs_domain_list
86
- "@" domain (("," )* CFWS? "@" domain)*
87
- end
88
-
89
- rule obs_local_part
90
- word ("." word)*
91
- end
92
-
93
- rule obs_domain
94
- atom ("." atom)*
95
- end
96
-
97
- rule obs_mbox_list
98
- (mailbox? CFWS? "," CFWS?)+ mailbox?
99
- end
100
-
101
- rule obs_addr_list
102
- (address? CFWS? "," CFWS?)+ address?
103
- end
104
-
105
- rule obs_fields
106
- (obs_return /
107
- obs_received /
108
- obs_orig_date /
109
- obs_from /
110
- obs_sender /
111
- obs_reply_to /
112
- obs_to /
113
- obs_cc /
114
- obs_bcc /
115
- obs_message_id /
116
- obs_in_reply_to /
117
- obs_references /
118
- obs_subject /
119
- obs_comments /
120
- obs_keywords /
121
- obs_resent_date /
122
- obs_resent_from /
123
- obs_resent_send /
124
- obs_resent_rply /
125
- obs_resent_to /
126
- obs_resent_cc /
127
- obs_resent_bcc /
128
- obs_resent_mid /
129
- obs_optional)*
130
- end
131
-
132
- rule obs_orig_date
133
- "Date" WSP* ":" date_time CRLF
134
- end
135
-
136
- rule obs_from
137
- "From" WSP* ":" mailbox_list CRLF
138
- end
139
-
140
- rule obs_sender
141
- "Sender" WSP* ":" mailbox CRLF
142
- end
143
-
144
- rule obs_reply_to
145
- "Reply-To" WSP* ":" mailbox_list CRLF
146
- end
147
-
148
-
149
- rule obs_to
150
- "To" WSP* ":" address_list CRLF
151
- end
152
-
153
- rule obs_cc
154
- "Cc" WSP* ":" address_list CRLF
155
- end
156
-
157
- rule obs_bcc
158
- "Bcc" WSP* ":" (address_list / CFWS?) CRLF
159
- end
160
-
161
- rule obs_message_id
162
- "Message-ID" WSP* ":" msg_id CRLF
163
- end
164
-
165
- rule obs_in_reply_to
166
- "In-Reply-To" WSP* ":" (phrase / msg_id)* CRLF
167
- end
168
-
169
- rule obs_references
170
- "References" WSP* ":" (phrase / msg_id)* CRLF
171
- end
172
-
173
- rule obs_id_left
174
- local_part
175
- end
176
-
177
- rule obs_id_right
178
- domain
179
- end
180
-
181
- rule obs_subject
182
- "Subject" WSP* ":" unstructured CRLF
183
- end
184
-
185
- rule obs_comments
186
- "Comments" WSP* ":" unstructured CRLF
187
- end
188
-
189
- rule obs_keywords
190
- "Keywords" WSP* ":" obs_phrase_list CRLF
191
- end
192
-
193
- rule obs_resent_from
194
- "Resent-From" WSP* ":" mailbox_list CRLF
195
- end
196
-
197
- rule obs_resent_send
198
- "Resent-Sender" WSP* ":" mailbox CRLF
199
- end
200
-
201
- rule obs_resent_date
202
- "Resent-Date" WSP* ":" date_time CRLF
203
- end
204
-
205
- rule obs_resent_to
206
- "Resent-To" WSP* ":" address_list CRLF
207
- end
208
-
209
- rule obs_resent_cc
210
- "Resent-Cc" WSP* ":" address_list CRLF
211
- end
212
-
213
- rule obs_resent_bcc
214
- "Resent-Bcc" WSP* ":" (address_list / CFWS?) CRLF
215
- end
216
-
217
- rule obs_resent_mid
218
- "Resent-Message-ID" WSP* ":" msg_id CRLF
219
- end
220
-
221
- rule obs_resent_rply
222
- "Resent-Reply-To" WSP* ":" address_list CRLF
223
- end
224
-
225
- rule obs_return
226
- "Return-Path" WSP* ":" path CRLF
227
- end
228
-
229
- rule obs_received
230
- "Received" WSP* ":" name_val_list CRLF
231
- end
232
-
233
- rule obs_path
234
- obs_angle_addr
235
- end
236
-
237
- rule obs_optional
238
- field_name WSP* ":" unstructured CRLF
239
- end
240
- end
241
- end
@@ -1,125 +0,0 @@
1
- namespace :corpus do
2
-
3
- task :load_mail do
4
- require File.expand_path('../../../spec/environment')
5
- require 'mail'
6
- end
7
-
8
- # Used to run parsing against an arbitrary corpus of email.
9
- # For example: http://plg.uwaterloo.ca/~gvcormac/treccorpus/
10
- desc "Provide a LOCATION=/some/dir to verify parsing in bulk, otherwise defaults"
11
- task :verify_all => :load_mail do
12
-
13
- root_of_corpus = ENV['LOCATION'] || 'corpus/spam'
14
- @save_failures_to = ENV['SAVE_TO'] || 'spec/fixtures/emails/failed_emails'
15
- @failed_emails = []
16
- @checked_count = 0
17
-
18
- if root_of_corpus
19
- root_of_corpus = File.expand_path(root_of_corpus)
20
- if not File.directory?(root_of_corpus)
21
- raise "\n\tPath '#{root_of_corpus}' is not a directory.\n\n"
22
- end
23
- else
24
- raise "\n\tSupply path to corpus: LOCATION=/path/to/corpus\n\n"
25
- end
26
-
27
- if @save_failures_to
28
- if not File.directory?(@save_failures_to)
29
- raise "\n\tPath '#{@save_failures_to}' is not a directory.\n\n"
30
- end
31
- @save_failures_to = File.expand_path(@save_failures_to)
32
- puts "Mail which fails to parse will be saved in '#{@save_failures_to}'"
33
- end
34
-
35
- puts "Checking '#{root_of_corpus}' directory (recursively)"
36
-
37
- # we're tracking all the errors separately, don't clutter terminal
38
- $stderr_backup = $stderr.dup
39
- $stderr.reopen("/dev/null", "w")
40
- STDERR = $stderr
41
-
42
- dir_node(root_of_corpus)
43
-
44
- # put our toys back now that we're done with them
45
- $stderr = $stderr_backup.dup
46
- STDERR = $stderr
47
-
48
- puts "\n\n"
49
-
50
- if @failed_emails.any?
51
- report_failures_to_stdout
52
- end
53
- puts "Out of Total: #{@checked_count}"
54
-
55
- if @save_failures_to
56
- puts "Add SAVE_TO=/some/dir to save failed emails to for review.,"
57
- puts "May result in a lot of saved files. Do a dry run first!\n\n"
58
- else
59
- puts "There are no errors"
60
- end
61
- end
62
-
63
- def dir_node(path)
64
- puts "\n\n"
65
- puts "Checking emails in '#{path}':"
66
-
67
- entries = Dir.entries(path)
68
-
69
- entries.each do |entry|
70
- next if ['.', '..'].include?(entry)
71
- full_path = File.join(path, entry)
72
-
73
- if File.file?(full_path)
74
- file_node(full_path)
75
- elsif File.directory?(full_path)
76
- dir_node(full_path)
77
- end
78
- end
79
- end
80
-
81
- def file_node(path)
82
- verify(path)
83
- end
84
-
85
- def verify(path)
86
- result, message = parse_as_mail(path)
87
- if result
88
- print '.'
89
- $stdout.flush
90
- else
91
- save_failure(path, message)
92
- print 'x'
93
- end
94
- end
95
-
96
- def save_failure(path, message)
97
- @failed_emails << [path, message]
98
- if @save_failures_to
99
- email_basename = File.basename(path)
100
- failure_as_filename = message.gsub(/\W/, '_')
101
- new_email_name = [failure_as_filename, email_basename].join("_")
102
- File.open(File.join(@save_failures_to, new_email_name), 'w+') do |fh|
103
- fh << File.read(path)
104
- end
105
- end
106
- end
107
-
108
- def parse_as_mail(path)
109
- @checked_count += 1
110
- begin
111
- parsed_mail = Mail.read(path)
112
- [true, nil]
113
- rescue => e
114
- [false, e.message]
115
- end
116
- end
117
-
118
- def report_failures_to_stdout
119
- @failed_emails.each do |failed|
120
- puts "#{failed[0]} : #{failed[1]}"
121
- end
122
- puts "Failed: #{@failed_emails.size}"
123
- end
124
-
125
- end
@@ -1,10 +0,0 @@
1
- namespace :treetop do
2
-
3
- desc "Pre-generate all the .treetop files into .rb files"
4
- task :generate do
5
- Dir.glob(File.expand_path('../../mail/parsers/*.treetop', __FILE__)).each do |filename|
6
- `bundle exec tt #{filename}`
7
- end
8
- end
9
-
10
- end