mail 2.5.5 → 2.8.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 (191) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +170 -108
  4. data/lib/mail/attachments_list.rb +13 -10
  5. data/lib/mail/body.rb +105 -91
  6. data/lib/mail/check_delivery_params.rb +30 -22
  7. data/lib/mail/configuration.rb +3 -0
  8. data/lib/mail/constants.rb +79 -0
  9. data/lib/mail/elements/address.rb +118 -174
  10. data/lib/mail/elements/address_list.rb +16 -56
  11. data/lib/mail/elements/content_disposition_element.rb +12 -22
  12. data/lib/mail/elements/content_location_element.rb +9 -17
  13. data/lib/mail/elements/content_transfer_encoding_element.rb +8 -19
  14. data/lib/mail/elements/content_type_element.rb +20 -30
  15. data/lib/mail/elements/date_time_element.rb +10 -21
  16. data/lib/mail/elements/envelope_from_element.rb +23 -31
  17. data/lib/mail/elements/message_ids_element.rb +22 -20
  18. data/lib/mail/elements/mime_version_element.rb +10 -21
  19. data/lib/mail/elements/phrase_list.rb +13 -15
  20. data/lib/mail/elements/received_element.rb +26 -21
  21. data/lib/mail/elements.rb +1 -0
  22. data/lib/mail/encodings/7bit.rb +10 -14
  23. data/lib/mail/encodings/8bit.rb +5 -18
  24. data/lib/mail/encodings/base64.rb +15 -10
  25. data/lib/mail/encodings/binary.rb +4 -22
  26. data/lib/mail/encodings/identity.rb +24 -0
  27. data/lib/mail/encodings/quoted_printable.rb +13 -7
  28. data/lib/mail/encodings/transfer_encoding.rb +47 -28
  29. data/lib/mail/encodings/unix_to_unix.rb +20 -0
  30. data/lib/mail/encodings.rb +102 -93
  31. data/lib/mail/envelope.rb +12 -19
  32. data/lib/mail/field.rb +143 -71
  33. data/lib/mail/field_list.rb +73 -19
  34. data/lib/mail/fields/bcc_field.rb +42 -48
  35. data/lib/mail/fields/cc_field.rb +29 -50
  36. data/lib/mail/fields/comments_field.rb +28 -37
  37. data/lib/mail/fields/common_address_field.rb +170 -0
  38. data/lib/mail/fields/common_date_field.rb +58 -0
  39. data/lib/mail/fields/common_field.rb +77 -0
  40. data/lib/mail/fields/common_message_id_field.rb +42 -0
  41. data/lib/mail/fields/content_description_field.rb +8 -14
  42. data/lib/mail/fields/content_disposition_field.rb +20 -44
  43. data/lib/mail/fields/content_id_field.rb +25 -51
  44. data/lib/mail/fields/content_location_field.rb +12 -25
  45. data/lib/mail/fields/content_transfer_encoding_field.rb +31 -36
  46. data/lib/mail/fields/content_type_field.rb +51 -80
  47. data/lib/mail/fields/date_field.rb +24 -52
  48. data/lib/mail/fields/from_field.rb +29 -50
  49. data/lib/mail/fields/in_reply_to_field.rb +39 -49
  50. data/lib/mail/fields/keywords_field.rb +19 -32
  51. data/lib/mail/fields/message_id_field.rb +26 -71
  52. data/lib/mail/fields/mime_version_field.rb +20 -30
  53. data/lib/mail/fields/named_structured_field.rb +11 -0
  54. data/lib/mail/fields/named_unstructured_field.rb +11 -0
  55. data/lib/mail/fields/optional_field.rb +10 -7
  56. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +16 -13
  57. data/lib/mail/fields/received_field.rb +44 -57
  58. data/lib/mail/fields/references_field.rb +36 -49
  59. data/lib/mail/fields/reply_to_field.rb +29 -50
  60. data/lib/mail/fields/resent_bcc_field.rb +29 -50
  61. data/lib/mail/fields/resent_cc_field.rb +29 -50
  62. data/lib/mail/fields/resent_date_field.rb +6 -30
  63. data/lib/mail/fields/resent_from_field.rb +29 -50
  64. data/lib/mail/fields/resent_message_id_field.rb +6 -29
  65. data/lib/mail/fields/resent_sender_field.rb +28 -57
  66. data/lib/mail/fields/resent_to_field.rb +29 -50
  67. data/lib/mail/fields/return_path_field.rb +51 -55
  68. data/lib/mail/fields/sender_field.rb +35 -56
  69. data/lib/mail/fields/structured_field.rb +4 -30
  70. data/lib/mail/fields/subject_field.rb +10 -11
  71. data/lib/mail/fields/to_field.rb +29 -50
  72. data/lib/mail/fields/unstructured_field.rb +43 -51
  73. data/lib/mail/fields.rb +1 -0
  74. data/lib/mail/header.rb +78 -129
  75. data/lib/mail/indifferent_hash.rb +1 -0
  76. data/lib/mail/mail.rb +18 -11
  77. data/lib/mail/matchers/attachment_matchers.rb +44 -0
  78. data/lib/mail/matchers/has_sent_mail.rb +81 -4
  79. data/lib/mail/message.rb +142 -139
  80. data/lib/mail/multibyte/chars.rb +24 -180
  81. data/lib/mail/multibyte/unicode.rb +32 -27
  82. data/lib/mail/multibyte/utils.rb +27 -43
  83. data/lib/mail/multibyte.rb +56 -16
  84. data/lib/mail/network/delivery_methods/exim.rb +6 -4
  85. data/lib/mail/network/delivery_methods/file_delivery.rb +12 -10
  86. data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  87. data/lib/mail/network/delivery_methods/sendmail.rb +63 -21
  88. data/lib/mail/network/delivery_methods/smtp.rb +76 -50
  89. data/lib/mail/network/delivery_methods/smtp_connection.rb +4 -4
  90. data/lib/mail/network/delivery_methods/test_mailer.rb +5 -2
  91. data/lib/mail/network/retriever_methods/base.rb +9 -8
  92. data/lib/mail/network/retriever_methods/imap.rb +37 -18
  93. data/lib/mail/network/retriever_methods/pop3.rb +6 -3
  94. data/lib/mail/network/retriever_methods/test_retriever.rb +4 -2
  95. data/lib/mail/network.rb +2 -0
  96. data/lib/mail/parser_tools.rb +15 -0
  97. data/lib/mail/parsers/address_lists_parser.rb +33242 -0
  98. data/lib/mail/parsers/address_lists_parser.rl +179 -0
  99. data/lib/mail/parsers/content_disposition_parser.rb +901 -0
  100. data/lib/mail/parsers/content_disposition_parser.rl +89 -0
  101. data/lib/mail/parsers/content_location_parser.rb +822 -0
  102. data/lib/mail/parsers/content_location_parser.rl +78 -0
  103. data/lib/mail/parsers/content_transfer_encoding_parser.rb +522 -0
  104. data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
  105. data/lib/mail/parsers/content_type_parser.rb +1048 -0
  106. data/lib/mail/parsers/content_type_parser.rl +90 -0
  107. data/lib/mail/parsers/date_time_parser.rb +891 -0
  108. data/lib/mail/parsers/date_time_parser.rl +69 -0
  109. data/lib/mail/parsers/envelope_from_parser.rb +3675 -0
  110. data/lib/mail/parsers/envelope_from_parser.rl +89 -0
  111. data/lib/mail/parsers/message_ids_parser.rb +5161 -0
  112. data/lib/mail/parsers/message_ids_parser.rl +93 -0
  113. data/lib/mail/parsers/mime_version_parser.rb +513 -0
  114. data/lib/mail/parsers/mime_version_parser.rl +68 -0
  115. data/lib/mail/parsers/phrase_lists_parser.rb +884 -0
  116. data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
  117. data/lib/mail/parsers/received_parser.rb +8782 -0
  118. data/lib/mail/parsers/received_parser.rl +91 -0
  119. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  120. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  121. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  122. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  123. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  124. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  125. data/lib/mail/parsers/rfc5322.rl +74 -0
  126. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  127. data/lib/mail/parsers/rfc5322_date_time.rl +37 -0
  128. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  129. data/lib/mail/parsers.rb +13 -0
  130. data/lib/mail/part.rb +11 -12
  131. data/lib/mail/parts_list.rb +90 -14
  132. data/lib/mail/smtp_envelope.rb +57 -0
  133. data/lib/mail/utilities.rb +415 -76
  134. data/lib/mail/values/unicode_tables.dat +0 -0
  135. data/lib/mail/version.rb +8 -15
  136. data/lib/mail/yaml.rb +30 -0
  137. data/lib/mail.rb +9 -32
  138. metadata +127 -79
  139. data/CHANGELOG.rdoc +0 -742
  140. data/CONTRIBUTING.md +0 -45
  141. data/Dependencies.txt +0 -3
  142. data/Gemfile +0 -32
  143. data/Rakefile +0 -21
  144. data/TODO.rdoc +0 -9
  145. data/lib/VERSION +0 -4
  146. data/lib/load_parsers.rb +0 -35
  147. data/lib/mail/core_extensions/nil.rb +0 -19
  148. data/lib/mail/core_extensions/object.rb +0 -13
  149. data/lib/mail/core_extensions/smtp.rb +0 -24
  150. data/lib/mail/core_extensions/string/access.rb +0 -145
  151. data/lib/mail/core_extensions/string/multibyte.rb +0 -78
  152. data/lib/mail/core_extensions/string.rb +0 -33
  153. data/lib/mail/fields/common/address_container.rb +0 -16
  154. data/lib/mail/fields/common/common_address.rb +0 -140
  155. data/lib/mail/fields/common/common_date.rb +0 -42
  156. data/lib/mail/fields/common/common_field.rb +0 -57
  157. data/lib/mail/fields/common/common_message_id.rb +0 -48
  158. data/lib/mail/multibyte/exceptions.rb +0 -8
  159. data/lib/mail/parsers/address_lists.rb +0 -64
  160. data/lib/mail/parsers/address_lists.treetop +0 -19
  161. data/lib/mail/parsers/content_disposition.rb +0 -535
  162. data/lib/mail/parsers/content_disposition.treetop +0 -46
  163. data/lib/mail/parsers/content_location.rb +0 -139
  164. data/lib/mail/parsers/content_location.treetop +0 -20
  165. data/lib/mail/parsers/content_transfer_encoding.rb +0 -201
  166. data/lib/mail/parsers/content_transfer_encoding.treetop +0 -18
  167. data/lib/mail/parsers/content_type.rb +0 -971
  168. data/lib/mail/parsers/content_type.treetop +0 -68
  169. data/lib/mail/parsers/date_time.rb +0 -114
  170. data/lib/mail/parsers/date_time.treetop +0 -11
  171. data/lib/mail/parsers/envelope_from.rb +0 -194
  172. data/lib/mail/parsers/envelope_from.treetop +0 -32
  173. data/lib/mail/parsers/message_ids.rb +0 -45
  174. data/lib/mail/parsers/message_ids.treetop +0 -15
  175. data/lib/mail/parsers/mime_version.rb +0 -144
  176. data/lib/mail/parsers/mime_version.treetop +0 -19
  177. data/lib/mail/parsers/phrase_lists.rb +0 -45
  178. data/lib/mail/parsers/phrase_lists.treetop +0 -15
  179. data/lib/mail/parsers/received.rb +0 -71
  180. data/lib/mail/parsers/received.treetop +0 -11
  181. data/lib/mail/parsers/rfc2045.rb +0 -421
  182. data/lib/mail/parsers/rfc2045.treetop +0 -35
  183. data/lib/mail/parsers/rfc2822.rb +0 -5397
  184. data/lib/mail/parsers/rfc2822.treetop +0 -408
  185. data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
  186. data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
  187. data/lib/mail/patterns.rb +0 -35
  188. data/lib/mail/version_specific/ruby_1_8.rb +0 -119
  189. data/lib/mail/version_specific/ruby_1_9.rb +0 -147
  190. data/lib/tasks/corpus.rake +0 -125
  191. data/lib/tasks/treetop.rake +0 -10
