mail 2.6.3 → 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 (178) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +91 -79
  4. data/lib/mail/attachments_list.rb +11 -5
  5. data/lib/mail/body.rb +54 -41
  6. data/lib/mail/check_delivery_params.rb +50 -10
  7. data/lib/mail/configuration.rb +3 -0
  8. data/lib/mail/constants.rb +5 -3
  9. data/lib/mail/core_extensions/smtp.rb +20 -16
  10. data/lib/mail/core_extensions/string.rb +1 -30
  11. data/lib/mail/elements/address.rb +43 -32
  12. data/lib/mail/elements/address_list.rb +11 -18
  13. data/lib/mail/elements/content_disposition_element.rb +9 -15
  14. data/lib/mail/elements/content_location_element.rb +8 -12
  15. data/lib/mail/elements/content_transfer_encoding_element.rb +6 -10
  16. data/lib/mail/elements/content_type_element.rb +9 -19
  17. data/lib/mail/elements/date_time_element.rb +7 -14
  18. data/lib/mail/elements/envelope_from_element.rb +15 -21
  19. data/lib/mail/elements/message_ids_element.rb +12 -14
  20. data/lib/mail/elements/mime_version_element.rb +7 -14
  21. data/lib/mail/elements/phrase_list.rb +7 -9
  22. data/lib/mail/elements/received_element.rb +10 -15
  23. data/lib/mail/elements.rb +1 -0
  24. data/lib/mail/encodings/7bit.rb +6 -15
  25. data/lib/mail/encodings/8bit.rb +5 -18
  26. data/lib/mail/encodings/base64.rb +15 -10
  27. data/lib/mail/encodings/binary.rb +4 -22
  28. data/lib/mail/encodings/identity.rb +24 -0
  29. data/lib/mail/encodings/quoted_printable.rb +13 -7
  30. data/lib/mail/encodings/transfer_encoding.rb +47 -28
  31. data/lib/mail/encodings/unix_to_unix.rb +4 -1
  32. data/lib/mail/encodings.rb +114 -60
  33. data/lib/mail/envelope.rb +2 -1
  34. data/lib/mail/field.rb +114 -62
  35. data/lib/mail/field_list.rb +1 -0
  36. data/lib/mail/fields/bcc_field.rb +17 -5
  37. data/lib/mail/fields/cc_field.rb +2 -2
  38. data/lib/mail/fields/comments_field.rb +2 -1
  39. data/lib/mail/fields/common/address_container.rb +3 -2
  40. data/lib/mail/fields/common/common_address.rb +40 -14
  41. data/lib/mail/fields/common/common_date.rb +2 -1
  42. data/lib/mail/fields/common/common_field.rb +5 -11
  43. data/lib/mail/fields/common/common_message_id.rb +3 -2
  44. data/lib/mail/fields/common/parameter_hash.rb +2 -1
  45. data/lib/mail/fields/content_description_field.rb +2 -1
  46. data/lib/mail/fields/content_disposition_field.rb +14 -13
  47. data/lib/mail/fields/content_id_field.rb +5 -4
  48. data/lib/mail/fields/content_location_field.rb +3 -2
  49. data/lib/mail/fields/content_transfer_encoding_field.rb +3 -2
  50. data/lib/mail/fields/content_type_field.rb +7 -11
  51. data/lib/mail/fields/date_field.rb +4 -4
  52. data/lib/mail/fields/from_field.rb +2 -2
  53. data/lib/mail/fields/in_reply_to_field.rb +2 -1
  54. data/lib/mail/fields/keywords_field.rb +3 -3
  55. data/lib/mail/fields/message_id_field.rb +3 -2
  56. data/lib/mail/fields/mime_version_field.rb +4 -3
  57. data/lib/mail/fields/optional_field.rb +5 -1
  58. data/lib/mail/fields/received_field.rb +5 -4
  59. data/lib/mail/fields/references_field.rb +2 -1
  60. data/lib/mail/fields/reply_to_field.rb +2 -2
  61. data/lib/mail/fields/resent_bcc_field.rb +2 -2
  62. data/lib/mail/fields/resent_cc_field.rb +2 -2
  63. data/lib/mail/fields/resent_date_field.rb +2 -2
  64. data/lib/mail/fields/resent_from_field.rb +2 -2
  65. data/lib/mail/fields/resent_message_id_field.rb +2 -1
  66. data/lib/mail/fields/resent_sender_field.rb +2 -2
  67. data/lib/mail/fields/resent_to_field.rb +2 -2
  68. data/lib/mail/fields/return_path_field.rb +2 -2
  69. data/lib/mail/fields/sender_field.rb +2 -2
  70. data/lib/mail/fields/structured_field.rb +1 -0
  71. data/lib/mail/fields/subject_field.rb +2 -1
  72. data/lib/mail/fields/to_field.rb +2 -2
  73. data/lib/mail/fields/unstructured_field.rb +25 -7
  74. data/lib/mail/fields.rb +1 -0
  75. data/lib/mail/header.rb +15 -12
  76. data/lib/mail/indifferent_hash.rb +1 -0
  77. data/lib/mail/mail.rb +3 -10
  78. data/lib/mail/matchers/attachment_matchers.rb +29 -0
  79. data/lib/mail/matchers/has_sent_mail.rb +51 -7
  80. data/lib/mail/message.rb +91 -86
  81. data/lib/mail/multibyte/chars.rb +32 -30
  82. data/lib/mail/multibyte/unicode.rb +31 -26
  83. data/lib/mail/multibyte/utils.rb +1 -0
  84. data/lib/mail/multibyte.rb +65 -15
  85. data/lib/mail/network/delivery_methods/exim.rb +7 -10
  86. data/lib/mail/network/delivery_methods/file_delivery.rb +5 -8
  87. data/lib/mail/network/delivery_methods/logger_delivery.rb +37 -0
  88. data/lib/mail/network/delivery_methods/sendmail.rb +17 -11
  89. data/lib/mail/network/delivery_methods/smtp.rb +60 -53
  90. data/lib/mail/network/delivery_methods/smtp_connection.rb +11 -6
  91. data/lib/mail/network/delivery_methods/test_mailer.rb +6 -8
  92. data/lib/mail/network/retriever_methods/base.rb +1 -0
  93. data/lib/mail/network/retriever_methods/imap.rb +19 -5
  94. data/lib/mail/network/retriever_methods/pop3.rb +4 -1
  95. data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
  96. data/lib/mail/network.rb +2 -0
  97. data/lib/mail/parser_tools.rb +15 -0
  98. data/lib/mail/parsers/address_lists_parser.rb +33208 -104
  99. data/lib/mail/parsers/address_lists_parser.rl +172 -0
  100. data/lib/mail/parsers/content_disposition_parser.rb +877 -49
  101. data/lib/mail/parsers/content_disposition_parser.rl +82 -0
  102. data/lib/mail/parsers/content_location_parser.rb +804 -23
  103. data/lib/mail/parsers/content_location_parser.rl +71 -0
  104. data/lib/mail/parsers/content_transfer_encoding_parser.rb +502 -19
  105. data/lib/mail/parsers/content_transfer_encoding_parser.rl +64 -0
  106. data/lib/mail/parsers/content_type_parser.rb +1024 -48
  107. data/lib/mail/parsers/content_type_parser.rl +83 -0
  108. data/lib/mail/parsers/date_time_parser.rb +872 -23
  109. data/lib/mail/parsers/date_time_parser.rl +62 -0
  110. data/lib/mail/parsers/envelope_from_parser.rb +3570 -34
  111. data/lib/mail/parsers/envelope_from_parser.rl +82 -0
  112. data/lib/mail/parsers/message_ids_parser.rb +2840 -25
  113. data/lib/mail/parsers/message_ids_parser.rl +82 -0
  114. data/lib/mail/parsers/mime_version_parser.rb +492 -26
  115. data/lib/mail/parsers/mime_version_parser.rl +61 -0
  116. data/lib/mail/parsers/phrase_lists_parser.rb +862 -17
  117. data/lib/mail/parsers/phrase_lists_parser.rl +83 -0
  118. data/lib/mail/parsers/received_parser.rb +8765 -36
  119. data/lib/mail/parsers/received_parser.rl +84 -0
  120. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  121. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  122. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  123. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  124. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  125. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  126. data/lib/mail/parsers/rfc5322.rl +59 -0
  127. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  128. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
  129. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  130. data/lib/mail/parsers.rb +17 -24
  131. data/lib/mail/part.rb +8 -5
  132. data/lib/mail/parts_list.rb +31 -14
  133. data/lib/mail/utilities.rb +109 -10
  134. data/lib/mail/values/unicode_tables.dat +0 -0
  135. data/lib/mail/version.rb +3 -2
  136. data/lib/mail/version_specific/ruby_1_8.rb +50 -6
  137. data/lib/mail/version_specific/ruby_1_9.rb +103 -18
  138. data/lib/mail.rb +5 -12
  139. metadata +47 -57
  140. data/CHANGELOG.rdoc +0 -759
  141. data/CONTRIBUTING.md +0 -60
  142. data/Dependencies.txt +0 -2
  143. data/Gemfile +0 -15
  144. data/Rakefile +0 -29
  145. data/TODO.rdoc +0 -9
  146. data/lib/mail/core_extensions/nil.rb +0 -19
  147. data/lib/mail/core_extensions/object.rb +0 -13
  148. data/lib/mail/core_extensions/string/access.rb +0 -145
  149. data/lib/mail/core_extensions/string/multibyte.rb +0 -78
  150. data/lib/mail/multibyte/exceptions.rb +0 -8
  151. data/lib/mail/parsers/ragel/common.rl +0 -185
  152. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  153. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  154. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  155. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  156. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  157. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  158. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  159. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  160. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  161. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  162. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  163. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  164. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  165. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  166. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  167. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  168. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  169. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  170. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  171. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  172. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  173. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  174. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  175. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  176. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  177. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  178. data/lib/mail/parsers/ragel.rb +0 -17
