mail 2.6.6 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +74 -90
  4. data/lib/mail/attachments_list.rb +8 -4
  5. data/lib/mail/body.rb +50 -38
  6. data/lib/mail/check_delivery_params.rb +8 -6
  7. data/lib/mail/configuration.rb +2 -0
  8. data/lib/mail/constants.rb +1 -1
  9. data/lib/mail/core_extensions/smtp.rb +19 -16
  10. data/lib/mail/core_extensions/string.rb +0 -4
  11. data/lib/mail/elements/address.rb +28 -22
  12. data/lib/mail/elements/address_list.rb +10 -18
  13. data/lib/mail/elements/content_disposition_element.rb +8 -15
  14. data/lib/mail/elements/content_location_element.rb +5 -10
  15. data/lib/mail/elements/content_transfer_encoding_element.rb +5 -10
  16. data/lib/mail/elements/content_type_element.rb +8 -19
  17. data/lib/mail/elements/date_time_element.rb +6 -14
  18. data/lib/mail/elements/envelope_from_element.rb +14 -21
  19. data/lib/mail/elements/message_ids_element.rb +8 -12
  20. data/lib/mail/elements/mime_version_element.rb +6 -14
  21. data/lib/mail/elements/phrase_list.rb +6 -9
  22. data/lib/mail/elements/received_element.rb +9 -15
  23. data/lib/mail/encodings/7bit.rb +5 -15
  24. data/lib/mail/encodings/8bit.rb +2 -21
  25. data/lib/mail/encodings/base64.rb +11 -12
  26. data/lib/mail/encodings/binary.rb +3 -22
  27. data/lib/mail/encodings/identity.rb +24 -0
  28. data/lib/mail/encodings/quoted_printable.rb +6 -6
  29. data/lib/mail/encodings/transfer_encoding.rb +38 -29
  30. data/lib/mail/encodings/unix_to_unix.rb +3 -1
  31. data/lib/mail/encodings.rb +99 -43
  32. data/lib/mail/envelope.rb +1 -1
  33. data/lib/mail/field.rb +96 -59
  34. data/lib/mail/fields/bcc_field.rb +2 -2
  35. data/lib/mail/fields/cc_field.rb +1 -1
  36. data/lib/mail/fields/comments_field.rb +1 -1
  37. data/lib/mail/fields/common/common_address.rb +32 -7
  38. data/lib/mail/fields/common/common_field.rb +1 -10
  39. data/lib/mail/fields/common/parameter_hash.rb +1 -1
  40. data/lib/mail/fields/content_description_field.rb +1 -1
  41. data/lib/mail/fields/content_disposition_field.rb +3 -3
  42. data/lib/mail/fields/content_id_field.rb +2 -2
  43. data/lib/mail/fields/content_location_field.rb +1 -1
  44. data/lib/mail/fields/content_transfer_encoding_field.rb +1 -1
  45. data/lib/mail/fields/content_type_field.rb +4 -9
  46. data/lib/mail/fields/date_field.rb +2 -3
  47. data/lib/mail/fields/from_field.rb +1 -1
  48. data/lib/mail/fields/in_reply_to_field.rb +1 -1
  49. data/lib/mail/fields/keywords_field.rb +1 -1
  50. data/lib/mail/fields/message_id_field.rb +1 -1
  51. data/lib/mail/fields/mime_version_field.rb +1 -1
  52. data/lib/mail/fields/optional_field.rb +4 -1
  53. data/lib/mail/fields/received_field.rb +1 -1
  54. data/lib/mail/fields/references_field.rb +1 -1
  55. data/lib/mail/fields/reply_to_field.rb +1 -1
  56. data/lib/mail/fields/resent_bcc_field.rb +1 -1
  57. data/lib/mail/fields/resent_cc_field.rb +1 -1
  58. data/lib/mail/fields/resent_date_field.rb +0 -1
  59. data/lib/mail/fields/resent_from_field.rb +1 -1
  60. data/lib/mail/fields/resent_message_id_field.rb +1 -1
  61. data/lib/mail/fields/resent_sender_field.rb +1 -1
  62. data/lib/mail/fields/resent_to_field.rb +1 -1
  63. data/lib/mail/fields/return_path_field.rb +1 -1
  64. data/lib/mail/fields/sender_field.rb +1 -1
  65. data/lib/mail/fields/subject_field.rb +1 -1
  66. data/lib/mail/fields/to_field.rb +1 -1
  67. data/lib/mail/fields/unstructured_field.rb +21 -4
  68. data/lib/mail/header.rb +10 -8
  69. data/lib/mail/mail.rb +2 -10
  70. data/lib/mail/matchers/has_sent_mail.rb +21 -1
  71. data/lib/mail/message.rb +78 -68
  72. data/lib/mail/multibyte/chars.rb +29 -28
  73. data/lib/mail/multibyte/unicode.rb +10 -10
  74. data/lib/mail/multibyte.rb +64 -15
  75. data/lib/mail/network/delivery_methods/logger_delivery.rb +37 -0
  76. data/lib/mail/network/delivery_methods/sendmail.rb +8 -5
  77. data/lib/mail/network/delivery_methods/smtp.rb +58 -49
  78. data/lib/mail/network/delivery_methods/smtp_connection.rb +9 -1
  79. data/lib/mail/network/retriever_methods/imap.rb +18 -5
  80. data/lib/mail/network/retriever_methods/pop3.rb +3 -1
  81. data/lib/mail/network.rb +1 -0
  82. data/lib/mail/parser_tools.rb +15 -0
  83. data/lib/mail/parsers/address_lists_parser.rb +33207 -104
  84. data/lib/mail/parsers/address_lists_parser.rl +172 -0
  85. data/lib/mail/parsers/content_disposition_parser.rb +876 -49
  86. data/lib/mail/parsers/content_disposition_parser.rl +82 -0
  87. data/lib/mail/parsers/content_location_parser.rb +803 -23
  88. data/lib/mail/parsers/content_location_parser.rl +71 -0
  89. data/lib/mail/parsers/content_transfer_encoding_parser.rb +501 -19
  90. data/lib/mail/parsers/content_transfer_encoding_parser.rl +64 -0
  91. data/lib/mail/parsers/content_type_parser.rb +1023 -48
  92. data/lib/mail/parsers/content_type_parser.rl +83 -0
  93. data/lib/mail/parsers/date_time_parser.rb +870 -24
  94. data/lib/mail/parsers/date_time_parser.rl +62 -0
  95. data/lib/mail/parsers/envelope_from_parser.rb +3569 -34
  96. data/lib/mail/parsers/envelope_from_parser.rl +82 -0
  97. data/lib/mail/parsers/message_ids_parser.rb +2839 -25
  98. data/lib/mail/parsers/message_ids_parser.rl +82 -0
  99. data/lib/mail/parsers/mime_version_parser.rb +491 -26
  100. data/lib/mail/parsers/mime_version_parser.rl +61 -0
  101. data/lib/mail/parsers/phrase_lists_parser.rb +860 -18
  102. data/lib/mail/parsers/phrase_lists_parser.rl +83 -0
  103. data/lib/mail/parsers/received_parser.rb +8764 -37
  104. data/lib/mail/parsers/received_parser.rl +84 -0
  105. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  106. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  107. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  108. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  109. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  110. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  111. data/lib/mail/parsers/rfc5322.rl +59 -0
  112. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  113. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
  114. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  115. data/lib/mail/parsers.rb +16 -24
  116. data/lib/mail/part.rb +3 -3
  117. data/lib/mail/parts_list.rb +5 -6
  118. data/lib/mail/utilities.rb +59 -28
  119. data/lib/mail/version.rb +2 -2
  120. data/lib/mail/version_specific/ruby_1_8.rb +40 -3
  121. data/lib/mail/version_specific/ruby_1_9.rb +61 -9
  122. data/lib/mail.rb +3 -16
  123. metadata +44 -53
  124. data/CHANGELOG.rdoc +0 -803
  125. data/CONTRIBUTING.md +0 -60
  126. data/Dependencies.txt +0 -2
  127. data/Gemfile +0 -14
  128. data/Rakefile +0 -29
  129. data/TODO.rdoc +0 -9
  130. data/lib/mail/core_extensions/string/access.rb +0 -146
  131. data/lib/mail/core_extensions/string/multibyte.rb +0 -79
  132. data/lib/mail/multibyte/exceptions.rb +0 -9
  133. data/lib/mail/parsers/ragel/common.rl +0 -185
  134. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  135. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  136. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  137. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  138. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  139. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  140. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  141. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  142. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  143. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  144. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  145. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  146. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  147. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  148. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  149. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  150. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  151. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  152. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  153. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  154. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  155. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  156. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  157. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  158. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  159. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  160. data/lib/mail/parsers/ragel.rb +0 -18
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/address_lists_parser'
4
+
3
5
  module Mail
