mail 2.7.0.rc1 → 2.7.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +71 -98
  3. data/lib/mail.rb +1 -6
  4. data/lib/mail/attachments_list.rb +5 -2
  5. data/lib/mail/body.rb +39 -33
  6. data/lib/mail/check_delivery_params.rb +8 -6
  7. data/lib/mail/configuration.rb +2 -0
  8. data/lib/mail/elements/address.rb +19 -18
  9. data/lib/mail/encodings.rb +89 -31
  10. data/lib/mail/encodings/7bit.rb +5 -15
  11. data/lib/mail/encodings/8bit.rb +2 -21
  12. data/lib/mail/encodings/base64.rb +11 -12
  13. data/lib/mail/encodings/binary.rb +3 -22
  14. data/lib/mail/encodings/identity.rb +24 -0
  15. data/lib/mail/encodings/quoted_printable.rb +6 -6
  16. data/lib/mail/encodings/transfer_encoding.rb +38 -29
  17. data/lib/mail/encodings/unix_to_unix.rb +2 -1
  18. data/lib/mail/envelope.rb +1 -1
  19. data/lib/mail/field.rb +93 -61
  20. data/lib/mail/fields/bcc_field.rb +2 -2
  21. data/lib/mail/fields/cc_field.rb +1 -1
  22. data/lib/mail/fields/comments_field.rb +1 -1
  23. data/lib/mail/fields/common/common_address.rb +32 -7
  24. data/lib/mail/fields/common/common_field.rb +1 -10
  25. data/lib/mail/fields/content_description_field.rb +1 -1
  26. data/lib/mail/fields/content_disposition_field.rb +3 -3
  27. data/lib/mail/fields/content_id_field.rb +2 -2
  28. data/lib/mail/fields/content_location_field.rb +1 -1
  29. data/lib/mail/fields/content_transfer_encoding_field.rb +1 -1
  30. data/lib/mail/fields/content_type_field.rb +1 -1
  31. data/lib/mail/fields/date_field.rb +2 -3
  32. data/lib/mail/fields/from_field.rb +1 -1
  33. data/lib/mail/fields/in_reply_to_field.rb +1 -1
  34. data/lib/mail/fields/keywords_field.rb +1 -1
  35. data/lib/mail/fields/message_id_field.rb +1 -1
  36. data/lib/mail/fields/mime_version_field.rb +1 -1
  37. data/lib/mail/fields/optional_field.rb +4 -1
  38. data/lib/mail/fields/received_field.rb +1 -1
  39. data/lib/mail/fields/references_field.rb +1 -1
  40. data/lib/mail/fields/reply_to_field.rb +1 -1
  41. data/lib/mail/fields/resent_bcc_field.rb +1 -1
  42. data/lib/mail/fields/resent_cc_field.rb +1 -1
  43. data/lib/mail/fields/resent_date_field.rb +0 -1
  44. data/lib/mail/fields/resent_from_field.rb +1 -1
  45. data/lib/mail/fields/resent_message_id_field.rb +1 -1
  46. data/lib/mail/fields/resent_sender_field.rb +1 -1
  47. data/lib/mail/fields/resent_to_field.rb +1 -1
  48. data/lib/mail/fields/return_path_field.rb +1 -1
  49. data/lib/mail/fields/sender_field.rb +1 -1
  50. data/lib/mail/fields/subject_field.rb +1 -1
  51. data/lib/mail/fields/to_field.rb +1 -1
  52. data/lib/mail/fields/unstructured_field.rb +19 -2
  53. data/lib/mail/header.rb +9 -8
  54. data/lib/mail/mail.rb +2 -10
  55. data/lib/mail/matchers/has_sent_mail.rb +21 -1
  56. data/lib/mail/message.rb +64 -51
  57. data/lib/mail/multibyte.rb +14 -16
  58. data/lib/mail/multibyte/chars.rb +2 -1
  59. data/lib/mail/network.rb +1 -0
  60. data/lib/mail/network/delivery_methods/exim.rb +6 -10
  61. data/lib/mail/network/delivery_methods/logger_delivery.rb +37 -0
  62. data/lib/mail/network/delivery_methods/sendmail.rb +8 -4
  63. data/lib/mail/network/delivery_methods/smtp.rb +56 -55
  64. data/lib/mail/network/delivery_methods/smtp_connection.rb +9 -1
  65. data/lib/mail/network/retriever_methods/imap.rb +18 -5
  66. data/lib/mail/network/retriever_methods/pop3.rb +3 -1
  67. data/lib/mail/parser_tools.rb +15 -0
  68. data/lib/mail/parsers/address_lists_parser.rb +30462 -12597
  69. data/lib/mail/parsers/address_lists_parser.rl +18 -12
  70. data/lib/mail/parsers/content_disposition_parser.rb +405 -215
  71. data/lib/mail/parsers/content_disposition_parser.rl +11 -5
  72. data/lib/mail/parsers/content_location_parser.rb +443 -208
  73. data/lib/mail/parsers/content_location_parser.rl +9 -3
  74. data/lib/mail/parsers/content_transfer_encoding_parser.rb +180 -80
  75. data/lib/mail/parsers/content_transfer_encoding_parser.rl +8 -2
  76. data/lib/mail/parsers/content_type_parser.rb +436 -245
  77. data/lib/mail/parsers/content_type_parser.rl +12 -6
  78. data/lib/mail/parsers/date_time_parser.rb +172 -72
  79. data/lib/mail/parsers/date_time_parser.rl +10 -4
  80. data/lib/mail/parsers/envelope_from_parser.rb +2833 -1320
  81. data/lib/mail/parsers/envelope_from_parser.rl +9 -3
  82. data/lib/mail/parsers/message_ids_parser.rb +2325 -976
  83. data/lib/mail/parsers/message_ids_parser.rl +9 -3
  84. data/lib/mail/parsers/mime_version_parser.rb +164 -64
  85. data/lib/mail/parsers/mime_version_parser.rl +9 -3
  86. data/lib/mail/parsers/phrase_lists_parser.rb +582 -237
  87. data/lib/mail/parsers/phrase_lists_parser.rl +9 -3
  88. data/lib/mail/parsers/received_parser.rb +7036 -3004
  89. data/lib/mail/parsers/received_parser.rl +11 -5
  90. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +1 -0
  91. data/lib/mail/parsers/rfc2045_content_type.rl +1 -0
  92. data/lib/mail/parsers/rfc2045_mime.rl +1 -0
  93. data/lib/mail/parsers/rfc2183_content_disposition.rl +1 -0
  94. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  95. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +7 -1
  96. data/lib/mail/parsers/rfc5322.rl +3 -1
  97. data/lib/mail/parsers/rfc5322_address.rl +3 -1
  98. data/lib/mail/parsers/rfc5322_date_time.rl +1 -0
  99. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +9 -5
  100. data/lib/mail/part.rb +1 -1
  101. data/lib/mail/utilities.rb +44 -15
  102. data/lib/mail/version.rb +1 -1
  103. data/lib/mail/version_specific/ruby_1_8.rb +12 -1
  104. data/lib/mail/version_specific/ruby_1_9.rb +13 -1
  105. metadata +7 -13
  106. data/CHANGELOG.rdoc +0 -822
  107. data/CONTRIBUTING.md +0 -60
  108. data/Dependencies.txt +0 -1
  109. data/Gemfile +0 -11
  110. data/Rakefile +0 -23
  111. data/TODO.rdoc +0 -9
  112. data/lib/mail/multibyte/exceptions.rb +0 -9
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/encodings/transfer_encoding'
4
+
5
+ module Mail
6
+ module Encodings
7
+ # Identity encodings do no encoding/decoding and have a fixed cost:
8
+ # 1 byte in -> 1 byte out.
9
+ class Identity < TransferEncoding #:nodoc:
10
+ def self.decode(str)
11
+ str
12
+ end
13
+
14
+ def self.encode(str)
15
+ str
16
+ end
17
+
18
+ # 1 output byte per input byte.
19
+ def self.cost(str)
20
+ 1.0
21
+ end
22
+ end
23
+ end
24
+ end
@@ -6,27 +6,27 @@ module Mail
6
6
  module Encodings