@@ -1,20 +1,60 @@
1
+ # frozen_string_literal: true
1
2
  module Mail
2
- module CheckDeliveryParams
3
- def check_delivery_params(mail)
4
- if mail.smtp_envelope_from.blank?
5
- raise ArgumentError.new('An SMTP From address is required to send a message. Set the message smtp_envelope_from, return_path, sender, or from address.')
3
+ module CheckDeliveryParams #:nodoc:
4
+ class << self
5
+ def check(mail)
6
+ [ check_from(mail.smtp_envelope_from),
7
+ check_to(mail.smtp_envelope_to),
8
+ check_message(mail) ]
6
9
  end
7
10
 
8
- if mail.smtp_envelope_to.blank?
9
- raise ArgumentError.new('An SMTP To address is required to send a message. Set the message smtp_envelope_to, to, cc, or bcc address.')
11
+ def check_from(addr)
12
+ if Utilities.blank?(addr)
13
+ raise ArgumentError, "SMTP From address may not be blank: #{addr.inspect}"
14
+ end
15
+
16
+ check_addr 'From', addr
17
+ end
18
+
19
+ def check_to(addrs)
20
+ if Utilities.blank?(addrs)
21
+ raise ArgumentError, "SMTP To address may not be blank: #{addrs.inspect}"
22
+ end
23
+
24
+ Array(addrs).map do |addr|
25
+ check_addr 'To', addr
26
+ end
10
27
  end
