mail 2.6.6 → 2.7.1

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.
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