@@ -1,42 +1,40 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/parsers/address_lists_parser'
4
+ require 'mail/constants'
5
+ require 'mail/utilities'
6
+
2
7
  module Mail
8
+ # Mail::Address handles all email addresses in Mail. It takes an email address string
9
+ # and parses it, breaking it down into its component parts and allowing you to get the
10
+ # address, comments, display name, name, local part, domain part and fully formatted
11
+ # address.
12
+ #
13
+ # Mail::Address requires a correctly formatted email address per RFC2822 or RFC822. It
14
+ # handles all obsolete versions including obsolete domain routing on the local part.
15
+ #
16
+ # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
17
+ # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
18
+ # a.address #=> 'mikel@test.lindsaar.net'
19
+ # a.display_name #=> 'Mikel Lindsaar'
20
+ # a.local #=> 'mikel'
21
+ # a.domain #=> 'test.lindsaar.net'
22
+ # a.comments #=> ['My email address']
23
+ # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
3
24
  class Address
4
-
5
- include Mail::Utilities
6
-
7
- # Mail::Address handles all email addresses in Mail. It takes an email address string
8
- # and parses it, breaking it down into its component parts and allowing you to get the
9
- # address, comments, display name, name, local part, domain part and fully formatted
10
- # address.
11
- #
12
- # Mail::Address requires a correctly formatted email address per RFC2822 or RFC822. It
13
- # handles all obsolete versions including obsolete domain routing on the local part.
14
- #
15
- # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
16
- # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
17
- # a.address #=> 'mikel@test.lindsaar.net'
18
- # a.display_name #=> 'Mikel Lindsaar'
19
- # a.local #=> 'mikel'
20
- # a.domain #=> 'test.lindsaar.net'
21
- # a.comments #=> ['My email address']
22
- # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
23
25
  def initialize(value = nil)