11
28
 
12
- message = mail.encoded if mail.respond_to?(:encoded)
13
- if message.blank?
14
- raise ArgumentError.new('An encoded message is required to send an email')
29
+ def check_addr(addr_name, addr)
30
+ validate_smtp_addr addr do |error_message|
31
+ raise ArgumentError, "SMTP #{addr_name} address #{error_message}: #{addr.inspect}"
32
+ end
15
33
  end
16
34
 
17
- [mail.smtp_envelope_from, mail.smtp_envelope_to, message]
35
+ def validate_smtp_addr(addr)
36
+ if addr
37
+ if addr.bytesize > 2048
38
+ yield 'may not exceed 2kB'
39
+ end
40
+
41
+ if /[\r\n]/ =~ addr
42
+ yield 'may not contain CR or LF line breaks'
43
+ end
44
+ end
45
+
46
+ addr
47
+ end
48
+
49
+ def check_message(message)
50
+ message = message.encoded if message.respond_to?(:encoded)
51
+
52
+ if Utilities.blank?(message)
53
+ raise ArgumentError, 'An encoded message is required to send an email'
54
+ end
55
+
56
+ message
57
+ end
18
58
  end
19
59
  end
20
60
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # Thanks to Nicolas Fouché for this wrapper
4
5
  #
@@ -41,6 +42,8 @@ module Mail
41
42
  Mail::SMTPConnection
42
43
  when :test
43
44
  Mail::TestMailer