7
7
  class QuotedPrintable < SevenBit
8
8
  NAME='quoted-printable'
9
-
9
+
10
10
  PRIORITY = 2
11
11
 
12
- def self.can_encode?(str)
13
- EightBit.can_encode? str
12
+ def self.can_encode?(enc)
13
+ EightBit.can_encode? enc
14
14
  end
15
15
 
16
16
  # Decode the string from Quoted-Printable. Cope with hard line breaks
17
17
  # that were incorrectly encoded as hex instead of literal CRLF.
18
18
  def self.decode(str)
19
- ::Mail::Utilities.to_lf str.gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack("M*").first
19
+ str.gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack("M*").first
20
20
  end
21
21
 
22
22
  def self.encode(str)
23
- ::Mail::Utilities.to_crlf([::Mail::Utilities.to_lf(str)].pack("M"))
23
+ [str].pack("M")
24
24
  end
25
25
 
26
26
  def self.cost(str)
27
27
  # These bytes probably do not need encoding
28
28
  c = str.count("\x9\xA\xD\x20-\x3C\x3E-\x7E")
29
- # Everything else turns into =XX where XX is a
29
+ # Everything else turns into =XX where XX is a
30
30
  # two digit hex number (taking 3 bytes)
31
31
  total = (str.bytesize - c)*3 + c