4
6
  class Address
5
-
6
7
  include Mail::Utilities
7
8
 
8
9
  # Mail::Address handles all email addresses in Mail. It takes an email address string
@@ -22,7 +23,6 @@ module Mail
22
23
  # a.comments #=> ['My email address']
23
24
  # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
24
25
  def initialize(value = nil)
25
- @output_type = :decode
26
26
  if value.nil?
27
27
  @parsed = false
28
28
  @data = nil
@@ -44,14 +44,14 @@ module Mail
44
44
  #
45
45
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
46
46
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
47
- def format
47
+ def format(output_type = :decode)
48
48
  parse unless @parsed
49
49
  if @data.nil?
50
50
  EMPTY
51
- elsif display_name
52
- [quote_phrase(display_name), "<#{address}>", format_comments].compact.join(SPACE)
53
- elsif address
54
- [address, format_comments].compact.join(SPACE)
51
+ elsif name = display_name(output_type)
52
+ [quote_phrase(name), "<#{address(output_type)}>", format_comments].compact.join(SPACE)
53
+ elsif a = address(output_type)
54
+ [a, format_comments].compact.join(SPACE)
55
55
  else
56
56
  raw
57
57
  end
@@ -62,9 +62,13 @@ module Mail
62
62
  #
63
63
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
64
64
  # a.address #=> 'mikel@test.lindsaar.net'