45
+ when :logger
46
+ Mail::LoggerDelivery
44
47
  else
45
48
  method
46
49
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: us-ascii
2
+ # frozen_string_literal: true
2
3
  module Mail
3
4
  module Constants
4
5
  white_space = %Q|\x9\x20|
@@ -12,10 +13,10 @@ module Mail
12
13
  control = %Q|\x00-\x1f\x7f-\xff|
13
14
 
14
15
  if control.respond_to?(:force_encoding)
15
- control = control.force_encoding(Encoding::BINARY)
16
+ control = control.dup.force_encoding(Encoding::BINARY)
16
17
  end
17
18
 
18
- CRLF = /\r\n/
19
+ CRLF = /\r?\n/
19
20
  WSP = /[#{white_space}]/
20
21
  FWS = /#{CRLF}#{WSP}*/
21
22
  TEXT = /[#{text}]/ # + obs-text
@@ -33,7 +34,8 @@ module Mail
33
34
  ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{sp}]/n
34
35
  PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
35
36
  TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{sp}]/n
36
- ENCODED_VALUE = /\=\?[^?]+\?([QB])\?[^?]*?\?\=/mi
37
+ ENCODED_VALUE = /\=\?([^?]+)\?([QB])\?[^?]*?\?\=/mi
38
+ FULL_ENCODED_VALUE = /(\=\?[^?]+\?[QB]\?[^?]*?\?\=)/mi
37
39
 
38
40
  EMPTY = ''
39
41
  SPACE = ' '
@@ -1,24 +1,28 @@
1
1
  # encoding: utf-8
2
- module Net
3
- class SMTP
4
- # This is a backport of r30294 from ruby trunk because of a bug in net/smtp.
5
- # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&amp;revision=30294
6
- #
7
- # Fixed in what will be Ruby 1.9.3 - tlsconnect also does not exist in some early versions of ruby
8
- begin
9
- alias_method :original_tlsconnect, :tlsconnect
2
+ # frozen_string_literal: true
10
3
 
11
- def tlsconnect(s)
12
- verified = false
13
- begin
14
- original_tlsconnect(s).tap { verified = true }
15
- ensure
16
- unless verified
17
- s.close rescue nil
4
+ # This is a backport of r30294 from ruby trunk because of a bug in net/smtp.
5
+ # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&amp;revision=30294
6
+ #
7
+ # Fixed in Ruby 1.9.3 - tlsconnect also does not exist in some early versions of ruby
8
+ if RUBY_VERSION < '1.9.3'
9
+ module Net
10
+ class SMTP
11
+ begin
12
+ alias_method :original_tlsconnect, :tlsconnect
13
+
14
+ def tlsconnect(s)
15
+ verified = false
16
+ begin
17
+ original_tlsconnect(s).tap { verified = true }
18
+ ensure
19
+ unless verified
20
+ s.close rescue nil
21
+ end
18
22
  end
19
23
  end
24
+ rescue NameError
20
25
  end
21
- rescue NameError
22
26
  end
23
27
  end
24
28
  end
@@ -1,32 +1,7 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  class String #:nodoc:
3
4
 
4
- CRLF = "\r\n"
5
- LF = "\n"
6
-
7
- if RUBY_VERSION >= '1.9'
8
- # This 1.9 only regex can save a reasonable amount of time (~20%)
9
- # by not matching "\r\n" so the string is returned unchanged in
10
- # the common case.
11
- CRLF_REGEX = Regexp.new("(?<!\r)\n|\r(?!\n)")
12
- else
13
- CRLF_REGEX = /\n|\r\n|\r/
14
- end
15
-
16
- def to_crlf
17
- to_str.gsub(CRLF_REGEX, CRLF)
18
- end
19
-
20
- def to_lf
21
- to_str.gsub(/\r\n|\r/, LF)
22
- end
23
-
24
- unless String.instance_methods(false).map {|m| m.to_sym}.include?(:blank?)
25
- def blank?
26
- self !~ /\S/
27
- end
28
- end
29
-
30
5
  unless method_defined?(:ascii_only?)
31
6
  # Backport from Ruby 1.9 checks for non-us-ascii characters.
32
7
  def ascii_only?
@@ -36,10 +11,6 @@ class String #:nodoc:
36
11
  MATCH_NON_US_ASCII = /[^\x00-\x7f]/
37
12
  end
38
13
 