24
- @output_type = :decode
25
- @tree = nil
26
- @raw_text = value
27
- case
28
- when value.nil?
26
+ if value.nil?
29
27
  @parsed = false
30
- return
28
+ @data = nil
31
29
  else
32
30
  parse(value)
33
31
  end
34
32
  end
35
-
36
- # Returns the raw imput of the passed in string, this is before it is passed
33
+
34
+ # Returns the raw input of the passed in string, this is before it is passed
37
35
  # by the parser.
38
36
  def raw
39
- @raw_text
37
+ @data.raw
40
38
  end
41
39
 
42
40
  # Returns a correctly formatted address for the email going out. If given
@@ -46,112 +44,120 @@ module Mail
46
44
  #
47
45
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
48
46
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
49
- def format
47
+ def format(output_type = :decode)
50
48
  parse unless @parsed
51
- case
52
- when tree.nil?
53
- ''
54
- when display_name
55
- [quote_phrase(display_name), "<#{address}>", format_comments].compact.join(" ")
56
- when address
57
- [address, format_comments].compact.join(" ")
49
+ if @data.nil?
50
+ Constants::EMPTY
51
+ elsif name = display_name(output_type)
52
+ [Utilities.quote_phrase(name), "<#{address(output_type)}>", format_comments].compact.join(Constants::SPACE)
53
+ elsif a = address(output_type)
54
+ [a, format_comments].compact.join(Constants::SPACE)
58
55
  else