32
32
  total.to_f/str.bytesize
@@ -7,17 +7,17 @@ module Mail
7
7
 
8
8
  PRIORITY = -1
9
9
 
10
+ # And encoding's superclass can always transport it since the
11
+ # class hierarchy is arranged e.g. Base64 < 7bit < 8bit < Binary.
10
12
  def self.can_transport?(enc)
11
- enc = Encodings.get_name(enc)
12
- if Encodings.defined? enc
13
- Encodings.get_encoding(enc).new.is_a? self
14
- else
15
- false
16
- end
13
+ enc && enc <= self
17
14
  end
18
15
 
16
+ # Override in subclasses to indicate that they can encode text
17
+ # that couldn't be directly transported, e.g. Base64 has 7bit output,
18
+ # but it can encode binary.
19
19
  def self.can_encode?(enc)
20
- can_transport? enc
20
+ can_transport? enc
21
21
  end
22
22
 
23
23
  def self.cost(str)
@@ -32,36 +32,45 @@ module Mail
32
32
  self::NAME
33
33
  end
34
34
 
35
- def self.get_best_compatible(source_encoding, str)
36
- if self.can_transport?(source_encoding) && self.compatible_input?(str)
35
+ def self.negotiate(message_encoding, source_encoding, str, allowed_encodings = nil)
36
+ message_encoding = Encodings.get_encoding(message_encoding || '8bit')
37
+ source_encoding = Encodings.get_encoding(source_encoding)
38
+
39
+ if message_encoding && source_encoding && message_encoding.can_transport?(source_encoding) && source_encoding.compatible_input?(str)
37
40
  source_encoding
38
41
  else
39
- choices = Encodings.get_all.select do |enc|
40
- self.can_transport?(enc) && enc.can_encode?(source_encoding)
41
- end
42
+ renegotiate(message_encoding, source_encoding, str, allowed_encodings)
43
+ end
44
+ end
42
45
 
43
- best = nil
44
- best_cost = nil
46
+ def self.renegotiate(message_encoding, source_encoding, str, allowed_encodings = nil)
47
+ encodings = Encodings.get_all.select do |enc|
48
+ (allowed_encodings.nil? || allowed_encodings.include?(enc)) &&
49
+ message_encoding.can_transport?(enc) &&
50
+ enc.can_encode?(source_encoding)
51
+ end
45
52
 
46
- choices.each do |enc|
47
- # If the current choice cannot be transported safely,
48
- # give priority to other choices but allow it to be used as a fallback.
49
- this_cost = enc.cost(str) if enc.compatible_input?(str)
53
+ lowest_cost(str, encodings)
54
+ end
50
55
 