39
- def not_ascii_only?
40
- !ascii_only?
41
- end
42
-
43
14
  unless method_defined?(:bytesize)
44
15
  alias :bytesize :length
45
16
  end
@@ -1,7 +1,9 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/address_lists_parser'
4
+
2
5
  module Mail
3
6
  class Address
4
-
5
7
  include Mail::Utilities
6
8
 
7
9
  # Mail::Address handles all email addresses in Mail. It takes an email address string
@@ -21,7 +23,6 @@ module Mail
21
23
  # a.comments #=> ['My email address']
22
24
  # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
23
25
  def initialize(value = nil)
24
- @output_type = :decode
25
26
  if value.nil?
26
27
  @parsed = false
27
28
  @data = nil
@@ -43,14 +44,14 @@ module Mail
43
44
  #
44
45
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
45
46
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
46
- def format
47
+ def format(output_type = :decode)
47
48
  parse unless @parsed
48
49
  if @data.nil?
49
50
  EMPTY
50
- elsif display_name
51
- [quote_phrase(display_name), "<#{address}>", format_comments].compact.join(SPACE)
52
- elsif address
53
- [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)
54
55
  else
55
56
  raw
56
57
  end
@@ -61,9 +62,13 @@ module Mail
61
62
  #
62
63
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
63
64
  # a.address #=> 'mikel@test.lindsaar.net'
64
- def address
65
+ def address(output_type = :decode)
65
66
  parse unless @parsed
66
- domain ? "#{local}@#{domain}" : local
67
+ if d = domain(output_type)
68
+ "#{local(output_type)}@#{d}"
69
+ else
70
+ local(output_type)
71
+ end
67
72
  end
68
73
 
69
74
  # Provides a way to assign an address to an already made Mail::Address object.
@@ -79,10 +84,10 @@ module Mail
79
84
  #
80
85
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
81
86
  # a.display_name #=> 'Mikel Lindsaar'
82
- def display_name
87
+ def display_name(output_type = :decode)
83
88
  parse unless @parsed
84
89
  @display_name ||= get_display_name
85
- 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
86
91
  end
87
92
 
88
93
  # Provides a way to assign a display name to an already made Mail::Address object.
@@ -92,7 +97,7 @@ module Mail
92
97
  # a.display_name = 'Mikel Lindsaar'
93
98
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>'
94
99
  def display_name=( str )
95
- @display_name = str
100
+ @display_name = str.nil? ? nil : str.dup # in case frozen
96
101
  end
97
102
 
98
103
  # Returns the local part (the left hand side of the @ sign in the email address) of
@@ -100,9 +105,9 @@ module Mail
100
105
  #
101
106
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
102
107
  # a.local #=> 'mikel'
103
- def local
108
+ def local(output_type = :decode)
104
109
  parse unless @parsed
105
- "#{@data.obs_domain_list}#{get_local.strip}" if get_local
110
+ Encodings.decode_encode("#{@data.obs_domain_list}#{get_local.strip}", output_type) if get_local
106
111
  end
107
112
 
108
113
  # Returns the domain part (the right hand side of the @ sign in the email address) of
@@ -110,19 +115,28 @@ module Mail
110
115
  #
111
116
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
112
117
  # a.domain #=> 'test.lindsaar.net'
113
- def domain
118
+ def domain(output_type = :decode)
114
119
  parse unless @parsed
115
- strip_all_comments(get_domain) if get_domain
120
+ Encodings.decode_encode(strip_all_comments(get_domain), output_type) if get_domain
116
121
  end
117
122
 
118
- # 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
119
124
  # are no comments
120
125
  #
121
126
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
122
127
  # a.comments #=> ['My email address']
128
+ #
129
+ # b = Address.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
130
+ # b.comments #=> nil
131
+
123
132
  def comments
124
133
  parse unless @parsed
125
- get_comments.map { |c| c.squeeze(SPACE) } unless get_comments.empty?
134
+ comments = get_comments
135
+ if comments.nil? || comments.none?
136
+ nil
137
+ else
138
+ comments.map { |c| c.squeeze(SPACE) }
139
+ end
126
140
  end
127
141
 
128
142
  # Sometimes an address will not have a display name, but might have the name
@@ -153,13 +167,11 @@ module Mail
153
167
  end
154
168
 
155
169
  def encoded
156
- @output_type = :encode
157
- format
170
+ format :encode
158
171
  end