59
- tree.text_value
56
+ raw
60
57
  end
61
58
  end
62
59
 
63
- # Returns the address that is in the address itself. That is, the
60
+ # Returns the address that is in the address itself. That is, the
64
61
  # local@domain string, without any angle brackets or the like.
65
- #
62
+ #
66
63
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
67
64
  # a.address #=> 'mikel@test.lindsaar.net'
68
- def address
65
+ def address(output_type = :decode)
69
66
  parse unless @parsed
70
- domain ? "#{local}@#{domain}" : local
67
+ if d = domain(output_type)
68
+ "#{local(output_type)}@#{d}"
69
+ else
70
+ local(output_type)
71
+ end
71
72
  end
72
-
73
+
73
74
  # Provides a way to assign an address to an already made Mail::Address object.
74
- #
75
+ #
75
76
  # a = Address.new
76
77
  # a.address = 'Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>'
77
78
  # a.address #=> 'mikel@test.lindsaar.net'
78
79
  def address=(value)
79
80
  parse(value)
80
81
  end
81
-
82
+
82
83
  # Returns the display name of the email address passed in.
83
- #
84
+ #
84
85
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
85
86
  # a.display_name #=> 'Mikel Lindsaar'
86
- def display_name
87
+ def display_name(output_type = :decode)
87
88
  parse unless @parsed
88
89
  @display_name ||= get_display_name
89
- 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
90
91
  end
91
-
92
+
92
93
  # Provides a way to assign a display name to an already made Mail::Address object.
93
- #
94
+ #
94
95
  # a = Address.new
95
96
  # a.address = 'mikel@test.lindsaar.net'
96
97
  # a.display_name = 'Mikel Lindsaar'
97
98
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>'
98
99
  def display_name=( str )
99
- @display_name = str
100
+ @display_name = str.nil? ? nil : str.dup # in case frozen
100
101
  end
101
102
 
102
103
  # Returns the local part (the left hand side of the @ sign in the email address) of