65
- def address
65
+ def address(output_type = :decode)
66
66
  parse unless @parsed
67
- domain ? "#{local}@#{domain}" : local
67
+ if d = domain(output_type)
68
+ "#{local(output_type)}@#{d}"
69
+ else
70
+ local(output_type)
71
+ end
68
72
  end
69
73
 
70
74
  # Provides a way to assign an address to an already made Mail::Address object.
@@ -80,10 +84,10 @@ module Mail
80
84
  #
81
85
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
82
86
  # a.display_name #=> 'Mikel Lindsaar'
83
- def display_name
87
+ def display_name(output_type = :decode)
84
88
  parse unless @parsed
85
89
  @display_name ||= get_display_name
86
- Encodings.decode_encode(@display_name.to_s, @output_type) if @display_name
90
+ Encodings.decode_encode(@display_name.to_s, output_type) if @display_name
87
91
  end
88
92
 
89
93
  # Provides a way to assign a display name to an already made Mail::Address object.
@@ -101,9 +105,9 @@ module Mail
101
105
  #
102
106
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
103
107
  # a.local #=> 'mikel'
104
- def local
108
+ def local(output_type = :decode)
105
109
  parse unless @parsed
106
- Encodings.decode_encode("#{@data.obs_domain_list}#{get_local.strip}", @output_type) if get_local
110
+ Encodings.decode_encode("#{@data.obs_domain_list}#{get_local.strip}", output_type) if get_local
107
111
  end
108
112
 
109
113
  # Returns the domain part (the right hand side of the @ sign in the email address) of
@@ -111,16 +115,20 @@ module Mail
111
115
  #
112
116
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
113
117
  # a.domain #=> 'test.lindsaar.net'
114
- def domain
118
+ def domain(output_type = :decode)
115
119
  parse unless @parsed
116
- Encodings.decode_encode(strip_all_comments(get_domain), @output_type) if get_domain
120
+ Encodings.decode_encode(strip_all_comments(get_domain), output_type) if get_domain
117
121
  end
118
122
 
119
- # Returns an array of comments that are in the email, or an empty array if there
123
+ # Returns an array of comments that are in the email, or nil if there
120
124
  # are no comments
121
125
  #
122
126
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
123
127
  # a.comments #=> ['My email address']
128
+ #
129
+ # b = Address.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
130
+ # b.comments #=> nil
131
+
124
132
  def comments
125
133
  parse unless @parsed