159
172
 
160
173
  def decoded
161
- @output_type = :decode
162
- format
174
+ format :decode
163
175
  end
164
176
 
165
177
  def group
@@ -173,18 +185,18 @@ module Mail
173
185
  @data = nil
174
186
 
175
187
  case value
176
- when Mail::Parsers::AddressStruct
188
+ when Mail::Parsers::AddressListsParser::AddressStruct
177
189
  @data = value
178
190
  when String
179
- unless value.blank?
180
- address_list = Mail::Parsers::AddressListsParser.new.parse(value)
191
+ unless Utilities.blank?(value)
192
+ address_list = Mail::Parsers::AddressListsParser.parse(value)
181
193
  @data = address_list.addresses.first
182
194
  end
183
195
  end
184
196
  end
185
197
 
186
198
  def strip_all_comments(string)
187
- unless comments.blank?
199
+ unless Utilities.blank?(comments)
188
200
  comments.each do |comment|
189
201
  string = string.gsub("(#{comment})", EMPTY)
190
202
  end
@@ -193,7 +205,7 @@ module Mail
193
205
  end
194
206
 
195
207
  def strip_domain_comments(value)
196
- unless comments.blank?
208
+ unless Utilities.blank?(comments)
197
209
  comments.each do |comment|
198
210
  if @data.domain && @data.domain.include?("(#{comment})")
199
211
  value = value.gsub("(#{comment})", EMPTY)
@@ -204,13 +216,12 @@ module Mail
204
216
  end
205
217
 
206
218
  def get_display_name
207
- if @data.display_name
219
+ if @data && @data.display_name
208
220
  str = strip_all_comments(@data.display_name.to_s)
209
- elsif @data.comments && @data.domain
221
+ elsif @data && @data.comments && @data.domain
210
222
  str = strip_domain_comments(format_comments)
211
223
  end
212
-
213
- str unless str.blank?
224
+ str unless Utilities.blank?(str)
214
225
  end
215
226
 
216
227
  def get_name
@@ -220,7 +231,7 @@ module Mail
220
231
  str = "(#{comments.join(SPACE).squeeze(SPACE)})"
221
232
  end
222
233
 
223
- unparen(str) unless str.blank?
234
+ unparen(str) unless Utilities.blank?(str)
224
235
  end
225
236
 
226
237
  def format_comments
@@ -1,41 +1,34 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/address_lists_parser'
4
+
2
5
  module Mail
3
6
  class AddressList # :nodoc:
7
+ attr_reader :addresses, :group_names
4
8
 
5
9
  # Mail::AddressList is the class that parses To, From and other address fields from
6
10
  # emails passed into Mail.
7
- #
11
+ #
8
12
  # AddressList provides a way to query the groups and mailbox lists of the passed in
9
13
  # string.
10
- #
14
+ #
11
15
  # It can supply all addresses in an array, or return each address as an address object.
12
- #
16
+ #
13
17
  # Mail::AddressList requires a correctly formatted group or mailbox list per RFC2822 or
14
18
  # RFC822. It also handles all obsolete versions in those RFCs.
15
- #
19
+ #
16
20
  # list = 'ada@test.lindsaar.net, My Group: mikel@test.lindsaar.net, Bob <bob@test.lindsaar.net>;'
17
21
  # a = AddressList.new(list)
18
22
  # a.addresses #=> [#<Mail::Address:14943130 Address: |ada@test.lindsaar.net...
19
23
  # a.group_names #=> ["My Group"]
20
24
  def initialize(string)
21
- @addresses_grouped_by_group = nil
22
- @address_list = Parsers::AddressListsParser.new.parse(string)
23
- end
24
-
25
- # Returns a list of address objects from the parsed line
26
- def addresses
27
- @addresses ||= @address_list.addresses.map do |address_data|
28
- Mail::Address.new(address_data)
29
- 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
30
28
  end
31
29
 
32
30
  def addresses_grouped_by_group
33
31
  addresses.select(&:group).group_by(&:group)
34
32
  end
35
-
36
- # Returns the names as an array of strings of all groups
37
- def group_names # :nodoc:
38
- @address_list.group_names
39
- end
40
33
  end
41
34
  end
@@ -1,26 +1,20 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/content_disposition_parser'
4
+
2
5
  module Mail
3
6
  class ContentDispositionElement # :nodoc:
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- 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))
9
11
  @disposition_type = content_disposition.disposition_type