103
104
  # the address
104
- #
105
+ #
105
106
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
106
107
  # a.local #=> 'mikel'
107
- def local
108
+ def local(output_type = :decode)
108
109
  parse unless @parsed
109
- "#{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
110
111
  end
111
112
 
112
113
  # Returns the domain part (the right hand side of the @ sign in the email address) of
113
114
  # the address
114
- #
115
+ #
115
116
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
116
117
  # a.domain #=> 'test.lindsaar.net'
117
- def domain
118
+ def domain(output_type = :decode)
118
119
  parse unless @parsed
119
- strip_all_comments(get_domain) if get_domain
120
+ Encodings.decode_encode(strip_all_comments(get_domain), output_type) if get_domain
120
121
  end
121
-
122
- # Returns an array of comments that are in the email, or an empty array if there
122
+
123
+ # Returns an array of comments that are in the email, or nil if there
123
124
  # are no comments
124
- #
125
+ #
125
126
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
126
127
  # a.comments #=> ['My email address']
128
+ #
129
+ # b = Address.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
130
+ # b.comments #=> nil
131
+
127
132
  def comments
128
133
  parse unless @parsed
129
- if get_comments.empty?
134
+ comments = get_comments
135
+ if comments.nil? || comments.none?
130
136
  nil
131
137
  else
132
- get_comments.map { |c| c.squeeze(" ") }
138
+ comments.map { |c| c.squeeze(Constants::SPACE) }
133
139
  end
134
140
  end
135
-
141
+
136
142
  # Sometimes an address will not have a display name, but might have the name
137
143
  # as a comment field after the address. This returns that name if it exists.
138
- #
144
+ #
139
145
  # a = Address.new('mikel@test.lindsaar.net (Mikel Lindsaar)')
140
146
  # a.name #=> 'Mikel Lindsaar'
141
147
  def name
142
148
  parse unless @parsed
143
149
  get_name
144
150
  end
145
-
151
+
146
152
  # Returns the format of the address, or returns nothing
147
- #
153
+ #
148
154
  # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
149
155
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
150
156
  def to_s
151
157
  parse unless @parsed
152
158
  format
153
159
  end
154
-
160
+
155
161
  # Shows the Address object basic details, including the Address
156
162
  # a = Address.new('Mikel (My email) <mikel@test.lindsaar.net>')
157
163
  # a.inspect #=> "#<Mail::Address:14184910 Address: |Mikel <mikel@test.lindsaar.net> (My email)| >"
@@ -159,156 +165,94 @@ module Mail
159
165
  parse unless @parsed
160
166
  "#<#{self.class}:#{self.object_id} Address: |#{to_s}| >"
161
167
  end
162
-
168
+
163
169
  def encoded
164
- @output_type = :encode
165
- format
170
+ format :encode
166
171
  end
167
-
172
+
168
173
  def decoded
169
- @output_type = :decode
170
- format
174
+ format :decode
175
+ end
176
+
177
+ def group
178
+ @data && @data.group
171
179
  end
172
180
 
173
181
  private
174
-
182
+
175
183
  def parse(value = nil)
176
184
  @parsed = true
177
- case
178
- when value.nil?
179
- nil
180
- when value.class == String
181
- self.tree = Mail::AddressList.new(value).address_nodes.first
182
- else
183
- self.tree = value
184
- end
185
- end
186
-
187
-
188
- def get_domain
189
- if tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:domain)
190
- @domain_text ||= tree.angle_addr.addr_spec.domain.text_value.strip
191
- elsif tree.respond_to?(:domain)
192
- @domain_text ||= tree.domain.text_value.strip
193
- elsif tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:domain)
194
- tree.addr_spec.domain.text_value.strip
195
- else
196
- nil
185
+ @data = nil
186
+
187
+ case value
188
+ when Mail::Parsers::AddressListsParser::AddressStruct
189
+ @data = value
190
+ when String
191
+ unless Utilities.blank?(value)
192
+ address_list = Mail::Parsers::AddressListsParser.parse(value)
193
+ @data = address_list.addresses.first
194
+ end
197
195
  end
198
196
  end
199
197
 
200
198
  def strip_all_comments(string)
201
- unless comments.blank?
199
+ unless Utilities.blank?(comments)
202
200
  comments.each do |comment|
203
- string = string.gsub("(#{comment})", '')
201
+ string = string.gsub("(#{comment})", Constants::EMPTY)
204
202
  end