126
134
  comments = get_comments
@@ -159,13 +167,11 @@ module Mail
159
167
  end
160
168
 
161
169
  def encoded
162
- @output_type = :encode
163
- format
170
+ format :encode
164
171
  end
165
172
 
166
173
  def decoded
167
- @output_type = :decode
168
- format
174
+ format :decode
169
175
  end
170
176
 
171
177
  def group
@@ -179,11 +185,11 @@ module Mail
179
185
  @data = nil
180
186
 
181
187
  case value
182
- when Mail::Parsers::AddressStruct
188
+ when Mail::Parsers::AddressListsParser::AddressStruct
183
189
  @data = value
184
190
  when String
185
191
  unless Utilities.blank?(value)
186
- address_list = Mail::Parsers::AddressListsParser.new.parse(value)
192
+ address_list = Mail::Parsers::AddressListsParser.parse(value)
187
193
  @data = address_list.addresses.first
188
194
  end
189
195
  end
@@ -1,42 +1,34 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/address_lists_parser'
4
+
3
5
  module Mail
4
6
  class AddressList # :nodoc:
7
+ attr_reader :addresses, :group_names
5
8
 
6
9
  # Mail::AddressList is the class that parses To, From and other address fields from
7
10
  # emails passed into Mail.
8
- #
11
+ #
9
12
  # AddressList provides a way to query the groups and mailbox lists of the passed in
10
13
  # string.
11
- #
14
+ #
12
15
  # It can supply all addresses in an array, or return each address as an address object.
13
- #
16
+ #
14
17
  # Mail::AddressList requires a correctly formatted group or mailbox list per RFC2822 or
15
18
  # RFC822. It also handles all obsolete versions in those RFCs.
16
- #
19
+ #
17
20
  # list = 'ada@test.lindsaar.net, My Group: mikel@test.lindsaar.net, Bob <bob@test.lindsaar.net>;'
18
21
  # a = AddressList.new(list)
19
22
  # a.addresses #=> [#<Mail::Address:14943130 Address: |ada@test.lindsaar.net...
20
23
  # a.group_names #=> ["My Group"]
21
24
  def initialize(string)
22
- @addresses_grouped_by_group = nil
23
- @address_list = Mail::Parsers::AddressListsParser.new.parse(string)
24
- end
25
-
26
- # Returns a list of address objects from the parsed line
27
- def addresses
28
- @addresses ||= @address_list.addresses.map do |address_data|
29
- Mail::Address.new(address_data)
30
- end
25
+ address_list = Parsers::AddressListsParser.parse(string)
26
+ @addresses = address_list.addresses.map { |a| Address.new(a) }
27
+ @group_names = address_list.group_names
31
28
  end
32
29
 
33
30
  def addresses_grouped_by_group
34
31
  addresses.select(&:group).group_by(&:group)
35
32
  end
36
-
37
- # Returns the names as an array of strings of all groups
38
- def group_names # :nodoc:
39
- @address_list.group_names
40
- end
41
33
  end
42
34
  end
@@ -1,27 +1,20 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/content_disposition_parser'
4
+
3
5
  module Mail
4
6
  class ContentDispositionElement # :nodoc:
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- content_disposition = Mail::Parsers::ContentDispositionParser.new.parse(cleaned(string))
7
+ attr_reader :disposition_type, :parameters
8
+
9
+ def initialize(string)
10
+ content_disposition = Mail::Parsers::ContentDispositionParser.parse(cleaned(string))
10
11
  @disposition_type = content_disposition.disposition_type
11
12
  @parameters = content_disposition.parameters
12
13
  end
13
-
14
- def disposition_type
15
- @disposition_type
16
- end
17
-
18
- def parameters
19
- @parameters
20
- end
21
-
14
+
15
+ private
22
16
  def cleaned(string)
23
17
  string =~ /(.+);\s*$/ ? $1 : string
24
18
  end
25
-
26
19
  end
27
20
  end
@@ -1,22 +1,17 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/content_location_parser'
4
+
3
5
  module Mail
4
6
  class ContentLocationElement # :nodoc:
7
+ attr_reader :location
5
8
 
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- content_location = Mail::Parsers::ContentLocationParser.new.parse(string)
10
- @location = content_location.location
11
- end
12
-
13
- def location
14
- @location
9
+ def initialize(string)
10
+ @location = Mail::Parsers::ContentLocationParser.parse(string).location
15
11
  end
16
12
 
17
13
  def to_s(*args)
18
14
  location.to_s
19
15
  end
20
-
21
16
  end
22
17
  end
@@ -1,18 +1,13 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/content_transfer_encoding_parser'
4
+
3
5
  module Mail
4
6
  class ContentTransferEncodingElement
5
-
6
- include Mail::Utilities
7
-
7
+ attr_reader :encoding
8
+
8
9
  def initialize(string)
9
- content_transfer_encoding = Mail::Parsers::ContentTransferEncodingParser.new.parse(string)
10
- @encoding = content_transfer_encoding.encoding
10
+ @encoding = Mail::Parsers::ContentTransferEncodingParser.parse(string).encoding
11
11
  end
12
-
13
- def encoding
14
- @encoding
15
- end
16
-
17
12
  end
18
13
  end
@@ -1,32 +1,21 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/content_type_parser'
4
+
3
5
  module Mail
4
6
  class ContentTypeElement # :nodoc:
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- content_type = Mail::Parsers::ContentTypeParser.new.parse(cleaned(string))
7
+ attr_reader :main_type, :sub_type, :parameters
8
+
9
+ def initialize(string)
10
+ content_type = Mail::Parsers::ContentTypeParser.parse(cleaned(string))
10
11
  @main_type = content_type.main_type
11
12
  @sub_type = content_type.sub_type
12
13
  @parameters = content_type.parameters
13
14
  end
14
-
15
- def main_type
16
- @main_type
17
- end
18
-
19
- def sub_type
20
- @sub_type
21
- end
22
-
23
- def parameters
24
- @parameters
25
- end
26
-
15
+
16
+ private
27
17
  def cleaned(string)
28
18
  string =~ /(.+);\s*$/ ? $1 : string
29
19
  end
30
-
31
20
  end
32
21
  end
@@ -1,23 +1,15 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/date_time_parser'
4
+
3
5
  module Mail
4
6
  class DateTimeElement # :nodoc:
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- date_time = Mail::Parsers::DateTimeParser.new.parse(string)
7
+ attr_reader :date_string, :time_string
8
+
9
+ def initialize(string)
10
+ date_time = Mail::Parsers::DateTimeParser.parse(string)
10
11
  @date_string = date_time.date_string
11
12
  @time_string = date_time.time_string
12
13
  end
13
-
14
- def date_string
15
- @date_string
16
- end
17
-
18
- def time_string
19
- @time_string
20
- end
21
-
22
14
  end
23
15
  end
@@ -1,40 +1,33 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/envelope_from_parser'
4
+ require 'date'
5
+
3
6
  module Mail
4
7
  class EnvelopeFromElement
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- @envelope_from = Mail::Parsers::EnvelopeFromParser.new.parse(string)
10
- @address = @envelope_from.address
11
- @date_time = ::DateTime.parse(@envelope_from.ctime_date)
12
- end
13
-
14
- def date_time
15
- @date_time
16
- end
17
-
18
- def address
19
- @address
8
+ attr_reader :date_time, :address
9
+
10
+ def initialize(string)
11
+ envelope_from = Mail::Parsers::EnvelopeFromParser.parse(string)
12
+ @address = envelope_from.address
13
+ @date_time = ::DateTime.parse(envelope_from.ctime_date)
20
14
  end
21
-
15
+
22
16
  # RFC 4155:
23
17
  # a timestamp indicating the UTC date and time when the message
24
18
  # was originally received, conformant with the syntax of the
25
19
  # traditional UNIX 'ctime' output sans timezone (note that the
26
20
  # use of UTC precludes the need for a timezone indicator);
27
21
  def formatted_date_time
28
- if @date_time.respond_to?(:ctime)
29
- @date_time.ctime
22
+ if date_time.respond_to?(:ctime)
23
+ date_time.ctime
30
24
  else
31
- @date_time.strftime '%a %b %e %T %Y'
25
+ date_time.strftime '%a %b %e %T %Y'
32
26
  end
33
27
  end
34
28
 
35
29
  def to_s