51
- if !best_cost || (this_cost && this_cost < best_cost)
52
- best_cost = this_cost
53
- best = enc
54
- elsif this_cost == best_cost
55
- best = enc if enc::PRIORITY < best::PRIORITY
56
- end
57
- end
56
+ def self.lowest_cost(str, encodings)
57
+ best = nil
58
+ best_cost = nil
58
59
 
59
- best
60
+ encodings.each do |enc|
61
+ # If the current choice cannot be transported safely, give priority
62
+ # to other choices but allow it to be used as a fallback.
63
+ this_cost = enc.cost(str) if enc.compatible_input?(str)
64
+
65
+ if !best_cost || (this_cost && this_cost < best_cost)
66
+ best_cost = this_cost
67
+ best = enc
68
+ elsif this_cost == best_cost
69
+ best = enc if enc::PRIORITY < best::PRIORITY
70
+ end
60
71
  end
61
- end
62
72
 
63
- def to_s
64
- self.class.to_s
73
+ best
65
74
  end
66
75
  end
67
76
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Mail
3
3
  module Encodings
4
- module UnixToUnix
4
+ class UnixToUnix < TransferEncoding
5
5
  NAME = "x-uuencode"
6
6
 
7
7
  def self.decode(str)
@@ -13,6 +13,7 @@ module Mail
13
13
  end
14
14
 
15
15
  Encodings.register(NAME, self)
16
+ Encodings.register("uuencode", self)
16
17
  end
17
18
  end
18
19
  end
@@ -12,7 +12,7 @@ module Mail
12
12
  class Envelope < StructuredField
13
13
 
14
14
  def initialize(*args)
15
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
15
+ super(FIELD_NAME, args.last.to_s)
16
16
  end
17
17
 
18
18
  def element
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'mail/fields'
3
+ require 'mail/constants'
3
4
 
4
5
  # encoding: utf-8
5
6
  module Mail
@@ -83,9 +84,31 @@ module Mail
83
84
 
84
85
  def initialize(element, value, reason)
85
86
  @element = element
86
- @value = value
87
- @reason = reason
88
- super("#{element} can not parse |#{value}|\nReason was: #{reason}")
87
+ @value = to_utf8(value)
88
+ @reason = to_utf8(reason)
89
+ super("#{@element} can not parse |#{@value}|: #{@reason}")
90
+ end
91
+
92
+ private
93
+ def to_utf8(text)
94
+ if text.respond_to?(:force_encoding)
95
+ text.dup.force_encoding(Encoding::UTF_8)
96
+ else
97
+ text
98
+ end
99
+ end
100
+ end
101
+
102
+ class NilParseError < ParseError #:nodoc:
103
+ def initialize(element)
104
+ super element, nil, 'nil is invalid'
105
+ end
106
+ end
107
+
108
+ class IncompleteParseError < ParseError #:nodoc:
109
+ def initialize(element, original_text, unparsed_index)
110
+ parsed_text = to_utf8(original_text[0...unparsed_index])
111
+ super element, original_text, "Only able to parse up to #{parsed_text.inspect}"
89
112
  end
90
113
  end
91
114
 
@@ -93,41 +116,62 @@ module Mail
93
116
  class SyntaxError < FieldError #:nodoc:
94
117
  end
95
118
 