205
203
  end
206
204
  string.strip
207
205
  end
208
206
 
209
207
  def strip_domain_comments(value)
210
- unless comments.blank?
208
+ unless Utilities.blank?(comments)
211
209
  comments.each do |comment|
212
- if get_domain && get_domain.include?("(#{comment})")
213
- value = value.gsub("(#{comment})", '')
210
+ if @data.domain && @data.domain.include?("(#{comment})")
211
+ value = value.gsub("(#{comment})", Constants::EMPTY)
214
212
  end
215
213
  end
216
214
  end
217
215
  value.to_s.strip
218
216
  end
219
-
220
- def get_comments
221
- if tree.respond_to?(:comments)
222
- @comments = tree.comments.map { |c| unparen(c.text_value.to_str) }
223
- else
224
- @comments = []
225
- end
226
- end
227
-
217
+
228
218
  def get_display_name
229
- if tree.respond_to?(:display_name)
230
- name = unquote(tree.display_name.text_value.strip)
231
- str = strip_all_comments(name.to_s)
232
- elsif comments
233
- if domain
234
- str = strip_domain_comments(format_comments)
235
- else
236
- str = nil
237
- end
238
- else
239
- nil
240
- end
241
-
242
- if str.blank?
243
- nil
244
- else
245
- str
219
+ if @data && @data.display_name
220
+ str = strip_all_comments(@data.display_name.to_s)
221
+ elsif @data && @data.comments && @data.domain
222
+ str = strip_domain_comments(format_comments)
246
223
  end
224
+ str unless Utilities.blank?(str)
247
225
  end
248
-
226
+
249
227
  def get_name
250
228
  if display_name
251
229
  str = display_name
252
- else
253
- if comments
254
- comment_text = comments.join(' ').squeeze(" ")
255
- str = "(#{comment_text})"
256
- end
230
+ elsif comments
231
+ str = "(#{comments.join(Constants::SPACE).squeeze(Constants::SPACE)})"
257
232
  end
258
233
 
259
- if str.blank?
260
- nil
261
- else
262
- unparen(str)
263
- end
264
- end
265
-
266
- # Provides access to the Treetop parse tree for this address
267
- def tree
268
- @tree
269
- end
270
-
271
- def tree=(value)
272
- @tree = value
234
+ Utilities.unparen(str) unless Utilities.blank?(str)
273
235
  end
274
-
236
+
275
237
  def format_comments
276
238
  if comments
277
- comment_text = comments.map {|c| escape_paren(c) }.join(' ').squeeze(" ")
239
+ comment_text = comments.map {|c| Utilities.escape_paren(c) }.join(Constants::SPACE).squeeze(Constants::SPACE)
278
240
  @format_comments ||= "(#{comment_text})"
279
241
  else
280
242
  nil
281
243
  end
282
244
  end
283
-
284
- def obs_domain_list
285
- if tree.respond_to?(:angle_addr)
286
- obs = tree.angle_addr.elements.select { |e| e.respond_to?(:obs_domain_list) }
287
- !obs.empty? ? obs.first.text_value : nil
288
- else
289
- nil
290
- end
291
- end
292
-
245
+
293
246
  def get_local
294
- case
295
- when tree.respond_to?(:local_dot_atom_text)
296
- tree.local_dot_atom_text.text_value
297
- when tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:local_part)
298
- tree.angle_addr.addr_spec.local_part.text_value
299
- when tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:local_part)
300
- tree.addr_spec.local_part.text_value
301
- when tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:local_dot_atom_text)
302
- # Ignore local dot atom text when in angle brackets
303
- nil
304
- when tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:local_dot_atom_text)
305
- # Ignore local dot atom text when in angle brackets
306
- nil
307
- else
308
- tree && tree.respond_to?(:local_part) ? tree.local_part.text_value : nil
309
- end
247
+ @data && @data.local
248
+ end
249
+
250
+ def get_domain
251
+ @data && @data.domain
252
+ end
253
+
254
+ def get_comments
255
+ @data && @data.comments
310
256
  end
311
-
312
-
313
257
  end
314
258
  end