36
- "#{@address} #{formatted_date_time}"
30
+ "#{address} #{formatted_date_time}"
37
31
  end
38
-
39
32
  end
40
33
  end
@@ -1,26 +1,22 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/message_ids_parser'
4
+
3
5
  module Mail
4
6
  class MessageIdsElement
5
-
6
- include Mail::Utilities
7
+ attr_reader :message_ids
7
8
 
8
9
  def initialize(string)
9
- raise Mail::Field::ParseError.new(Mail::MessageIdsElement, string, 'nil is invalid') if string.nil?
10
- @message_ids = Mail::Parsers::MessageIdsParser.new.parse(string).message_ids.map { |msg_id| clean_msg_id(msg_id) }
11
- end
12
-
13
- def message_ids
14
- @message_ids
10
+ @message_ids = Mail::Parsers::MessageIdsParser.parse(string).message_ids.map { |msg_id| clean_msg_id(msg_id) }
15
11
  end
16
12
 
17
13
  def message_id
18
- @message_ids.first
14
+ message_ids.first
19
15
  end
20
16
 
21
- def clean_msg_id( val )
22
- val =~ /.*<(.*)>.*/ ; $1
17
+ private
18
+ def clean_msg_id(val)
19
+ val =~ /.*<(.*)>.*/ ? $1 : val
23
20
  end
24
-
25
21
  end
26
22
  end
@@ -1,23 +1,15 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/mime_version_parser'
4
+
3
5
  module Mail
4
6
  class MimeVersionElement
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- mime_version = Mail::Parsers::MimeVersionParser.new.parse(string)
7
+ attr_reader :major, :minor
8
+
9
+ def initialize(string)
10
+ mime_version = Mail::Parsers::MimeVersionParser.parse(string)
10
11
  @major = mime_version.major
11
12
  @minor = mime_version.minor
12
13
  end
13
-
14
- def major
15
- @major
16
- end
17
-
18
- def minor
19
- @minor
20
- end
21
-
22
14
  end
23
15
  end
@@ -1,17 +1,14 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/phrase_lists_parser'
4
+ require 'mail/utilities'
5
+
3
6
  module Mail
4
7
  class PhraseList
5
-
6
- include Mail::Utilities
7
-
8
+ attr_reader :phrases
9
+
8
10
  def initialize(string)
9
- @phrase_lists = Mail::Parsers::PhraseListsParser.new.parse(string)
11
+ @phrases = Mail::Parsers::PhraseListsParser.parse(string).phrases.map { |p| Mail::Utilities.unquote(p) }
10
12
  end
11
-
12
- def phrases
13
- @phrase_lists.phrases.map { |p| unquote(p) }
14
- end
15
-
16
13
  end
17
14
  end
@@ -1,27 +1,21 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/received_parser'
4
+ require 'date'
5
+
3
6
  module Mail
4
7
  class ReceivedElement
5
-
6
8
  include Mail::Utilities
7
-
8
- def initialize( string )
9
- received = Mail::Parsers::ReceivedParser.new.parse(string)
9
+ attr_reader :date_time, :info
10
+
11
+ def initialize(string)
12
+ received = Mail::Parsers::ReceivedParser.parse(string)
10
13
  @date_time = ::DateTime.parse("#{received.date} #{received.time}")
11
14
  @info = received.info
12
15
  end
13
-
14
- def date_time
15
- @date_time
16
- end
17
-
18
- def info
19
- @info
20
- end
21
-
16
+
22
17
  def to_s(*args)
23
- "#{@info}; #{@date_time.to_s(*args)}"
18
+ "#{info}; #{date_time.to_s(*args)}"
24
19
  end
25
-
26
20
  end
27
21
  end
@@ -4,29 +4,19 @@ require 'mail/encodings/8bit'
4
4
 
5
5
  module Mail
6
6
  module Encodings
7
+ # 7bit and 8bit are equivalent. 7bit encoding is for text only.
7
8
  class SevenBit < EightBit
8
9
  NAME = '7bit'
9
-
10
10
  PRIORITY = 1
11
+ Encodings.register(NAME, self)
11
12
 
12
- # 7bit and 8bit operate the same
13
-
14
- # Decode the string
15
13
  def self.decode(str)
16
- super
14
+ ::Mail::Utilities.binary_unsafe_to_lf str
17
15
  end