96
- # Accepts a string:
97
- #
98
- # Field.new("field-name: field data")
99
- #
100
- # Or name, value pair:
101
- #
102
- # Field.new("field-name", "value")
119
+ class << self
120
+ # Parse a field from a raw header line:
121
+ #
122
+ # Mail::Field.parse("field-name: field data")
123
+ # # => #<Mail::Field …>
124
+ def parse(field, charset = nil)
125
+ name, value = split(field)
126
+ if name && value
127
+ new name, value, charset
128
+ end
129
+ end
130
+
131
+ def split(raw_field) #:nodoc:
132
+ if raw_field.index(Constants::COLON)
133
+ name, value = raw_field.split(Constants::COLON, 2)
134
+ name.rstrip!
135
+ if name =~ /\A#{Constants::FIELD_NAME}\z/
136
+ [ name.rstrip, value.strip ]
137
+ else
138
+ Kernel.warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: invalid header name syntax: #{name.inspect}"
139
+ nil
140
+ end
141
+ else
142
+ raw_field.strip
143
+ end
144
+ rescue => error
145
+ warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: #{error.class}: #{error.message}"
146
+ nil
147
+ end
148
+ end
149
+
150
+ # Create a field by name and optional value:
103
151
  #
104
- # Or a name by itself:
152
+ # Mail::Field.new("field-name", "value")
153
+ # # => #<Mail::Field …>
105
154
  #
106
- # Field.new("field-name")
155
+ # Values that aren't strings or arrays are coerced to Strings with `#to_s`.
107
156
  #
108
- # Note, does not want a terminating carriage return. Returns
109
- # self appropriately parsed. If value is not a string, then
110
- # it will be passed through as is, for example, content-type
111
- # field can accept an array with the type and a hash of
112
- # parameters:
157
+ # Mail::Field.new("field-name", 1234)
158
+ # # => #<Mail::Field …>
113
159
  #
114
- # Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
160
+ # Mail::Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
161
+ # # => #<Mail::Field …>
115
162
  def initialize(name, value = nil, charset = 'utf-8')
116
163
  case
117
- when name.index(COLON) # Field.new("field-name: field data")
164
+ when name.index(COLON)
165
+ Kernel.warn 'Passing an unparsed header field to Mail::Field.new is deprecated and will be removed in Mail 2.8.0. Use Mail::Field.parse instead.'
166
+ @name, @unparsed_value = self.class.split(name)
118
167
  @charset = Utilities.blank?(value) ? charset : value
119
- @name = name[FIELD_PREFIX]
120
- @raw_value = name
121
- @value = nil
122
- when Utilities.blank?(value) # Field.new("field-name")
168
+ when Utilities.blank?(value)
123
169
  @name = name
124
- @value = nil
125
- @raw_value = nil
170
+ @unparsed_value = nil
126
171
  @charset = charset
127
- else # Field.new("field-name", "value")
172
+ else
128
173
  @name = name
129
- @value = value
130
- @raw_value = nil
174
+ @unparsed_value = value
131
175
  @charset = charset
132
176
  end
133
177
  @name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
@@ -138,8 +182,7 @@ module Mail
138
182
  end
139
183
 
140
184
  def field
141
- _, @value = split(@raw_value) if @raw_value && !@value
142
- @field ||= create_field(@name, @value, @charset)
185
+ @field ||= create_field(@name, @unparsed_value, @charset)
143
186
  end
144
187
 
145
188
  def name
@@ -217,14 +260,26 @@ module Mail
217
260
 
218
261
  private
219
262
 
220
- def split(raw_field)
221
- match_data = Mail::Multibyte.mb_chars(raw_field).match(FIELD_SPLIT)
222
- [
223
- Mail::Multibyte.mb_chars(match_data[1].to_s).strip,
224
- Mail::Multibyte.mb_chars(match_data[2].to_s).strip.to_s
225
- ]
226
- rescue
227
- $stderr.puts "WARNING: Could not parse (and so ignoring) '#{raw_field}'"
263
+ def create_field(name, value, charset)
264
+ new_field(name, value, charset)
265
+ rescue Mail::Field::ParseError => e
266
+ field = Mail::UnstructuredField.new(name, value)
267
+ field.errors << [name, value, e]
268
+ field
269
+ end
270
+
271
+ def new_field(name, value, charset)
272
+ value = unfold(value) if value.is_a?(String)
273
+
274
+ if klass = field_class_for(name)
275
+ klass.new(value, charset)
276
+ else
277
+ OptionalField.new(name, value, charset)
278
+ end
279
+ end
280
+
281
+ def field_class_for(name)
282
+ FIELDS_MAP[name.to_s.downcase]
228
283
  end