@@ -1,74 +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
- class AddressList # :nodoc:
4
-
6
+ class AddressList #:nodoc:
7
+ attr_reader :addresses, :group_names
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
- if string.blank?
22
- @address_nodes = []
23
- return self
24
- end
25
- parser = Mail::AddressListsParser.new
26
- if tree = parser.parse(string)
27
- @address_nodes = tree.addresses
28
- else
29
- raise Mail::Field::ParseError.new(AddressListsParser, string, parser.failure_reason)
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
-
33
- # Returns a list of address objects from the parsed line
34
- def addresses
35
- @addresses ||= get_addresses.map do |address_tree|
36
- Mail::Address.new(address_tree)
37
- end
38
- end
39
-
40
- # Returns a list of all recipient syntax trees that are not part of a group
41
- def individual_recipients # :nodoc:
42
- @individual_recipients ||= @address_nodes - group_recipients
43
- end
44
-
45
- # Returns a list of all recipient syntax trees that are part of a group
46
- def group_recipients # :nodoc:
47
- @group_recipients ||= @address_nodes.select { |an| an.respond_to?(:group_name) }
48
- end
49
-
50
- # Returns the names as an array of strings of all groups
51
- def group_names # :nodoc:
52
- group_recipients.map { |g| g.group_name.text_value }
53
- end
54
-
55
- # Returns a list of address syntax trees
56
- def address_nodes # :nodoc:
57
- @address_nodes
58
- end
59
-
60
- private
61
-
62
- def get_addresses
63
- (individual_recipients + group_recipients.map { |g| get_group_addresses(g) }).flatten
64
- end
65
-
66
- def get_group_addresses(g)
67
- if g.group_list.respond_to?(:addresses)
68
- g.group_list.addresses
69
- else
70
- []
71
- end
29
+
30
+ def addresses_grouped_by_group
31
+ addresses.select(&:group).group_by(&:group)
72
32
  end
73
33
  end
74
34
  end
@@ -1,30 +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
- class ContentDispositionElement # :nodoc:
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- parser = Mail::ContentDispositionParser.new
9
- if tree = parser.parse(cleaned(string))
10
- @disposition_type = tree.disposition_type.text_value.downcase
11
- @parameters = tree.parameters
12
- else
13
- raise Mail::Field::ParseError.new(ContentDispositionElement, string, parser.failure_reason)
14
- end
6
+ class ContentDispositionElement #:nodoc:
7
+ attr_reader :disposition_type, :parameters
8
+
9
+ def initialize(string)
10
+ content_disposition = Mail::Parsers::ContentDispositionParser.parse(cleaned(string))
11
+ @disposition_type = content_disposition.disposition_type
12
+ @parameters = content_disposition.parameters
15
13
  end
16
-
17
- def disposition_type
18
- @disposition_type
19
- end
20
-
21
- def parameters
22
- @parameters
23
- end
24
-
14
+
15
+ private
25
16
  def cleaned(string)
26
17
  string =~ /(.+);\s*$/ ? $1 : string
27
18
  end
28
-
29
19
  end
30
20
  end
@@ -1,25 +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
- class ContentLocationElement # :nodoc:
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- parser = Mail::ContentLocationParser.new
9
- if tree = parser.parse(string)
10
- @location = tree.location.text_value
11
- else
12
- raise Mail::Field::ParseError.new(ContentLocationElement, string, parser.failure_reason)
13
- end
6
+ class ContentLocationElement #:nodoc:
7
+ attr_reader :location
8
+
9
+ def initialize(string)
10
+ @location = Mail::Parsers::ContentLocationParser.parse(string).location
14
11
  end
15
-
16
- def location
17
- @location
18
- end
19
-
12
+
20
13
  def to_s(*args)
21
14
  location.to_s
22
15
  end
23
-
24
16
  end
25
17
  end
@@ -1,24 +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
- class ContentTransferEncodingElement
4
-
5
- include Mail::Utilities
6
-
7
- def initialize( string )
8
- parser = Mail::ContentTransferEncodingParser.new
9
- case
10
- when string.blank?
11
- @encoding = ''
12
- when tree = parser.parse(string.to_s.downcase)
13
- @encoding = tree.encoding.text_value
14
- else
15
- raise Mail::Field::ParseError.new(ContentTransferEncodingElement, string, parser.failure_reason)
16
- end
6
+ class ContentTransferEncodingElement #:nodoc:
7
+ attr_reader :encoding
8
+
9
+ def initialize(string)
10
+ @encoding = Mail::Parsers::ContentTransferEncodingParser.parse(string).encoding
17
11
  end
18
-
19
- def encoding
20
- @encoding
21
- end
22
-
23
12
  end
24
13
  end