18
-
19
- # Encode the string
16
+
20
17
  def self.encode(str)
21
- super
22
- end
23
-
24
- # Idenity encodings have a fixed cost, 1 byte out per 1 byte in
25
- def self.cost(str)
26
- super
18
+ ::Mail::Utilities.binary_unsafe_to_crlf str
27
19
  end
28
-
29
- Encodings.register(NAME, self)
30
20
  end
31
21
  end
32
22
  end
@@ -6,32 +6,13 @@ module Mail
6
6
  module Encodings
7
7
  class EightBit < Binary
8
8
  NAME = '8bit'
9
-
10
9
  PRIORITY = 4
11
-
12
- # 8bit is an identiy encoding, meaning nothing to do
13
-
14
- # Decode the string
15
- def self.decode(str)
16
- ::Mail::Utilities.to_lf str
17
- end
18
-
19
- # Encode the string
20
- def self.encode(str)
21
- ::Mail::Utilities.to_crlf str
22
- end
23
-
24
- # Idenity encodings have a fixed cost, 1 byte out per 1 byte in
25
- def self.cost(str)
26
- 1.0
27
- end
10
+ Encodings.register(NAME, self)
28
11
 
29
12
  # Per RFC 2821 4.5.3.1, SMTP lines may not be longer than 1000 octets including the <CRLF>.
30
13
  def self.compatible_input?(str)
31
- !str.lines.find { |line| line.length > 998 }
14
+ !str.lines.find { |line| line.bytesize > 998 }
32
15
  end
33
-
34
- Encodings.register(NAME, self)
35
16
  end
36
17
  end
37
18
  end
@@ -4,36 +4,35 @@ require 'mail/encodings/7bit'
4
4
 
5
5
  module Mail
6
6
  module Encodings
7
+ # Base64 encoding handles binary content at the cost of 4 output bytes
8
+ # per input byte.
7
9
  class Base64 < SevenBit
8
10
  NAME = 'base64'
9
-
10
11
  PRIORITY = 3
11
-
12
+ Encodings.register(NAME, self)
13
+
12
14
  def self.can_encode?(enc)
13
15
  true
14
16
  end
15
17
 
16
- # Decode the string from Base64
17
18
  def self.decode(str)
18
- RubyVer.decode_base64( str )
19
+ RubyVer.decode_base64(str)
19
20
  end
20
-
21
- # Encode the string to Base64
21
+
22
22
  def self.encode(str)
23
- ::Mail::Utilities.to_crlf(RubyVer.encode_base64( str ))
23
+ ::Mail::Utilities.binary_unsafe_to_crlf(RubyVer.encode_base64(str))
24
24
  end
25
25
 
26
- # Base64 has a fixed cost, 4 bytes out per 3 bytes in
26
+ # 3 bytes in -> 4 bytes out
27
27
  def self.cost(str)
28
- 4.0/3
28
+ 4.0 / 3
29
29
  end
30
30
 
31
- # Base64 inserts newlines automatically and cannot violate the SMTP spec.
31
+ # Ruby Base64 inserts newlines automatically, so it doesn't exceed
32
+ # SMTP line length limits.
32
33
  def self.compatible_input?(str)
33
34
  true
34
35
  end
35
-
36
- Encodings.register(NAME, self)
37
36
  end
38
37
  end
39
38
  end
@@ -1,32 +1,13 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/encodings/transfer_encoding'
3
+ require 'mail/encodings/identity'
4
4
 
5
5
  module Mail
6
6
  module Encodings
7
- class Binary < TransferEncoding
7
+ class Binary < Identity
8
8
  NAME = 'binary'
9
-
10
9
  PRIORITY = 5
11
-
12
- # Binary is an identiy encoding, meaning nothing to do
13
-
14
- # Decode the string
15
- def self.decode(str)
16
- str
17
- end
18
-
19
- # Encode the string
20
- def self.encode(str)
21
- str
22
- end
23
-
24
- # Idenity encodings have a fixed cost, 1 byte out per 1 byte in
25
- def self.cost(str)
26
- 1.0
27
- end
28
-
29
- Encodings.register(NAME, self)
10
+ Encodings.register(NAME, self)
30
11
  end
31
12
  end
32
13
  end