229
284
 
230
285
  # 2.2.3. Long Header Fields
@@ -238,28 +293,5 @@ module Mail
238
293
  def unfold(string)
239
294
  string.gsub(/#{CRLF}(#{WSP})/m, '\1')
240
295
  end
241
-
242
- def create_field(name, value, charset)
243
- value = unfold(value) if value.is_a?(String)
244
-
245
- begin
246
- new_field(name, value, charset)
247
- rescue Mail::Field::ParseError => e
248
- field = Mail::UnstructuredField.new(name, value)
249
- field.errors << [name, value, e]
250
- field
251
- end
252
- end
253
-
254
- def new_field(name, value, charset)
255
- lower_case_name = name.to_s.downcase
256
- if field_klass = FIELDS_MAP[lower_case_name]
257
- field_klass.new(value, charset)
258
- else
259
- OptionalField.new(name, value, charset)
260
- end
261
- end
262
-
263
296
  end
264
-
265
297
  end
@@ -37,9 +37,9 @@ module Mail
37
37
  FIELD_NAME = 'bcc'
38
38
  CAPITALIZED_FIELD = 'Bcc'
39
39
 
40
- def initialize(value = '', charset = 'utf-8')
40
+ def initialize(value = nil, charset = 'utf-8')
41
41
  @charset = charset
42
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -39,7 +39,7 @@ module Mail
39
39
 
40
40
  def initialize(value = nil, charset = 'utf-8')
41
41
  self.charset = charset
42
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -33,7 +33,7 @@ module Mail
33
33
 
34
34
  def initialize(value = nil, charset = 'utf-8')
35
35
  @charset = charset
36
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value))
36
+ super(CAPITALIZED_FIELD, value)
37
37
  self.parse
38
38
  self
39
39
  end
@@ -4,7 +4,6 @@ require 'mail/fields/common/address_container'
4
4
 
5
5
  module Mail
6
6
  module CommonAddress # :nodoc:
7
-
8
7
  def parse(val = value)
9
8
  unless Utilities.blank?(val)
10
9
  @address_list = AddressList.new(encode_if_needed(val))
@@ -12,15 +11,22 @@ module Mail
12
11
  nil
13
12
  end
14
13
  end
15
-
14
+
16
15
  def charset
17
16
  @charset
18
17
  end
19
-
20
- def encode_if_needed(val)
21
- Encodings.address_encode(val, charset)
18
+
19
+ def encode_if_needed(val) #:nodoc:
20
+ # Need to join arrays of addresses into a single value
21
+ if val.kind_of?(Array)
22
+ val.compact.map { |a| encode_if_needed a }.join(', ')
23
+
24
+ # Pass through UTF-8; encode non-UTF-8.
25
+ else
26
+ utf8_if_needed(val) || Encodings.encode_non_usascii(val, charset)
27
+ end
22
28
  end
23
-
29
+
24
30
  # Allows you to iterate through each address object in the address_list
25
31
  def each
26
32
  address_list.addresses.each do |address|
@@ -98,7 +104,26 @@ module Mail
98
104
  end
99
105
 
100
106
  private
101
-
107
+
108
+ if 'string'.respond_to?(:encoding)
109
+ # Pass through UTF-8 addresses
110
+ def utf8_if_needed(val)
111
+ if charset =~ /\AUTF-?8\z/i
112
+ val
113
+ elsif val.encoding == Encoding::UTF_8
114
+ val
115
+ elsif (utf8 = val.dup.force_encoding(Encoding::UTF_8)).valid_encoding?
116
+ utf8
117
+ end
118
+ end
119
+ else
120
+ def utf8_if_needed(val)
121
+ if charset =~ /\AUTF-?8\z/i
122
+ val
123
+ end
124
+ end
125
+ end
126
+
102
127
  def do_encode(field_name)
103
128
  return '' if Utilities.blank?(value)
104
129
  address_array = address_list.addresses.reject { |a| encoded_group_addresses.include?(a.encoded) }.compact.map { |a| a.encoded }