10
12
  @parameters = content_disposition.parameters
11
13
  end
12
-
13
- def disposition_type
14
- @disposition_type
15
- end
16
-
17
- def parameters
18
- @parameters
19
- end
20
-
14
+
15
+ private
21
16
  def cleaned(string)
22
17
  string =~ /(.+);\s*$/ ? $1 : string
23
18
  end
24
-
25
19
  end
26
20
  end
@@ -1,21 +1,17 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/content_location_parser'
4
+
2
5
  module Mail
3
6
  class ContentLocationElement # :nodoc:
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- content_location = Mail::Parsers::ContentLocationParser.new.parse(string)
9
- @location = content_location.location
7
+ attr_reader :location
8
+
9
+ def initialize(string)
10
+ @location = Mail::Parsers::ContentLocationParser.parse(string).location
10
11
  end
11
-
12
- def location
13
- @location
14
- end
15
-
12
+
16
13
  def to_s(*args)
17
14
  location.to_s
18
15
  end
19
-
20
16
  end
21
17
  end
@@ -1,17 +1,13 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/content_transfer_encoding_parser'
4
+
2
5
  module Mail
3
6
  class ContentTransferEncodingElement
4
-
5
- include Mail::Utilities
6
-
7
+ attr_reader :encoding
8
+
7
9
  def initialize(string)
8
- content_transfer_encoding = Mail::Parsers::ContentTransferEncodingParser.new.parse(string)
9
- @encoding = content_transfer_encoding.encoding
10
+ @encoding = Mail::Parsers::ContentTransferEncodingParser.parse(string).encoding
10
11
  end
11
-
12
- def encoding
13
- @encoding
14
- end
15
-
16
12
  end
17
13
  end
@@ -1,31 +1,21 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/content_type_parser'
4
+
2
5
  module Mail
3
6
  class ContentTypeElement # :nodoc:
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- 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))
9
11
  @main_type = content_type.main_type
10
12
  @sub_type = content_type.sub_type
11
13
  @parameters = content_type.parameters
12
14
  end
13
-
14
- def main_type
15
- @main_type
16
- end
17
-
18
- def sub_type
19
- @sub_type
20
- end
21
-
22
- def parameters
23
- @parameters
24
- end
25
-
15
+
16
+ private
26
17
  def cleaned(string)
27
18
  string =~ /(.+);\s*$/ ? $1 : string
28
19
  end
29
-
30
20
  end
31
21
  end
@@ -1,22 +1,15 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/date_time_parser'
4
+
2
5
  module Mail
3
6
  class DateTimeElement # :nodoc:
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- 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)
9
11
  @date_string = date_time.date_string
10
12
  @time_string = date_time.time_string
11
13
  end
12
-
13
- def date_string
14
- @date_string
15
- end
16
-
17
- def time_string
18
- @time_string
19
- end
20
-
21
14
  end
22
15
  end
@@ -1,39 +1,33 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/envelope_from_parser'
4
+ require 'date'
5
+
2
6
  module Mail
3
7
  class EnvelopeFromElement
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- @envelope_from = Mail::Parsers::EnvelopeFromParser.new.parse(string)
9
- @address = @envelope_from.address
10
- @date_time = ::DateTime.parse(@envelope_from.ctime_date)
11
- end
12
-
13
- def date_time
14
- @date_time
15
- end
16
-
17
- def address
18
- @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)
19
14
  end
20
-
15
+
21
16
  # RFC 4155:
22
17
  # a timestamp indicating the UTC date and time when the message
23
18
  # was originally received, conformant with the syntax of the
24
19
  # traditional UNIX 'ctime' output sans timezone (note that the
25
20
  # use of UTC precludes the need for a timezone indicator);
26
21
  def formatted_date_time
27
- if @date_time.respond_to?(:ctime)
28
- @date_time.ctime
22
+ if date_time.respond_to?(:ctime)
23
+ date_time.ctime
29
24
  else
30
- @date_time.strftime '%a %b %e %T %Y'
25
+ date_time.strftime '%a %b %e %T %Y'
31
26
  end
32
27
  end
33
28
 
34
29
  def to_s
35
- "#{@address} #{formatted_date_time}"
30
+ "#{address} #{formatted_date_time}"
36
31
  end
37
-
38
32
  end
39
33
  end