nano-fast-tool 0.0.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 (138) hide show
  1. checksums.yaml +7 -0
  2. data/mail-2.9.1/MIT-LICENSE +20 -0
  3. data/mail-2.9.1/README.md +771 -0
  4. data/mail-2.9.1/lib/mail/attachments_list.rb +109 -0
  5. data/mail-2.9.1/lib/mail/body.rb +305 -0
  6. data/mail-2.9.1/lib/mail/configuration.rb +78 -0
  7. data/mail-2.9.1/lib/mail/constants.rb +79 -0
  8. data/mail-2.9.1/lib/mail/elements/address.rb +258 -0
  9. data/mail-2.9.1/lib/mail/elements/address_list.rb +34 -0
  10. data/mail-2.9.1/lib/mail/elements/content_disposition_element.rb +20 -0
  11. data/mail-2.9.1/lib/mail/elements/content_location_element.rb +17 -0
  12. data/mail-2.9.1/lib/mail/elements/content_transfer_encoding_element.rb +13 -0
  13. data/mail-2.9.1/lib/mail/elements/content_type_element.rb +25 -0
  14. data/mail-2.9.1/lib/mail/elements/date_time_element.rb +15 -0
  15. data/mail-2.9.1/lib/mail/elements/envelope_from_element.rb +39 -0
  16. data/mail-2.9.1/lib/mail/elements/message_ids_element.rb +31 -0
  17. data/mail-2.9.1/lib/mail/elements/mime_version_element.rb +15 -0
  18. data/mail-2.9.1/lib/mail/elements/phrase_list.rb +19 -0
  19. data/mail-2.9.1/lib/mail/elements/received_element.rb +35 -0
  20. data/mail-2.9.1/lib/mail/elements.rb +15 -0
  21. data/mail-2.9.1/lib/mail/encodings/7bit.rb +27 -0
  22. data/mail-2.9.1/lib/mail/encodings/8bit.rb +18 -0
  23. data/mail-2.9.1/lib/mail/encodings/base64.rb +38 -0
  24. data/mail-2.9.1/lib/mail/encodings/binary.rb +13 -0
  25. data/mail-2.9.1/lib/mail/encodings/identity.rb +24 -0
  26. data/mail-2.9.1/lib/mail/encodings/quoted_printable.rb +45 -0
  27. data/mail-2.9.1/lib/mail/encodings/transfer_encoding.rb +77 -0
  28. data/mail-2.9.1/lib/mail/encodings/unix_to_unix.rb +20 -0
  29. data/mail-2.9.1/lib/mail/encodings.rb +314 -0
  30. data/mail-2.9.1/lib/mail/envelope.rb +28 -0
  31. data/mail-2.9.1/lib/mail/field.rb +313 -0
  32. data/mail-2.9.1/lib/mail/field_list.rb +87 -0
  33. data/mail-2.9.1/lib/mail/fields/bcc_field.rb +49 -0
  34. data/mail-2.9.1/lib/mail/fields/cc_field.rb +33 -0
  35. data/mail-2.9.1/lib/mail/fields/comments_field.rb +31 -0
  36. data/mail-2.9.1/lib/mail/fields/common_address_field.rb +162 -0
  37. data/mail-2.9.1/lib/mail/fields/common_date_field.rb +56 -0
  38. data/mail-2.9.1/lib/mail/fields/common_field.rb +77 -0
  39. data/mail-2.9.1/lib/mail/fields/common_message_id_field.rb +41 -0
  40. data/mail-2.9.1/lib/mail/fields/content_description_field.rb +12 -0
  41. data/mail-2.9.1/lib/mail/fields/content_disposition_field.rb +44 -0
  42. data/mail-2.9.1/lib/mail/fields/content_id_field.rb +35 -0
  43. data/mail-2.9.1/lib/mail/fields/content_location_field.rb +28 -0
  44. data/mail-2.9.1/lib/mail/fields/content_transfer_encoding_field.rb +44 -0
  45. data/mail-2.9.1/lib/mail/fields/content_type_field.rb +171 -0
  46. data/mail-2.9.1/lib/mail/fields/date_field.rb +28 -0
  47. data/mail-2.9.1/lib/mail/fields/from_field.rb +33 -0
  48. data/mail-2.9.1/lib/mail/fields/in_reply_to_field.rb +45 -0
  49. data/mail-2.9.1/lib/mail/fields/keywords_field.rb +30 -0
  50. data/mail-2.9.1/lib/mail/fields/message_id_field.rb +36 -0
  51. data/mail-2.9.1/lib/mail/fields/mime_version_field.rb +42 -0
  52. data/mail-2.9.1/lib/mail/fields/named_structured_field.rb +10 -0
  53. data/mail-2.9.1/lib/mail/fields/named_unstructured_field.rb +10 -0
  54. data/mail-2.9.1/lib/mail/fields/optional_field.rb +15 -0
  55. data/mail-2.9.1/lib/mail/fields/parameter_hash.rb +61 -0
  56. data/mail-2.9.1/lib/mail/fields/received_field.rb +61 -0
  57. data/mail-2.9.1/lib/mail/fields/references_field.rb +42 -0
  58. data/mail-2.9.1/lib/mail/fields/reply_to_field.rb +33 -0
  59. data/mail-2.9.1/lib/mail/fields/resent_bcc_field.rb +33 -0
  60. data/mail-2.9.1/lib/mail/fields/resent_cc_field.rb +33 -0
  61. data/mail-2.9.1/lib/mail/fields/resent_date_field.rb +10 -0
  62. data/mail-2.9.1/lib/mail/fields/resent_from_field.rb +33 -0
  63. data/mail-2.9.1/lib/mail/fields/resent_message_id_field.rb +10 -0
  64. data/mail-2.9.1/lib/mail/fields/resent_sender_field.rb +32 -0
  65. data/mail-2.9.1/lib/mail/fields/resent_to_field.rb +33 -0
  66. data/mail-2.9.1/lib/mail/fields/return_path_field.rb +60 -0
  67. data/mail-2.9.1/lib/mail/fields/sender_field.rb +45 -0
  68. data/mail-2.9.1/lib/mail/fields/structured_field.rb +24 -0
  69. data/mail-2.9.1/lib/mail/fields/subject_field.rb +14 -0
  70. data/mail-2.9.1/lib/mail/fields/to_field.rb +33 -0
  71. data/mail-2.9.1/lib/mail/fields/unstructured_field.rb +189 -0
  72. data/mail-2.9.1/lib/mail/fields.rb +45 -0
  73. data/mail-2.9.1/lib/mail/header.rb +237 -0
  74. data/mail-2.9.1/lib/mail/indifferent_hash.rb +147 -0
  75. data/mail-2.9.1/lib/mail/mail.rb +267 -0
  76. data/mail-2.9.1/lib/mail/matchers/attachment_matchers.rb +44 -0
  77. data/mail-2.9.1/lib/mail/matchers/has_sent_mail.rb +201 -0
  78. data/mail-2.9.1/lib/mail/message.rb +2159 -0
  79. data/mail-2.9.1/lib/mail/multibyte/chars.rb +318 -0
  80. data/mail-2.9.1/lib/mail/multibyte/unicode.rb +405 -0
  81. data/mail-2.9.1/lib/mail/multibyte/utils.rb +44 -0
  82. data/mail-2.9.1/lib/mail/multibyte.rb +82 -0
  83. data/mail-2.9.1/lib/mail/network/delivery_methods/exim.rb +50 -0
  84. data/mail-2.9.1/lib/mail/network/delivery_methods/file_delivery.rb +43 -0
  85. data/mail-2.9.1/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  86. data/mail-2.9.1/lib/mail/network/delivery_methods/sendmail.rb +87 -0
  87. data/mail-2.9.1/lib/mail/network/delivery_methods/smtp.rb +200 -0
  88. data/mail-2.9.1/lib/mail/network/delivery_methods/smtp_connection.rb +57 -0
  89. data/mail-2.9.1/lib/mail/network/delivery_methods/test_mailer.rb +44 -0
  90. data/mail-2.9.1/lib/mail/network/retriever_methods/base.rb +64 -0
  91. data/mail-2.9.1/lib/mail/network/retriever_methods/imap.rb +190 -0
  92. data/mail-2.9.1/lib/mail/network/retriever_methods/pop3.rb +143 -0
  93. data/mail-2.9.1/lib/mail/network/retriever_methods/test_retriever.rb +45 -0
  94. data/mail-2.9.1/lib/mail/network.rb +16 -0
  95. data/mail-2.9.1/lib/mail/parser_tools.rb +15 -0
  96. data/mail-2.9.1/lib/mail/parsers/address_lists_parser.rb +33245 -0
  97. data/mail-2.9.1/lib/mail/parsers/address_lists_parser.rl +183 -0
  98. data/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rb +904 -0
  99. data/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rl +93 -0
  100. data/mail-2.9.1/lib/mail/parsers/content_location_parser.rb +825 -0
  101. data/mail-2.9.1/lib/mail/parsers/content_location_parser.rl +82 -0
  102. data/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rb +525 -0
  103. data/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
  104. data/mail-2.9.1/lib/mail/parsers/content_type_parser.rb +1051 -0
  105. data/mail-2.9.1/lib/mail/parsers/content_type_parser.rl +94 -0
  106. data/mail-2.9.1/lib/mail/parsers/date_time_parser.rb +894 -0
  107. data/mail-2.9.1/lib/mail/parsers/date_time_parser.rl +73 -0
  108. data/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rb +3678 -0
  109. data/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rl +93 -0
  110. data/mail-2.9.1/lib/mail/parsers/message_ids_parser.rb +5164 -0
  111. data/mail-2.9.1/lib/mail/parsers/message_ids_parser.rl +97 -0
  112. data/mail-2.9.1/lib/mail/parsers/mime_version_parser.rb +516 -0
  113. data/mail-2.9.1/lib/mail/parsers/mime_version_parser.rl +72 -0
  114. data/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rb +887 -0
  115. data/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rl +94 -0
  116. data/mail-2.9.1/lib/mail/parsers/received_parser.rb +8785 -0
  117. data/mail-2.9.1/lib/mail/parsers/received_parser.rl +95 -0
  118. data/mail-2.9.1/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  119. data/mail-2.9.1/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  120. data/mail-2.9.1/lib/mail/parsers/rfc2045_mime.rl +16 -0
  121. data/mail-2.9.1/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  122. data/mail-2.9.1/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  123. data/mail-2.9.1/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  124. data/mail-2.9.1/lib/mail/parsers/rfc5322.rl +74 -0
  125. data/mail-2.9.1/lib/mail/parsers/rfc5322_address.rl +72 -0
  126. data/mail-2.9.1/lib/mail/parsers/rfc5322_date_time.rl +37 -0
  127. data/mail-2.9.1/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  128. data/mail-2.9.1/lib/mail/parsers.rb +13 -0
  129. data/mail-2.9.1/lib/mail/part.rb +119 -0
  130. data/mail-2.9.1/lib/mail/parts_list.rb +131 -0
  131. data/mail-2.9.1/lib/mail/smtp_envelope.rb +57 -0
  132. data/mail-2.9.1/lib/mail/utilities.rb +576 -0
  133. data/mail-2.9.1/lib/mail/values/unicode_tables.dat +0 -0
  134. data/mail-2.9.1/lib/mail/version.rb +17 -0
  135. data/mail-2.9.1/lib/mail/yaml.rb +30 -0
  136. data/mail-2.9.1/lib/mail.rb +65 -0
  137. data/nano-fast-tool.gemspec +12 -0
  138. metadata +177 -0
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/encodings/7bit'
4
+
5
+ module Mail
6
+ module Encodings
7
+ class QuotedPrintable < SevenBit
8
+ NAME='quoted-printable'
9
+
10
+ PRIORITY = 2
11
+
12
+ def self.can_encode?(enc)
13
+ EightBit.can_encode? enc
14
+ end
15
+
16
+ # Decode the string from Quoted-Printable. Cope with hard line breaks
17
+ # that were incorrectly encoded as hex instead of literal CRLF.
18
+ def self.decode(str)
19
+ ::Mail::Utilities.to_lf ::Mail::Utilities.to_crlf(str).gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack1("M*")
20
+ end
21
+
22
+ def self.encode(str)
23
+ ::Mail::Utilities.to_crlf [::Mail::Utilities.to_lf(str)].pack("M")
24
+ end
25
+
26
+ def self.cost(str)
27
+ # These bytes probably do not need encoding
28
+ c = str.count("\x9\xA\xD\x20-\x3C\x3E-\x7E")
29
+ # Everything else turns into =XX where XX is a
30
+ # two digit hex number (taking 3 bytes)
31
+ total = (str.bytesize - c)*3 + c
32
+ total.to_f/str.bytesize
33
+ end
34
+
35
+ # QP inserts newlines automatically and cannot violate the SMTP spec.
36
+ def self.compatible_input?(str)
37
+ true
38
+ end
39
+
40
+ private
41
+
42
+ Encodings.register(NAME, self)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Mail
4
+ module Encodings
5
+ class TransferEncoding
6
+ NAME = ''
7
+
8
+ PRIORITY = -1
9
+
10
+ # And encoding's superclass can always transport it since the
11
+ # class hierarchy is arranged e.g. Base64 < 7bit < 8bit < Binary.
12
+ def self.can_transport?(enc)
13
+ enc && enc <= self
14
+ end
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
+ def self.can_encode?(enc)
20
+ can_transport? enc
21
+ end
22
+
23
+ def self.cost(str)
24
+ raise "Unimplemented"
25
+ end
26
+
27
+ def self.compatible_input?(str)
28
+ true
29
+ end
30
+
31
+ def self.to_s
32
+ self::NAME
33
+ end
34
+
35
+ def self.negotiate(message_encoding, source_encoding, str, allowed_encodings = nil)
36
+ message_encoding = Encodings.get_encoding(message_encoding) || Encodings.get_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)
40
+ source_encoding
41
+ else
42
+ renegotiate(message_encoding, source_encoding, str, allowed_encodings)
43
+ end
44
+ end
45
+
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
52
+
53
+ lowest_cost(str, encodings)
54
+ end
55
+
56
+ def self.lowest_cost(str, encodings)
57
+ best = nil
58
+ best_cost = nil
59
+
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
71
+ end
72
+
73
+ best
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Mail
3
+ module Encodings
4
+ class UnixToUnix < TransferEncoding
5
+ NAME = "x-uuencode"
6
+
7
+ def self.decode(str)
8
+ str.sub(/\Abegin \d+ [^\n]*\n/, '').unpack1('u')
9
+ end
10
+
11
+ def self.encode(str)
12
+ [str].pack("u")
13
+ end
14
+
15
+ Encodings.register(NAME, self)
16
+ Encodings.register("uuencode", self)
17
+ Encodings.register("x-uue", self)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,314 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Mail
5
+ # Raised when attempting to decode an unknown encoding type
6
+ class UnknownEncodingType < StandardError #:nodoc:
7
+ end
8
+
9
+ module Encodings
10
+ include Mail::Constants
11
+ extend Mail::Utilities
12
+
13
+ @transfer_encodings = {}
14
+
15
+ # Register transfer encoding
16
+ #
17
+ # Example
18
+ #
19
+ # Encodings.register "base64", Mail::Encodings::Base64
20
+ def Encodings.register(name, cls)
21
+ @transfer_encodings[get_name(name)] = cls
22
+ end
23
+
24
+ # Is the encoding we want defined?
25
+ #
26
+ # Example:
27
+ #
28
+ # Encodings.defined?(:base64) #=> true
29
+ def Encodings.defined?(name)
30
+ @transfer_encodings.include? get_name(name)
31
+ end
32
+
33
+ # Gets a defined encoding type, QuotedPrintable or Base64 for now.
34
+ #
35
+ # Each encoding needs to be defined as a Mail::Encodings::ClassName for
36
+ # this to work, allows us to add other encodings in the future.
37
+ #
38
+ # Example:
39
+ #
40
+ # Encodings.get_encoding(:base64) #=> Mail::Encodings::Base64
41
+ def Encodings.get_encoding(name)
42
+ @transfer_encodings[get_name(name)]
43
+ end
44
+
45
+ def Encodings.get_all
46
+ @transfer_encodings.values
47
+ end
48
+
49
+ def Encodings.get_name(name)
50
+ underscoreize(name).downcase
51
+ end
52
+
53
+ def Encodings.transcode_charset(str, from_charset, to_charset = 'UTF-8')
54
+ if from_charset
55
+ Utilities.transcode_charset str, from_charset, to_charset
56
+ else
57
+ str
58
+ end
59
+ end
60
+
61
+ # Encodes a parameter value using URI Escaping, note the language field 'en' can
62
+ # be set using Mail::Configuration, like so:
63
+ #
64
+ # Mail.defaults do
65
+ # param_encode_language 'jp'
66
+ # end
67
+ #
68
+ # The character set used for encoding will be the encoding on the string passed in.
69
+ #
70
+ # Example:
71
+ #
72
+ # Mail::Encodings.param_encode("This is fun") #=> "us-ascii'en'This%20is%20fun"
73
+ def Encodings.param_encode(str)
74
+ case
75
+ when str.ascii_only? && TOKEN_UNSAFE.match?(str)
76
+ %Q{"#{str}"}
77
+ when str.ascii_only?
78
+ str
79
+ else
80
+ Utilities.param_encode(str)
81
+ end
82
+ end
83
+
84
+ # Decodes a parameter value using URI Escaping.
85
+ #
86
+ # Example:
87
+ #
88
+ # Mail::Encodings.param_decode("This%20is%20fun", 'us-ascii') #=> "This is fun"
89
+ #
90
+ # str = Mail::Encodings.param_decode("This%20is%20fun", 'iso-8559-1')
91
+ # str.encoding #=> 'ISO-8859-1' ## Only on Ruby 1.9
92
+ # str #=> "This is fun"
93
+ def Encodings.param_decode(str, encoding)
94
+ Utilities.param_decode(str, encoding)
95
+ end
96
+
97
+ # Decodes or encodes a string as needed for either Base64 or QP encoding types in
98
+ # the =?<encoding>?[QB]?<string>?=" format.
99
+ #
100
+ # The output type needs to be :decode to decode the input string or :encode to
101
+ # encode the input string. The character set used for encoding will be the
102
+ # encoding on the string passed in.
103
+ #
104
+ # On encoding, will only send out Base64 encoded strings.
105
+ def Encodings.decode_encode(str, output_type)
106
+ case
107
+ when output_type == :decode
108
+ Encodings.value_decode(str)
109
+ else
110
+ if str.ascii_only?
111
+ str
112
+ else
113
+ Encodings.b_value_encode(str, str.encoding)
114
+ end
115
+ end
116
+ end
117
+
118
+ # Decodes a given string as Base64 or Quoted Printable, depending on what
119
+ # type it is.
120
+ #
121
+ # String has to be of the format =?<encoding>?[QB]?<string>?=
122
+ def Encodings.value_decode(str)
123
+ # Optimization: If there's no encoded-words in the string, just return it
124
+ return str unless ENCODED_VALUE.match?(str)
125
+
126
+ lines = collapse_adjacent_encodings(str)
127
+
128
+ # Split on white-space boundaries with capture, so we capture the white-space as well
129
+ lines.each do |line|
130
+ line.gsub!(ENCODED_VALUE) do |string|
131
+ case $2
132
+ when *B_VALUES then b_value_decode(string)
133
+ when *Q_VALUES then q_value_decode(string)
134
+ end
135
+ end
136
+ end.join("")
137
+ end
138
+
139
+ # Takes an encoded string of the format =?<encoding>?[QB]?<string>?=
140
+ def Encodings.unquote_and_convert_to(str, to_encoding)
141
+ output = value_decode( str ).to_s # output is already converted to UTF-8
142
+
143
+ if 'utf8' == to_encoding.to_s.downcase.gsub("-", "")
144
+ output
145
+ elsif to_encoding
146
+ begin
147
+ output.encode(to_encoding)
148
+ rescue Errno::EINVAL
149
+ # the 'from' parameter specifies a charset other than what the text
150
+ # actually is...not much we can do in this case but just return the
151
+ # unconverted text.
152
+ #
153
+ # Ditto if either parameter represents an unknown charset, like
154
+ # X-UNKNOWN.
155
+ output
156
+ end
157
+ else
158
+ output
159
+ end
160
+ end
161
+
162
+ def Encodings.address_encode(address, charset = 'utf-8')
163
+ if address.is_a?(Array)
164
+ address.compact.map { |a| Encodings.address_encode(a, charset) }.join(", ")
165
+ elsif address
166
+ encode_non_usascii(address, charset)
167
+ end
168
+ end
169
+
170
+ def Encodings.encode_non_usascii(address, charset)
171
+ return address if address.ascii_only? or charset.nil?
172
+
173
+ # Encode all strings embedded inside of quotes
174
+ address = address.gsub(/("[^"]*[^\/]")/) { |s| Encodings.b_value_encode(unquote(s), charset) }
175
+
176
+ # Then loop through all remaining items and encode as needed
177
+ tokens = address.split(/\s/)
178
+
179
+ map_with_index(tokens) do |word, i|
180
+ if word.ascii_only?
181
+ word
182
+ else
183
+ previous_non_ascii = i>0 && tokens[i-1] && !tokens[i-1].ascii_only?
184
+ if previous_non_ascii #why are we adding an extra space here?
185
+ word = " #{word}"
186
+ end
187
+ Encodings.b_value_encode(word, charset)
188
+ end
189
+ end.join(' ')
190
+ end
191
+
192
+ # Encode a string with Base64 Encoding and returns it ready to be inserted
193
+ # as a value for a field, that is, in the =?<charset>?B?<string>?= format
194
+ #
195
+ # Example:
196
+ #
197
+ # Encodings.b_value_encode('This is あ string', 'UTF-8')
198
+ # #=> "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?="
199
+ def Encodings.b_value_encode(string, encoding = nil)
200
+ if string.to_s.ascii_only?
201
+ string
202
+ else
203
+ Encodings.each_base64_chunk_byterange(string, 60).map do |chunk|
204
+ str, encoding = Utilities.b_value_encode(chunk, encoding)
205
+ "=?#{encoding}?B?#{str.chomp}?="
206
+ end.join(" ")
207
+ end
208
+ end
209
+
210
+ # Encode a string with Quoted-Printable Encoding and returns it ready to be inserted
211
+ # as a value for a field, that is, in the =?<charset>?Q?<string>?= format
212
+ #
213
+ # Example:
214
+ #
215
+ # Encodings.q_value_encode('This is あ string', 'UTF-8')
216
+ # #=> "=?UTF-8?Q?This_is_=E3=81=82_string?="
217
+ def Encodings.q_value_encode(encoded_str, encoding = nil)
218
+ return encoded_str if encoded_str.to_s.ascii_only?
219
+ string, encoding = Utilities.q_value_encode(encoded_str, encoding)
220
+ string.gsub!("=\r\n", '') # We already have limited the string to the length we want
221
+ map_lines(string) do |str|
222
+ "=?#{encoding}?Q?#{str.chomp.gsub(/ /, '_')}?="
223
+ end.join(" ")
224
+ end
225
+
226
+ private
227
+
228
+ # Decodes a Base64 string from the "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=" format
229
+ #
230
+ # Example:
231
+ #
232
+ # Encodings.b_value_decode("=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=")
233
+ # #=> 'This is あ string'
234
+ def Encodings.b_value_decode(str)
235
+ Utilities.b_value_decode(str)
236
+ end
237
+
238
+ # Decodes a Quoted-Printable string from the "=?UTF-8?Q?This_is_=E3=81=82_string?=" format
239
+ #
240
+ # Example:
241
+ #
242
+ # Encodings.q_value_decode("=?UTF-8?Q?This_is_=E3=81=82_string?=")
243
+ # #=> 'This is あ string'
244
+ def Encodings.q_value_decode(str)
245
+ Utilities.q_value_decode(str)
246
+ end
247
+
248
+ # Gets the encoding type (Q or B) from the string.
249
+ def Encodings.value_encoding_from_string(str)
250
+ str[ENCODED_VALUE, 1]
251
+ end
252
+
253
+ # Split header line into proper encoded and unencoded parts.
254
+ #
255
+ # String has to be of the format =?<encoding>?[QB]?<string>?=
256
+ #
257
+ # Omit unencoded space after an encoded-word.
258
+ def Encodings.collapse_adjacent_encodings(str)
259
+ results = []
260
+ last_encoded = nil # Track whether to preserve or drop whitespace
261
+
262
+ lines = str.split(FULL_ENCODED_VALUE)
263
+ lines.each_slice(2) do |unencoded, encoded|
264
+ if last_encoded = encoded
265
+ if !Utilities.blank?(unencoded) || (!last_encoded && unencoded != EMPTY)
266
+ results << unencoded
267
+ end
268
+
269
+ results << encoded
270
+ else
271
+ results << unencoded
272
+ end
273
+ end
274
+
275
+ results
276
+ end
277
+
278
+ # Partition the string into bounded-size chunks without splitting
279
+ # multibyte characters.
280
+ def Encodings.each_base64_chunk_byterange(str, max_bytesize_per_base64_chunk, &block)
281
+ raise "size per chunk must be multiple of 4" if (max_bytesize_per_base64_chunk % 4).nonzero?
282
+
283
+ if block_given?
284
+ max_bytesize = ((3 * max_bytesize_per_base64_chunk) / 4.0).floor
285
+ each_chunk_byterange(str, max_bytesize, &block)
286
+ else
287
+ enum_for :each_base64_chunk_byterange, str, max_bytesize_per_base64_chunk
288
+ end
289
+ end
290
+
291
+ # Partition the string into bounded-size chunks without splitting
292
+ # multibyte characters.
293
+ def Encodings.each_chunk_byterange(str, max_bytesize_per_chunk)
294
+ return enum_for(:each_chunk_byterange, str, max_bytesize_per_chunk) unless block_given?
295
+
296
+ offset = 0
297
+ chunksize = 0
298
+
299
+ str.each_char do |chr|
300
+ charsize = chr.bytesize
301
+
302
+ if chunksize + charsize > max_bytesize_per_chunk
303
+ yield Utilities.string_byteslice(str, offset, chunksize)
304
+ offset += chunksize
305
+ chunksize = charsize
306
+ else
307
+ chunksize += charsize
308
+ end
309
+ end
310
+
311
+ yield Utilities.string_byteslice(str, offset, chunksize)
312
+ end
313
+ end
314
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ #
4
+ # = Mail Envelope
5
+ #
6
+ # The Envelope class provides a field for the first line in an
7
+ # mbox file, that looks like "From mikel@test.lindsaar.net DATETIME"
8
+ #
9
+ # This envelope class reads that line, and turns it into an
10
+ # Envelope.from and Envelope.date for your use.
11
+
12
+ module Mail
13
+ class Envelope < NamedStructuredField
14
+ NAME = 'Envelope-From'
15
+
16
+ def element
17
+ @element ||= Mail::EnvelopeFromElement.new(value)
18
+ end
19
+
20
+ def from
21
+ element.address
22
+ end
23
+
24
+ def date
25
+ element.date_time
26
+ end
27
+ end
28
+ end